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$