in the name of zero

April 26, 2007

0xf001’s 0xf001m3

hack the password!

features: a anti-libbfd, anti-disassembling, anti-debugging, and a bit of obfuscation ;)

have a lot of fun … ;}

0xf001

Difficulty: 5 - Professional problem to solve
Platform: Unix/linux etc.
Language: Assembler

get it here

as you’ll find out soon after starting,

1) the crackme is filled with anti-disassembly constructs.
2) along the way, there are lots and lots (and lots) or jump via ret/double rets. it’s simply just a matter of fixing/telling the disassembler the correct offset where to start disassembly (IDA in my case)
3) there is a short encrpytion thingy goin on
4) the crackme hides the details of setting up the parameters for a system call among the many jump via ret/double rets
5) patches an int 0x80 before calling it. patches it back after calling it.

example of jump via “ret” in the crackme

0x8048080		call loc_8048086	; put 0x08048085 to esp
0x8048085		db 0E9h			; garbage
0x8048086		pop edx			; edx = 0x08048085
0x8048087		add edx, 0Bh		; edx = 0x08048090
0x804808D		push edx		; on stack
0x804808E		retn			; jump to 0x08048090

“double ret”

0x080480E0		add edx, 0xe		; fix 2nd jump address
0x080480E6		push edx		; put on stack
0x080480E7		push 0x80480cc		; 1st jump address
0x080480EC		retn			; return once
0x080480CC		retn 			; return twice

we can basically grasp the pattern immediately after a few tries…. going further we reach a “sign of life” of some sort.. a lodsb instruction.

0x08048130		mov al, [+0x8048c90]
0x08048135		lodsb			; esi initially at  0x08048196

which will put the first byte at 0x08048196 (0xCC) to al, then increment esi. a few blocks further…

0x08048154		xor al, 0x58		; byte morph ...

…another series of ret/double rets… then we have

0x08048174		stosb			; initially at 0x08048196

eventually, a “loop”

0x08048193		loop +0xa0 (0x8048235)	; 0xa80 times

tell tale signs of decryption don’t you agree? so if we do the math, 0x08048196 + 0xa80 = 0x08048C16. what i want to achieve as of the moment is a copy of the decrpted block so that i can still follow ald’s debugging session in ida. we can take a memory dump of the crackme. i on the other hand chose to make a helper program[1] that will decrypt the encrypted block.

another set of jump via ret/double ret series…

we basically continue till we reach a shl eax, 1 instruction.

08048783                      D1E0                 shl eax, 1  

from the current value of eax = 0xd, the shift left by one bit will make eax = 0x1a (26 decimal) which happens to be the syscall number for sys_ptrace()

series of jump via ret again…

former value of ecx = 0x10 .. via shl cl, 0x3 becomes ecx = 0x80

0804893C                      C0E103               shl cl, 0x3 

further along the way, this instruction patches the byte pointed to by edx (0x08048A4E) with cl = 0x80 (which by the way, is also the linux interrupt vector)

880A                 mov byte [edx], cl 

still following the trail… we now reached the instruction at address 0x080489C4. which is a jz 0x08048653. if we follow this jump (in the disassembler), we’ll reach the dead end which is where the crackme will try returning to 0xf001. we don’t want our debugging session disrupted, so let’s skip that instruction. eventually, (after yet another series of jump via rets) we reach an int 0x80 instruction at 0x08048A4D. remember the mov byte [edx], cl instruction a while ago? the crackme patches this location at runtime in order for a ptrace() system call to resolve.

we can easily defeat this (ald in my case) by giving eax = 0 value.

going further we eventually encounter

08048AA7                      BA4E8A0408           mov edx, 0x8048a4e ; this will later be overwitten then restored...

…. more jump via rets …

08048AD7                      880A                 mov byte [edx], cl

so the crackme patches the int 0x80 byte (to cover its tracks). then after a helluva lot of nuisances….

0x08048826	or al, al	; the crackme tries to toggle the zero flag

and further down the listing…

0x08048853                      0F85FAFDFFFF         jne near +0xfffffdfa (0x8048653)

wait a minute! we’ve already seen this memory address once right? it’s the path leading to 0xf001! so let’s skip that instruction and we’ll safely reach the next set of surprises.

things get interesting starting at 0x080481B5. we encounter more and more of those jump via ret thingies along the way but at least now we now the pattern on how they work…

we encounter another int 0x80 patch so we know something’s gonna turn up soon. the details on how parameters are being setup is hidden among tons of repetitive jump via ret/double calls. don’t forget that the crackme also patches int 0x80 again after every call. we can also determine that address 0x080485bc is the address responsible for the flow of the crackme after every int 0x80 payload. i opted to simply check the registers (parameters) before every int 0x80 call.

ecx = 0x080481D5 (oxfoo1m3 started ;])
ecx = 0x0804820F (3nt4 p455w0rD:)

we now enter the fourth int 0x80 installment (0x0804835C). this time, instead of entering the usual routine (setup int 0x80) the crackme does an int 0x80 directly. checking the registers, we have:


eax = 0x00000003 ebx = 0x00000000 ecx = 0x08048223 edx = 0x0000000B

sys_read 0x0b characters from stdin and save to buffer at 0x08048223. i guess that brings us to the fifth phase… roughly like the one below.

at 0x080483e2, we see the mov esi, 0x08048223 instruction… and another interesting instruction at 0x08048412 (mov edi, 0x8048223).

08048472                      AC                   lodsb  ; load byte (esi) to al
0804849E                      30D0                 xor al, dl ; dl is strlen(input)
080484CB                      FEC2                 inc dl
08048582                      3A01                 cmp al, byte [ecx]    ; aha!

by virtue of common sense.. i made a keygen[2] immediately to test things out.

works like a charm.


~/oxfoo1m3 $ ./cracker
password is : fucktheduck
	
~/oxfoo1m3 $ ./oxfoo1m3
oxfoo1m3 started ;]
3nt4 p455w0rD:
fucktheduck
u made it!

thanks to 0xf001 for this wonderful crackme.

references:
[1] decrypt_foolme.c
[2] cracker.c

Get free blog up and running in minutes with Blogsome | Theme designs available here