Back from the Nuit du Hack 2013, we managed with depierre to put the hackgyver name on the 23th position (iirc). I was a little bit disapointed by the wargame (Seriously, prisedetete, 450 !?), but talks were nice, we met amazing people, and had fun :) Ok, enough about this, let's talk about crackmeimfamous.
The crackme
You can get it here.
Reversing
It's a i686 binary, with some crypto stuff. The strings command tells us it's using OpenSSL. I checked here that AES-related functions where real AES stuffs, and not some idiotic deception trickery.
Run it
I had to softlink some libraries to make it run.
ldd crackmeimfamous- softlink/renames libs
export LD_LIBRARY_PATH=$(pwd)
Anti-debug
Nothing amazing; the gdb_check function, uses the classic ptrace trick inside a fork.
Crypto
The main function calls the check one
push ebp
mov ebp,esp
sub esp,0x38
call 0x8048ae5 <gdb_check> ; anti-debug
test eax,eax
je 0x8048cd3 <check+39>
mov DWORD PTR [esp],0x8048e0e ; boo
call 0x80487e0 <puts@plt>
mov DWORD PTR [esp],0x1
call 0x80487b0 <exit@plt>
call 0x8048bf2 <get_pass> ; crypto computations
mov DWORD PTR [ebp-0xc],eax
mov DWORD PTR [esp],0x80491ae ; "Password : "
call 0x80487c0 <printf@plt>
mov eax,ds:0x804b060
mov DWORD PTR [esp+0x8],eax
mov DWORD PTR [esp+0x4],0x10
lea eax,[ebp-0x1c]
mov DWORD PTR [esp],eax
call 0x8048730 <fgets@plt>
mov eax,DWORD PTR [ebp-0xc]
lea edx,[ebp-0x1c]
mov DWORD PTR [esp],edx
call eax ; <- Weird call
leave
ret
The get_pass function is likely doing some AES decryption voodoo:
push ebp
mov ebp,esp
sub esp,0x168
mov DWORD PTR [ebp-0x138],0x3039
mov DWORD PTR [ebp-0x134],0xd431
mov DWORD PTR [ebp-0xc],0x8048e26 ; "b026324c6904b2a9", the AES key_data ?
mov DWORD PTR [ebp-0x10],0x10
lea eax,[ebp-0x130]
mov DWORD PTR [esp+0x10],eax
lea eax,[ebp-0xa4]
mov DWORD PTR [esp+0xc],eax
lea eax,[ebp-0x138]
mov DWORD PTR [esp+0x8],eax
mov eax,DWORD PTR [ebp-0x10]
mov DWORD PTR [esp+0x4],eax
mov eax,DWORD PTR [ebp-0xc]
mov DWORD PTR [esp],eax
call 0x804892c <aes_init>
test eax,eax
je 0x8048c58 <get_pass+102> ; aes_init failed :/
mov eax,0xffffffff
jmp 0x8048caa <get_pass+184>
mov DWORD PTR [ebp-0x14],0x8048e38 ; This is a large block of data
mov DWORD PTR [ebp-0x13c],0x375 ; Data block size ?
lea eax,[ebp-0x13c]
mov DWORD PTR [esp+0x8],eax
mov eax,DWORD PTR [ebp-0x14]
mov DWORD PTR [esp+0x4],eax
lea eax,[ebp-0x130]
mov DWORD PTR [esp],eax
call 0x8048a14 <aes_decrypt>
mov DWORD PTR [ebp-0x18],eax
lea eax,[ebp-0x130]
mov DWORD PTR [esp],eax
call 0x8048790 <EVP_CIPHER_CTX_cleanup@plt>
lea eax,[ebp-0xa4]
mov DWORD PTR [esp],eax
call 0x8048790 <EVP_CIPHER_CTX_cleanup@plt>
mov eax,DWORD PTR [ebp-0x18]
leave
ret
Looks like this function is decrypting from 0x8048e38 to 0x8048e38+0x375,
using a key/IV derived from b026324c6904b2a9.
First, I didn't saw that the function was decrypting a large block of data,
and though that it was only used to get the password to compare with our output.
I lost so much time looking for it!
Remember the weird call eax stuff? It jumps inside the decrypted block!
Dumping
Since I felt so stupid, I finished this crackme in a quick'n'dirty manner, I:
- Bypassed by hand calls to
check_gdb - Set a breakpoint on the
call eax - Dumped the decrypted data using
dump memory dirtydump 0x0804c209 0x0804c209+1024 > output.tmpin gdb - ran
stringson it
And we've got the flag:
strings output.tmp | grep - flag
2cd Flag : 26ab0db90d72e28ad0ba1e22ee510510
Yay!