Reverse Engineering
13
13
6
4
ffiishy (TBU)
1
Raw Diary
Description
Author: .effie
I put a digital sign on this diary ^-^
Initial Analysis
We are given a file:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Raw Diary]
└──╼ $file chall
chall: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=9edbed209686e8fd38cc522ae3f08453c9262498, for GNU/Linux 3.2.0, stripped
Code Analysis
Decompile using IDA:
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4; // bl
char v5; // [rsp+3h] [rbp-3Dh]
int i; // [rsp+4h] [rbp-3Ch]
int n; // [rsp+8h] [rbp-38h]
unsigned int seed; // [rsp+Ch] [rbp-34h]
FILE *stream; // [rsp+10h] [rbp-30h]
char *s; // [rsp+18h] [rbp-28h]
FILE *v11; // [rsp+20h] [rbp-20h]
const char *v12; // [rsp+28h] [rbp-18h]
stream = fopen("flag.txt", "r");
if ( stream )
{
fseek(stream, 0LL, 2);
n = ftell(stream);
fseek(stream, 0LL, 0);
s = (char *)malloc(n + 4);
if ( s )
{
fgets(s, n, stream);
fclose(stream);
seed = time(0LL);
srand(seed);
printf("%d\n", seed);
v11 = fopen("output.txt", "w");
if ( v11 )
{
v12 = (const char *)sub_1349();
if ( v12 )
{
fprintf(v11, "\n[%s %s]\n%s\n", "Mar 2 2025", "15:24:49", v12);
for ( i = 0; i < n; ++i )
{
v4 = s[i];
v5 = v4 ^ rand();
fputc(v5, v11);
}
fputc(10, v11);
fclose(v11);
return 0LL;
}
else
{
fwrite("i'm too tired for this.\n", 1uLL, 0x18uLL, stderr);
return 1LL;
}
}
else
{
perror("what's wrong with you? -_-\n");
return 1LL;
}
}
else
{
perror("aaaa! can't malloc D:\n");
return 1LL;
}
}
else
{
perror("eepy! flag.txt is GONE.\n");
return 1LL;
}
}
This code essentially opens 2 files, flag.txt and output.txt. Then it initiate a PRNG using the current time as a seed. It then encrypt the content if flag.txt using XOR against a randomly generated number. After that, it will output the encrypted flag to output.txt
Solve
To decrypt the flag, we first need to find out what seed is used when initiating the PRNG.
When we are using the same seed for some PRNG. The sequence of the generated random value will always be the same.
But when i try to decrypt using the exact timestamp given on the output.txt, it doesn't outputs a flag.
[Mar 2 2025 15:24:49]
So my instant thought is to bruteforce the timestamp, with the range of 10 minutes before and 10 minutes after. And we will get the flag.
from ctypes import CDLL
libr = CDLL("/lib/x86_64-linux-gnu/libc.so.6")
def decrypt(seed, flag_enc):
libr.srand(seed)
flag = b""
for byte in flag_enc:
flag += bytes([byte ^ (libr.rand() % 0x100)])
return flag
with open("output.txt", "rb") as f:
for i in range(68):
f.readline()
flag_enc = f.readline().strip()
seed = 1740929089
for s in range(seed - 600, seed + 601):
flag = decrypt(s, flag_enc)
if b"RAMADAN{" in flag:
print(f"Seed: {s}")
print(flag)
break
Flag: RAMADAN{1_60nn4_b3_m3}
Mencari PW
Description
Author: b4r
Mas bisa bantu aku buat login? Aku lupa passwordnya :(
Initial Analysis
We are given a file:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Mencari PW]
└──╼ $file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8485f6953c06d12b9865185ba3466fdbf9b4a65c, for GNU/Linux 2.6.32, stripped
If we try to run it, we will get this error:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Mencari PW]
└──╼ $./chall
[PYI-198843:ERROR] Failed to load Python shared library '/tmp/_MEIQpunxn/libpython3.13.so': dlopen: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.38' not found (required by /tmp/_MEIQpunxn/libpython3.13.so)
We identify that it is a PyInstaller executable:
Code Analysis
# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: chall.py
# Bytecode version: 3.13.0rc3 (3571)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)
import tkinter
import string
from tkinter import messagebox
import time
window = tkinter.Tk()
window.title('Login Form')
window.geometry('400x500')
window.configure(bg='#0d0d0d')
password = ['qswaefrdthy_gukojplzcxvbmn', 'pkolihu_jyftgrsedwaqmzbxvc', 'mlnkbjvhcgxfzdsapqowueyr_t', 'plokijuhygtfrdeswaqmnbvcxz', 'qswdefrgthyjukilopmnbzvcx_', 'qswaefrgthyjukilpom_znxbcv', 'zqwsedrftgyhuji_kolpxcvbnm', 'qaedwsrf_tgujyhikpomznxbcv', 'mxnzbcvqsplokwdij_efuhrgyt', 'plokmnzbxvcijuygtfrdeswa_q', 'plmoknijbuhvygctfxrdzeswaq', 'qazwsxedcrfvtgbyhnujmikol_', 'wqzsxedcrfvt_gbyhnujmikolp', 'qazwxedcrf_vtgbyhnplmokiju', 'okmplijnuhbygvtfcrdxewqaz_', 'ygvtfcrd_xeszqaplmoknijbuh', 'ijnkmpluhbygvtfc_rdxeszwqa', 'tyuioplkjhgfdsaqwezxcvb_nm', 'mkolpijnuhbygv_tfcrxeszwaq', 'hubijnmkoplygvtfcrdxeszwaq', 'swxedcr_fvtgbynujmikolpqaz', 'trqwyuioplkjhgfdsazxcvbn_m', 'klopmijn_ubygvtfcrdxeszaqw', 'bvnmczxlaksjdhfgp_qowiruty']
def login():
username = 'TCP1P'
entered_username = username_entry.get()
entered_password = password_entry.get()
if entered_username != username or len(entered_password) != len(password):
messagebox.showerror(title='Error', message='Invalid Login')
return None
frame = tkinter.Frame(bg='#0d0d0d')
login_label = tkinter.Label(frame, text=' Login ', bg='#0d0d0d', fg='#ff00ff', font=('Courier', 30, 'bold'))
username_label = tkinter.Label(frame, text='Username', bg='#0d0d0d', fg='#00ffcc', font=('Courier', 16))
username_entry = tkinter.Entry(frame, font=('Courier', 16), bg='#262626', fg='#00ffcc', insertbackground='#00ffcc', relief='flat')
password_label = tkinter.Label(frame, text='Password', bg='#0d0d0d', fg='#00ffcc', font=('Courier', 16))
password_entry = tkinter.Entry(frame, show='*', font=('Courier', 16), bg='#262626', fg='#00ffcc', insertbackground='#00ffcc', relief='flat')
login_button = tkinter.Button(frame, text='Login cik', bg='#ff00ff', fg='#0d0d0d', font=('Courier', 16), relief='flat', command=login)
login_label.pack(pady=40)
username_label.pack(anchor='w')
username_entry.pack(pady=10, ipadx=50, ipady=5)
password_label.pack(anchor='w')
password_entry.pack(pady=10, ipadx=50, ipady=5)
login_button.pack(pady=30)
frame.pack(expand=True)
window.mainloop()
There is no password checker logic, but when we look at the python bytecode:
There is some python bytecode, that is checking our input:
60 LOAD_GLOBAL 15 (NULL + zip)
62 LOAD_FAST 2 (entered_password)
64 LOAD_GLOBAL 8 (password)
66 CALL 2
68 GET_ITER
70 FOR_ITER 56 (to 118)
72 UNPACK_SEQUENCE 2
74 STORE_FAST_STORE_FAST 52 (char, pw_string)
76 LOAD_FAST_LOAD_FAST 52 (char, pw_string)
78 CONTAINS_OP 0 (in)
80 POP_JUMP_IF_TRUE 25 (to 98)
82 LOAD_FAST 3 (char)
84 LOAD_GLOBAL 16 (string)
86 LOAD_ATTR 18 (ascii_lowercase)
88 LOAD_CONST 5 ("_")
90 BINARY_OP 0 (+)
92 CONTAINS_OP 1 (not in)
94 POP_JUMP_IF_TRUE 2 (to 98)
96 JUMP_BACKWARD 35 (to 68)
98 LOAD_GLOBAL 10 (messagebox)
100 LOAD_ATTR 12 (showerror)
102 PUSH_NULL
104 LOAD_CONST 2 ("Error")
106 LOAD_CONST 6 ("masih salah atau coba tambahin underscore mas")
108 LOAD_CONST 4 (('title', 'message'))
110 CALL_KW 2
112 POP_TOP
114 POP_TOP
116 RETURN_CONST 0 (None)
118 END_FOR
120 POP_TOP
There are two conditions that it needs to pass:
This code checks if char is in pw_string:
76 LOAD_FAST 52 (char, pw_string)
78 CONTAINS_OP 0 (in)
80 POP_JUMP_IF_TRUE 25 (to 98)
This code checks if it is not in the range of [a-z_]
82 LOAD_FAST 3 (char)
84 LOAD_GLOBAL 16 (string)
86 LOAD_ATTR 18 (ascii_lowercase)
88 LOAD_CONST 5 ("_")
90 BINARY_OP 0 (+)
92 CONTAINS_OP 1 (not in)
94 POP_JUMP_IF_TRUE 2 (to 98)
96 JUMP_BACKWARD 35 (to 68)
So it will not jump this this condition:
98 LOAD_GLOBAL 10 (messagebox)
100 LOAD_ATTR 12 (showerror)
102 PUSH_NULL
104 LOAD_CONST 2 ("Error")
106 LOAD_CONST 6 ("masih salah atau coba tambahin underscore mas")
108 LOAD_CONST 4 (('title', 'message'))
110 CALL_KW 2
112 POP_TOP
So for every password list it needs to:
Is in the range of [a-z_]
For every char[i], is not in password[i]
Solve
Based on the two condition above, i write a script and get the flag:
alphabet = "abcdefghijklmnopqrstuvwxyz_"
pw_list = [
"qswaefrdthy_gukojplzcxvbmn",
"pkolihu_jyftgrsedwaqmzbxvc",
"mlnkbjvhcgxfzdsapqowueyr_t",
"plokijuhygtfrdeswaqmnbvcxz",
"qswdefrgthyjukilopmnbzvcx_",
"qswaefrgthyjukilpom_znxbcv",
"zqwsedrftgyhuji_kolpxcvbnm",
"qaedwsrf_tgujyhikpomznxbcv",
"mxnzbcvqsplokwdij_efuhrgyt",
"plokmnzbxvcijuygtfrdeswa_q",
"plmoknijbuhvygctfxrdzeswaq",
"qazwsxedcrfvtgbyhnujmikol_",
"wqzsxedcrfvt_gbyhnujmikolp",
"qazwxedcrf_vtgbyhnplmokiju",
"okmplijnuhbygvtfcrdxewqaz_",
"ygvtfcrd_xeszqaplmoknijbuh",
"ijnkmpluhbygvtfc_rdxeszwqa",
"tyuioplkjhgfdsaqwezxcvb_nm",
"mkolpijnuhbygv_tfcrxeszwaq",
"hubijnmkoplygvtfcrdxeszwaq",
"swxedcr_fvtgbynujmikolpqaz",
"trqwyuioplkjhgfdsazxcvbn_m",
"klopmijn_ubygvtfcrdxeszaqw",
"bvnmczxlaksjdhfgp_qowiruty",
]
result = []
for pw_string in pw_list:
for c in alphabet:
if c not in pw_string:
result.append(c)
break
final_pw = "".join(result)
print("RAMADHAN{" + final_pw + "}")
Flag: RAMADHAN{ini_adalah_password_hehe}
nomolog
Description
Author: .effie
D.I.D. i do that??
Initial Analysis
We are given two files:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $tree .
.
├── look
└── output.txt
1 directory, 2 files
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $file look
look: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2193600f0adbd69c95356ec4443a3052a47477ab, for GNU/Linux 3.2.0, with debug_info, not stripped
vinnie: 😭 g what are you doin in my room 💀💀
.effie: ====REDACTED====
.effie: dw i aint doin ya dirty if im paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_111312211l132112132110111312211k111312211_1113122110111312211r111312211_11131221151113122114111312211y111312211_1113122114111312211n111312211y1113122117111312211h31131122211n1113122116111312211_132123211o13211813211k111312211?111312211_111312211}
vinnie: what?? i cant understand this! anyway idk help >_<
Code Analysis
We open the file in IDA:
// local variable allocation has failed, the output may be wrong!
void __cdecl look::main()
{
__int64 v0; // rax
core::result::Result<(),std::io::error::Error> v1; // rax
__int64 v2; // rax
core::result::Result<usize,std::io::error::Error> v3; // rax OVERLAPPED
core::result::Result<usize,std::io::error::Error> v4; // rdi
__int64 v5; // rcx
_str v6; // rax
usize v7; // rdx
__int64 v8; // rax
core::result::Result<(),std::io::error::Error> v9; // rax
__int64 v10; // rax
core::result::Result<usize,std::io::error::Error> v11; // rax OVERLAPPED
core::result::Result<usize,std::io::error::Error> v12; // rdi
__int64 v13; // rcx
_str v14; // rax
_str v15; // rax
_str v16; // rdx
usize v17; // rax
_str v18; // [rsp+0h] [rbp-1A8h]
core::fmt::Arguments v19; // [rsp+10h] [rbp-198h] BYREF
__int64 v20; // [rsp+40h] [rbp-168h]
alloc::string::String self; // [rsp+48h] [rbp-160h] BYREF
__int64 v22; // [rsp+60h] [rbp-148h]
core::fmt::Arguments v23; // [rsp+68h] [rbp-140h] BYREF
__int64 v24; // [rsp+98h] [rbp-110h]
alloc::string::String v25; // [rsp+A0h] [rbp-108h] BYREF
__int64 v26; // [rsp+B8h] [rbp-F0h]
core::result::Result<usize,core::num::error::ParseIntError> v27; // [rsp+C0h] [rbp-E8h] BYREF
alloc::vec::Vec<alloc::string::String,alloc::alloc::Global> v28; // [rsp+D0h] [rbp-D8h] BYREF
core::fmt::Arguments v29; // [rsp+E8h] [rbp-C0h] BYREF
core::fmt::rt::Argument args[1]; // [rsp+118h] [rbp-90h] BYREF
alloc::string::String *v31; // [rsp+128h] [rbp-80h]
core::result::Result<(),core::fmt::Error> *(__cdecl *v32)(core::result::Result<(),core::fmt::Error> *__return_ptr __struct_ptr, alloc::string::String *, core::fmt::Formatter *); // [rsp+130h] [rbp-78h]
core::fmt::Arguments v33; // [rsp+138h] [rbp-70h] BYREF
u8 *data_ptr; // [rsp+168h] [rbp-40h]
usize v35; // [rsp+170h] [rbp-38h]
usize v36; // [rsp+178h] [rbp-30h]
alloc::string::String *v37; // [rsp+180h] [rbp-28h]
core::result::Result<(),core::fmt::Error> *(__cdecl *v38)(core::result::Result<(),core::fmt::Error> *__return_ptr __struct_ptr, alloc::string::String *, core::fmt::Formatter *); // [rsp+188h] [rbp-20h]
alloc::string::String *v39; // [rsp+190h] [rbp-18h]
core::result::Result<(),core::fmt::Error> *(__cdecl *v40)(core::result::Result<(),core::fmt::Error> *__return_ptr __struct_ptr, alloc::string::String *, core::fmt::Formatter *); // [rsp+198h] [rbp-10h]
alloc::string::String *v41; // [rsp+1A0h] [rbp-8h]
<core::fmt::Arguments>::new_const::<1>(&v19, (_str (*)[1])pieces);
std::io::stdio::_print();
std::io::stdio::stdout();
v20 = v0;
<std::io::stdio::Stdout as std::io::Write>::flush();
<core::result::Result<(), std::io::error::Error>>::expect(v1, (_str)__PAIR128__(17LL, "{_d0_m3_4_f4v0r_}"));
<alloc::string::String>::new(&self);
std::io::stdio::stdin();
v22 = v2;
std::io::stdio::Stdin::read_line();
v4 = v3;
*(_QWORD *)&v3.gap0[8] = "{_n0_c0n73x7_}";
v5 = 14LL;
<core::result::Result<usize, std::io::error::Error>>::expect(v4, *(_str *)((char *)&v3 + 8));
v6 = <alloc::string::String as core::ops::deref::Deref>::deref(&self);
v18.data_ptr = (u8 *)<str>::trim((_str *)v6.data_ptr, (_str)__PAIR128__(v6.length, v6.length));
v18.length = v7;
data_ptr = v18.data_ptr;
v35 = v7;
<core::fmt::Arguments>::new_const::<1>(&v23, (_str (*)[1])off_44B290);
std::io::stdio::_print();
std::io::stdio::stdout();
v24 = v8;
<std::io::stdio::Stdout as std::io::Write>::flush();
<core::result::Result<(), std::io::error::Error>>::expect(v9, (_str)__PAIR128__(14LL, "{_y34h_416h7_}"));
<alloc::string::String>::new(&v25);
std::io::stdio::stdin();
v26 = v10;
std::io::stdio::Stdin::read_line();
v12 = v11;
*(_QWORD *)&v11.gap0[8] = "{_4_P4P_P4P!_}";
v13 = 14LL;
<core::result::Result<usize, std::io::error::Error>>::expect(v12, *(_str *)((char *)&v11 + 8));
v14 = <alloc::string::String as core::ops::deref::Deref>::deref(&v25);
v15.data_ptr = (u8 *)<str>::trim((_str *)v14.data_ptr, (_str)__PAIR128__(v14.length, v14.length));
<str>::parse::<usize>(&v27, v15);
*(_QWORD *)v12.gap0 = &v27;
*(_QWORD *)&v12.gap0[8] = "{_74lk1n_0n_my_6uy5_}";
v16.data_ptr = (u8 *)21;
v16.length = (usize)&off_44B308;
v36 = <core::result::Result<usize, core::num::error::ParseIntError>>::expect(
(core::result::Result<usize,core::num::error::ParseIntError>)v12,
v16);
look::look_and_say(&v28, v18, v36 / 0x64);
v17 = <alloc::vec::Vec<alloc::string::String>>::len(&v28);
v39 = <alloc::vec::Vec<alloc::string::String> as core::ops::index::Index<usize>>::index(&v28, v17 - 1);
v40 = <alloc::string::String as core::fmt::Display>::fmt;
v41 = v39;
v37 = v39;
v38 = <alloc::string::String as core::fmt::Display>::fmt;
v31 = v39;
v32 = <alloc::string::String as core::fmt::Display>::fmt;
*(_QWORD *)args[0].ty.gap0 = v39;
*(_QWORD *)&args[0].ty.gap0[8] = <alloc::string::String as core::fmt::Display>::fmt;
<core::fmt::Arguments>::new_v1::<2, 1>(&v29, (_str (*)[2])off_44B338, (core::fmt::rt::Argument (*)[1])args);
std::io::stdio::_print();
<core::fmt::Arguments>::new_const::<1>(&v33, (_str (*)[1])off_44B3B0);
std::io::stdio::_print();
core::ptr::drop_in_place::<alloc::vec::Vec<alloc::string::String>>(&v28);
core::ptr::drop_in_place::<alloc::string::String>(&v25);
core::ptr::drop_in_place::<alloc::string::String>(&self);
}mm
This is a rust binary. I am not really familiar with Rust. (And i don't really understand how this code works :b). So i do output based analysis.
Solve
Analyzing Program Behavior
We are given an encrypted string:
111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_111312211l132112132110111312211k111312211_1113122110111312211r111312211_11131221151113122114111312211y111312211_1113122114111312211n111312211y1113122117111312211h31131122211n1113122116111312211_132123211o13211813211k111312211?111312211_111312211}
Our objective is to match our input with the encrypted string.
from pwn import *
from string import printable
elf = ELF('./look', checksec=False)
context.log_level = 'warn'
count = 0
for i in printable:
io = process(elf.path)
io.sendlineafter(b'.effie:', i.encode())
io.sendlineafter(b'vinnie:', b'699')
io.recvuntil(b': ')
print(i, io.recvline().decode().strip(), count)
io.close()
count += 1
io.interactive()
This will outputs all possible chars and this is what it will look like when encoded:
0 1113122110 0
1 312211 1
2 1113122112 2
3 1113122113 3
4 1113122114 4
5 1113122115 5
6 1113122116 6
7 1113122117 7
8 1113122118 8
9 1113122119 9
a 111312211a 10
b 111312211b 11
c 111312211c 12
d 111312211d 13
e 111312211e 14
f 111312211f 15
g 111312211g 16
h 111312211h 17
i 111312211i 18
j 111312211j 19
k 111312211k 20
l 111312211l 21
m 111312211m 22
n 111312211n 23
o 111312211o 24
p 111312211p 25
q 111312211q 26
r 111312211r 27
s 111312211s 28
t 111312211t 29
u 111312211u 30
v 111312211v 31
w 111312211w 32
x 111312211x 33
y 111312211y 34
z 111312211z 35
A 111312211A 36
B 111312211B 37
C 111312211C 38
D 111312211D 39
E 111312211E 40
F 111312211F 41
G 111312211G 42
H 111312211H 43
I 111312211I 44
J 111312211J 45
K 111312211K 46
L 111312211L 47
M 111312211M 48
N 111312211N 49
O 111312211O 50
P 111312211P 51
Q 111312211Q 52
R 111312211R 53
S 111312211S 54
T 111312211T 55
U 111312211U 56
V 111312211V 57
W 111312211W 58
X 111312211X 59
Y 111312211Y 60
Z 111312211Z 61
! 111312211! 62
" 111312211" 63
# 111312211# 64
$ 111312211$ 65
% 111312211% 66
& 111312211& 67
' 111312211' 68
( 111312211( 69
) 111312211) 70
* 111312211* 71
+ 111312211+ 72
, 111312211, 73
- 111312211- 74
. 111312211. 75
/ 111312211/ 76
: 111312211: 77
; 111312211; 78
< 111312211< 79
= 111312211= 80
> 111312211> 81
? 111312211? 82
@ 111312211@ 83
[ 111312211[ 84
\ 111312211\ 85
] 111312211] 86
^ 111312211^ 87
_ 111312211_ 88
` 111312211` 89
{ 111312211{ 90
| 111312211| 91
} 111312211} 92
~ 111312211~ 93
run with `RUST_BACKTRACE=1` environment variable to display a backtrace 94
run with `RUST_BACKTRACE=1` environment variable to display a backtrace 95
ParseIntError { kind: Empty } 96
run with `RUST_BACKTRACE=1` environment variable to display a backtrace 97
\x0b run with `RUST_BACKTRACE=1` environment variable to display a backtrace 98
\x0c run with `RUST_BACKTRACE=1` environment variable to display a backtrace 99
So for every character, it will have the prefix 111312211
then is followed by the character. 1 is a special case where it becomes 312211
Knowing that, we will first try to look which character have the prefix 111312211
:
We found some character, that is:
{__d0n7_lk_0r_54y_any76_k?}
While analyzing, we noticed some characters not following the prefix, so i thought that it was a multiple character:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: ss
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 13211213211s
vinnie: what?? i cant understand this! anyway idk help >_<
We found that it matches part of the encrypted flag:
The flag becomes:
{_ss_d0n7__0r_54y_any76_k?}
We continue:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: {_sshhhhhhh
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h
vinnie: what?? i cant understand this! anyway idk help >_<
{_sshhhhhhh_d0n7_lk_0r_54y_any76_k?}
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: {_sshhhhhhh_d0n7_
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_
vinnie: what?? i cant understand this! anyway idk help >_<
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: {_sshhhhhhh_d0n7_l00k_
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_111312211l132112132110111312211k111312211_
vinnie: what?? i cant understand this! anyway idk help >_<
{_sshhhhhhh_d0n7_l00k_0r_54y_any76_k?}
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: {_sshhhhhhh_d0n7_l00k_0r_54y_4ny7h1n6_
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_111312211l132112132110111312211k111312211_1113122110111312211r111312211_11131221151113122114111312211y111312211_1113122114111312211n111312211y1113122117111312211h31131122211n1113122116111312211_
vinnie: what?? i cant understand this! anyway idk help >_<
{_sshhhhhhh_d0n7_l00k_0r_54y_4ny7h1n6_k?}
You get the idea. After some trial and error, we will get the correct flag:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/nomolog/wu]
└──╼ $./look
vinnie: 😭 g what are you doin in my room 💀💀
.effie: {_sshhhhhhh_d0n7_l00k_0r_54y_4ny7h1n6_oookkkkkkkk?_}
.effie: dw i aint doin ya dirty if i paid first ;>
vinnie: yeah aight here some $699
.effie: 111312211{111312211_13211213211s13211713211h111312211_111312211d1113122110111312211n1113122117111312211_111312211l132112132110111312211k111312211_1113122110111312211r111312211_11131221151113122114111312211y111312211_1113122114111312211n111312211y1113122117111312211h31131122211n1113122116111312211_132123211o13211813211k111312211?111312211_111312211}
vinnie: what?? i cant understand this! anyway idk help >_<
When submitted to the platform, the flag doesn't use the flag format so...
Flag: {_sshhhhhhh_d0n7_l00k_0r_54y_4ny7h1n6_oookkkkkkkk?_}
Gacor
Description
Author: .effie
i did not have gaming relation with that balatro
Initial Analysis
We are given 3 files:
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Gacor]
└──╼ $tree -a .
.
├── chall
├── .effie
└── output.txt
1 directory, 4 files
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Gacor/wu]
└──╼ $file chall
chall: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6a88d64b2e0eb767a6445a6020f127dc25c412b0, for GNU/Linux 3.2.0, stripped
(SO35<?BT,W24IRL4=JL<55E"24EVN,/;68WYS8CW8H8?NAMSPSUYHJKQHQLUIJUTOVSTVRSTUVWVYX
14:55:42 ! effie ~thedaa@user/effie has joined #gamabargabukber
14:55:42 effie heyy, anyone wanna play poker? :p
[#gamabargabukber]
14:55:42 effie okay, whatever! here's the deck!! ;)
Black 6 Clubs
Black 6 Clubs
Red 6 Clubs
Red 7 Clubs
Black 7 Clubs
Black 8 Clubs
Red 10 Clubs
Red Jack Clubs
Red King Clubs
Red Hero Clubs
Black Hero Clubs
Black Hero Clubs
Red Hero Clubs
Red Hero Clubs
Black Hero Clubs
Black Hacker Clubs
Red Hacker Clubs
Black Hacker Clubs
Black Hacker Clubs
Red Queen Clubs
Black Queen Clubs
Red Queen Clubs
Black Queen Clubs
Red Queen Clubs
Red 4 Diamonds
Red 6 Diamonds
Black 6 Diamonds
Red 6 Diamonds
Black 6 Diamonds
Red 6 Diamonds
Red 7 Diamonds
Black 10 Diamonds
Red Jack Diamonds
Black Jack Diamonds
Red King Diamonds
Red King Diamonds
Red King Diamonds
Red King Diamonds
Black King Diamonds
Red Hero Diamonds
Red Hacker Diamonds
Red Hacker Diamonds
Red Hacker Diamonds
Black Queen Diamonds
Red Queen Diamonds
Red Queen Diamonds
Black Queen Diamonds
Black 3 Hearts
Black 4 Hearts
Black 5 Hearts
Black 5 Hearts
Black 6 Hearts
Black 6 Hearts
Black 7 Hearts
Black 8 Hearts
Black 9 Hearts
Black Jack Hearts
Black Jack Hearts
Black Jack Hearts
Red King Hearts
Black King Hearts
Black King Hearts
Black King Hearts
Black Hero Hearts
Red Hero Hearts
Black Hero Hearts
Red Hero Hearts
Black Hacker Hearts
Black 3 Spades
Black 5 Spades
Red 5 Spades
Black 6 Spades
Red 6 Spades
Black 7 Spades
Red 9 Spades
Black 10 Spades
Black 10 Spades
Black Jack Spades
Black Jack Spades
Black Jack Spades
Red King Spades
Black King Spades
Red King Spades
Black King Spades
Red King Spades
Black King Spades
Black Hero Spades
Red Hero Spades
Black Hacker Spades
Black Hacker Spades
[#gamabargabukber]
14:55:42 ! connection error! disconnected from #gamabargabukber
Code Analysis
We decompile in IDA:
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4; // al
int v5; // [rsp+4h] [rbp-23Ch]
int i; // [rsp+8h] [rbp-238h]
int j; // [rsp+Ch] [rbp-234h]
time_t timer; // [rsp+18h] [rbp-228h] BYREF
char v9[256]; // [rsp+20h] [rbp-220h] BYREF
char s[264]; // [rsp+120h] [rbp-120h] BYREF
unsigned __int64 v11; // [rsp+228h] [rbp-18h]
v11 = __readfsqword(0x28u);
timer = time(0LL);
qword_4050 = (__int64)localtime(&timer);
printf(
"%d:%d:%d ! effie ~thedaa@user/effie has joined #gamabargabukber\n",
*(_DWORD *)(qword_4050 + 8),
*(_DWORD *)(qword_4050 + 4),
*(_DWORD *)qword_4050);
printf(
"%d:%d:%d effie heyy, anyone wanna play poker? :p\n",
*(_DWORD *)(qword_4050 + 8),
*(_DWORD *)(qword_4050 + 4),
*(_DWORD *)qword_4050);
printf("[#gamabargabukber] ");
if ( fgets(s, 256, stdin) )
{
v5 = strlen(s);
if ( v5 > 0 && s[v5 - 1] == 10 )
s[--v5] = 0;
for ( i = 0; i < v5; ++i )
{
if ( s[i] < 0 )
{
printf(
"%d:%d:%d effie HEH what did you just said??? D:\n",
*(_DWORD *)(qword_4050 + 8),
*(_DWORD *)(qword_4050 + 4),
*(_DWORD *)qword_4050);
sub_1705();
return 1LL;
}
if ( (i & 1) != 0 )
v4 = -1;
else
v4 = 1;
v9[i] = sub_12E9((unsigned int)(char)(s[i] + (i % 12 + 1) / 2 * v4));
}
sub_13F5(v9, (unsigned int)v5);
printf(
"\n%d:%d:%d effie okay, whatever! here's the deck!! ;)\n",
*(_DWORD *)(qword_4050 + 8),
*(_DWORD *)(qword_4050 + 4),
*(_DWORD *)qword_4050);
for ( j = 0; j < v5; ++j )
sub_1555(&v9[j]);
puts("[#gamabargabukber] ");
sub_1705();
return 1LL;
}
else
{
fwrite("you don't wanna play?? >:/\n", 1uLL, 0x1BuLL, stderr);
return 1LL;
}
}
Solve
ffiishy (TBU)
Description
Author: f4r4w4y
Foreign Function Interface is FFIishy (or ffiilthy?)
Initial Analysis
TBU
Code Analysis
TBU
Solve
TBU
Last updated