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

April 5, 2007

virtuals

so i’m back with more of the shit that is C++ learning. i’ve gotten the hang of typing “cout” now instead of “printf” but more about this some other time. recently, i’m learning about virtual functions and i have this as an example:

class animal {
        public:
                void normal() { }
                virtual void normvirtual() { }
                virtual void purevirtual() = 0;
};
	
class sheep : public animal {
        public:
                void normvirtual() {
                        cout<<"sheep from normvirtual"<<endl;
                }    
	
                void purevirtual() {
                        cout<<"sheep from purevirtual"<<endl;
                }
};

again, using IDA and objdump …

 sheep   judy;
	
 8048803:       8d 45 e8                lea    eax,[ebp-24]
 8048806:       50                      push   eax
 8048807:       e8 8a 00 00 00          call   8048896 <sheep::sheep()>

nothing much happening here. the usual thing. a *this pointer being passed to a default constructor as a hidden argument.

08048896 <sheep::sheep()>:
 8048896:       55                      push   ebp		; save current stack frame
 8048897:       89 e5                   mov    ebp,esp		; new stack frame
 8048899:       83 ec 08                sub    esp,0x8		; space
 804889c:       83 ec 0c                sub    esp,0xc		; space
 804889f:       ff 75 08                push   DWORD PTR [ebp+8]		; our *this pointer
 80488a2:       e8 4d 00 00 00          call   80488f4 <animal::animal()>	; call animal constructor
 80488a7:       83 c4 10                add    esp,0x10				; cleanup
 80488aa:       8b 45 08                mov    eax,DWORD PTR [ebp+8]		; dereference
 80488ad:       c7 00 80 8a 04 08       mov    DWORD PTR [eax],0x8048a80	; see below...
 80488b3:       c9                      leave  			; epilog
 80488b4:       c3                      ret    			; return to callee
 80488b5:       90                      nop    			; byte pad (no operation)

so what does mov DWORD PTR [eax],0x8048a80 do? following the memory address in ida gives me an array of sheep class functions. objdump tells me that this block is called a “vtable” for my sheep class. 0x8048a80 is prolly what they call the “VPTR” pointer.

and then i called the get_kind() function.

 get_kind(judy);
	
 8048812:       8d 45 e8                lea    eax,[ebp-24]
 8048815:       50                      push   eax
 8048816:       e8 9b 00 00 00          call   80488b6 <get_kind(animal&)>

i learned from prior readings about “upcasting” and how a derived class object can be assigned to base class object. and this is how i interpreted things…

inline void get_kind(animal &a)
{
	a.normal();
	a.normvirtual();
	a.purevirtual();
}   
	
080488b6 <get_kind(animal&)>:
 80488b6:       55                      push   ebp
 80488b7:       89 e5                   mov    ebp,esp			; prolog
 80488b9:       83 ec 08                sub    esp,0x8
 80488bc:       83 ec 0c                sub    esp,0xc			; spaces
 80488bf:       ff 75 08                push   DWORD PTR [ebp+8]		; object as hidden argument
 80488c2:       e8 3b 00 00 00          call   8048902 <animal::normal()> 	; call the animal::normal() method
 80488c7:       83 c4 10                add    esp,0x10			; cleanup
 80488ca:       83 ec 0c                sub    esp,0xc			; space
	
 80488cd:       8b 45 08                mov    eax,DWORD PTR [ebp+8]	; *this pointer (VPTR)
 80488d0:       8b 00                   mov    eax,DWORD PTR [eax]	; dereference
 80488d2:       ff 75 08                push   DWORD PTR [ebp+8]	; pass object again as hidden argument
 80488d5:       8b 00                   mov    eax,DWORD PTR [eax]	; derefence again
 80488d7:       ff d0                   call   eax			; call the first virtual function
 80488d9:       83 c4 10                add    esp,0x10			; cleanup
 80488dc:       83 ec 0c                sub    esp,0xc			; space
	
 80488df:       8b 45 08                mov    eax,DWORD PTR [ebp+8]	; *this pointer (VPTR)
 80488e2:       8b 00                   mov    eax,DWORD PTR [eax]	; dereference
 80488e4:       83 c0 04                add    eax,0x4			; move to next function in array of funtions
 80488e7:       ff 75 08                push   DWORD PTR [ebp+8]	; pass object as hidden argument
 80488ea:       8b 00                   mov    eax,DWORD PTR [eax]	; dereference
 80488ec:       ff d0                   call   eax			; call second virtual function
	
 80488ee:       83 c4 10                add    esp,0x10			; cleanup
 80488f1:       c9                      leave  				; epilog
 80488f2:       c3                      ret    				; return to callee
 80488f3:       90                      nop  				; byte pad (no operation)

i wonder if i got the above things right? dynamic binding entails an additional overhead of locating and assigning the correct memory address for a particular function call to resolve. the whole thing is somehow similar to ELF PLT.GOT fixup (executable and linkable format procedure linkage table global offset table) except that addresses are always being referenced from the VPTR whenever a virtual call will be made.

also, there is a subtle difference between a normal virtual and a pure virtual function. from the looks of things, the pure virtual function takes up no space. in fact, i didn’t even see any single declartion of animal::purevirtual() anywhere on the dissassembly.

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