Wednesday, April 29, 2015

CONFidence DS CTF Teaser 2015 - So Easy - Reverse Engineering

We were given a 32 bit ELF which validates the flag. main function reads user input, converts lower case to upper case, upper case to lower case, then compares with string dRGNs{tHISwASsOsIMPLE}. But this is not the flag, there is something else happening. Lets check the .init_array

gdb-peda$ maintenance info sections

 [16]     0x8048d2c->0x8049120 at 0x00000d2c: .eh_frame ALLOC LOAD READONLY DATA HAS_CONTENTS
 [17]     0x804af04->0x804af0c at 0x00001f04: .init_array ALLOC LOAD DATA HAS_CONTENTS
 [18]     0x804af0c->0x804af10 at 0x00001f0c: .fini_array ALLOC LOAD DATA HAS_CONTENTS
 [19]     0x804af10->0x804af14 at 0x00001f10: .jcr ALLOC LOAD DATA HAS_CONTENTS
 [20]     0x804af14->0x804affc at 0x00001f14: .dynamic ALLOC LOAD DATA HAS_CONTENTS

gdb-peda$ x/4x 0x804af04
0x804af04: 0x080488be 0x08048570 0x08048550 0x00000000

0x080488be is priority constructor, which does some operation before main is executed. Below are the operations of the constructor

[*] Overwrite GOT entry of printf with address of function calling strlen
[*] Call calloc(32, 4)
[*] Then registers a series of destructors using ___cxa_atexit
[*] First destructor registered is the key validation routine, followed by a series of destructor to write a single DWORD to the calloc memory
.text:080488DE                 mov     [ebp+plt_printf], 8048412h
.text:080488E5                 mov     eax, [ebp+plt_printf]
.text:080488E8                 mov     eax, [eax]
.text:080488EA                 mov     [ebp+addr_printf], eax
.text:080488ED                 mov     eax, [ebp+addr_printf]
.text:080488F0                 mov     dword ptr [eax], offset strlen_w ; overwrite with strlen
.text:080488F6                 mov     dword ptr [esp+4], 4 ; size
.text:080488FE                 mov     dword ptr [esp], 32 ; nmemb
.text:08048905                 call    _calloc
.text:0804890A                 mov     ds:calloc_address, eax
.text:0804890F                 mov     dword ptr [esp], offset check_key
.text:08048916                 call    register_destructor
.text:0804891B                 mov     dword ptr [esp], offset a
.text:08048922                 call    register_destructor
.text:08048927                 mov     dword ptr [esp], offset b
Then the program goes into main, reads and modifies user input as mentioned earlier. Later, __run_exit_handlers executes the destructors in the reverse order. Finally, check_key validates the key.
gdb-peda$ break *0x000000000804873C
Breakpoint 1 at 0x804873c

gdb-peda$ heap used
Used chunks of memory on heap
     0: 0x0804c008 -> 0x0804c08f      136 bytes uncategorized::136 bytes |64 00 00 00 52 00 00 00 47 00 00 00 4e 00 00 00 73 00 00 00 7b 00 00 00 6e 00 00 00 4f 00 00 00 |d...R...G...N...s...{...n...O...|
User supplied flag is is case converted and compared with the bytes found above. So flag for the challenge is DrgnS{NotEvenWarmedUp}

No comments :

Post a Comment