simple ctf
find the flag!! flag starts with CTF_ warning: it doesnt strip ‘\n’ from the end of your input
- Category: rev
- Challenge author: slice
- Challenge link: crackmes.one
Solution:
1. Run the binary
$ ./simple_ctf
D0 50M3 H4CK3r r3V
test
7rY 4641N
We can try with ltrace to check the strcmp value
ltrace ./simple_ctf
puts("D0 50M3 H4CK3r r3V"D0 50M3 H4CK3r r3V) = 19
read(0test, "test\n", 15) = 5
strncmp("test\n", "CTF_sillycat", 15) = 49
puts("7rY 4641N"7rY 4641N) = 10
+++ exited (status 0) +++
So the correct string is CTF_sillycat
however the input contain \n
which is newline character, so the binary doesn’t remove.
By right, in the code should have strtok
to remove newline character. Like this:
strtok(input, "\n");
2. Disassemble the binary with IDA
After decompiling the binary to view the C pseudocode, we can head to the main function:
puts("D0 50M3 H4CK3r r3V");
read(0, buf, 0xFuLL);
if ( !strncmp(buf, valid_ctf, 0xFuLL) )
{
v10 = 0xD8CD84D3C5CAD1D0LL;
*(_DWORD *)v11 = -757609084;
*(_QWORD *)&v11[3] = 0x84D8C5CCD884D8D2LL;
v12 = 0x6EC9D0D4D1CDD7LL;
for ( size = 1LL; v11[size - 8]; ++size )
;
v6 = (const char *)malloc(size);
for ( i = 0LL; i != size; ++i )
v6[i] = v11[i - 8] - 100;
v6[size + 1] = 0;
printf("%s", v6);
}
This part of the code receive the input and compare it, we can use gdb debugger the remove the newline character
3. GDB remove newline character
At this part, s1 (RDI): 0x7fffffffe411
is the address of the first string, "CTF_sillycat\n"
, which includes a newline at the end but s2: 0x555555556008
is for address of the second string , "CTF_sillycat"
, which doesn’t include a newline.
To remove it: set *((char*)0x7fffffffe41d) = 0
4. Going back the decompiler
Notice another function compare_hashes
, making a comparison. If true, returns Y4Y U D1D 17
, or else 7rY 4641N
ctfhash(buf, v8, 15LL);
if ( (unsigned int)compare_hashes(v7, v8, 15LL) )
puts("Y4Y U D1D 17");
else
puts("7rY 4641N");
return 0;
}
This is the assembly of it:
lea rcx, [rbp+var_80]
lea rax, [rbp+buf]
mov edx, 0Fh
mov rsi, rcx
mov rdi, rax
call ctfhash
lea rcx, [rbp+var_80]
lea rax, [rbp+var_C0]
mov edx, 0Fh
mov rsi, rcx
mov rdi, rax
call compare_hashes
test eax, eax ; "set breakpoint and set eax to another value than 0"
jz short loc_14C3
lea rax, aY4yUD1d17 ; "Y4Y U D1D 17"
mov rdi, rax ; s
call _puts
jmp short loc_14D2 ; "7rY 4641N"
5. Using gdb to modify the value of eax to other value to 0
Here it how:
b *0x5555555554ae
c
info registers
set $eax=1
c
The full gdb process:
info functions
b main
r
b *0x555555555337
c
ni
ni
x/16b *0x7fffffffe411
x/s *0x7fffffffe411
x/s 0x7fffffffe411
x/16b 0x7fffffffe411
set *((char*)0x7fffffffe41e) = 0
set *((char*)0x7fffffffe41f) = 0
x/16b 0x7fffffffe411
set *((char*)0x7fffffffe41d) = 0
x/16b 0x7fffffffe411
set *((char*)0x7fffffffe41e) = 0
x/16b 0x7fffffffe411
context
b *0x5555555554ae
c
info registers
set $eax=1
info registers
ni
c
exit