====== Reverse 3 ======
Executable : https://repo.zenk-security.com/hackingweek2014_ctf/crackme-03
$ file crackme-03
crackme-03: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.32, dynamically linked (uses shared libs), stripped
Le crackme 3 est un ELF 32 bits.
Dans celui-ci, la fonction principale se compose de plusieurs boucles de déchiffrement de code et d'un peu d'obfuscation.
LOAD:080484DA push offset aEnterPassword ; "Enter password:\n"
LOAD:080484DF call printf_0
LOAD:080484E4 mov esp, ebp
LOAD:080484E6 mov ebp, esp
LOAD:080484E8 sub esp, 0Ch
LOAD:080484EB and esp, 0FFFFFFF0h
LOAD:080484EE add esp, 0Ch
LOAD:080484F1 push 9
LOAD:080484F3 push offset mypasswd
LOAD:080484F8 push 0
LOAD:080484FA call read_0
LOAD:080484FF mov esp, ebp
LOAD:08048501 mov byte ptr [eax+8048488h], 0
LOAD:08048508 mov ecx, 0C46981Dh
LOAD:0804850D mov esi, ds:dword_8049D32
LOAD:08048513 sub ecx, esi
LOAD:08048515 mov ds:dword_8049D6E, ebp
LOAD:0804851B sub ebp, 2EC33D4Eh
LOAD:08048521 mov ebp, ds:dword_8049D6E
LOAD:08048527 mov ds:dword_8049D6E, 180F301h
LOAD:08048531 add ecx, ds:dword_8049E0A
LOAD:08048537 mov edi, 7Dh
LOAD:0804853C
LOAD:0804853C loc_804853C: ; CODE XREF: LOAD:080485A9j
LOAD:0804853C mov ebx, [ecx]
LOAD:0804853E add ebx, 0A67D0AEEh
LOAD:08048544 mov ds:dword_8049D58+2, esi
LOAD:0804854A mov ds:dword_8049E56, esi
LOAD:08048550 mov ds:dword_8049E56, 2868941h
LOAD:0804855A mov esi, ds:dword_8049D58+2
LOAD:08048560 mov ds:dword_8049D58+2, 53020D9h
LOAD:0804856A mov edx, 6A62559h
LOAD:0804856F sub ebx, 0A67D0AEEh
LOAD:08048575 sub ebx, 115C0CABh
LOAD:0804857B mov ds:dword_8049DAE, esi
LOAD:08048581 add esi, 0F34126C9h
LOAD:08048587 mov esi, ds:dword_8049DAE
LOAD:0804858D
LOAD:0804858D loc_804858D: ; CODE XREF: LOAD:080485ABj
LOAD:0804858D mov ds:dword_8049DAE, 3EDB4FAh
LOAD:08048597 mov [ecx], ebx
LOAD:08048599 mov ebp, 4
LOAD:0804859E add ecx, ebp
LOAD:080485A0 sub edi, 1
LOAD:080485A6 cmp edi, 0
LOAD:080485A9 jnz short loc_804853C
L'idéal est encore une fois d'utiliser gdb pour laisser le programme s'auto-déchiffrer. La condition d'arrêt pourrait être la lecture de notre password.
Pour cela, on va breaker une première fois après le read de notre password, et placer un watchpoint sur la zone mémoire dans laquelle il a été écrit.
$ gdb ./crackme-03
gdb$ b *0x080484ff
Breakpoint 1 at 0x80484ff
gdb$ r
Starting program: /home/fab/Downloads/crackme-03
Enter password:
AAAA
--------------------------------------------------------------------------[regs]
EAX: 0x00000005 EBX: 0xF7FA1FF4 ECX: 0x08048489 EDX: 0x00000009 o d I t s z a p C
ESI: 0x00000000 EDI: 0x00000000 EBP: 0xFFFFCD2C ESP: 0xFFFFCD20 EIP: 0x080484FF
CS: 0023 DS: 002B ES: 002B FS: 0000 GS: 0063 SS: 002B
--------------------------------------------------------------------------[code]
=> 0x80484ff: mov esp,ebp
0x8048501: mov BYTE PTR [eax+0x8048488],0x0
0x8048508: mov ecx,0xc46981d
0x804850d: mov esi,DWORD PTR ds:0x8049d32
0x8048513: sub ecx,esi
0x8048515: mov DWORD PTR ds:0x8049d6e,ebp
0x804851b: sub ebp,0x2ec33d4e
0x8048521: mov ebp,DWORD PTR ds:0x8049d6e
--------------------------------------------------------------------------------
Breakpoint 1, 0x080484ff in ?? ()
gdb$ rwatch *(0x08048489)
Hardware read watchpoint 2: *(0x08048489)
gdb$ c
Continuing.
On break plus loin à la lecture de notre password. En regardant le code un peu avant, on voit une simple comparaison de chaines :
Hardware read watchpoint 2: *(0x08048489)
Value = 0x41414141
0x08049c89 in ?? ()
gdb$ x/8i $eip-11
0x8049c78: mov edi,0x8049cde
0x8049c7d: mov esi,0x8048489
0x8049c82: mov ecx,0x9
0x8049c87: repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi]
=> 0x8049c89: jne 0x8049c92
0x8049c8b: call 0x8049ca9
0x8049c90: jmp 0x8049c99
0x8049c92: call 0x8049cc3
gdb$ x/1s 0x8049cde
0x8049cde: "YGL83WrU"
$ ./crackme-03
Enter password:
YGL83WrU
sh-4.2$