codezen.fr code hacking, zen coding

4Mar/12Off

Insomni’hack 2012 reverse_me.bin Write-up

We have a binary

$ file reverse_me.bin
reverse_me.bin.back: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, corrupted section header size

$ readelf -l reverse_me.bin

Elf file type is EXEC (Executable file)
Entry point 0x8048054
There are 1 program headers, starting at offset 52

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x00344 0x00344 RWE 0x1000

$ ./reverse_me.bin
Get the flag

Yeah, let's get the flag...

$ strace ./reverse_me.bin
execve("./reverse_me.bin", ["./reverse_me.bin"], [/* 17 vars */]) = 0
ptrace(PTRACE_TRACEME, 0, 0, 0) = -1 EPERM (Operation not permitted)
write(1, "no gdb down there buddy...\n", 27no gdb down there buddy...
) = 27
_exit(0) = ?

The ELF header has been heavily modified and we have a hard time setting a breakpoint on the Entry Point... some code is run before at start that detect gdb (ptrace) and exits..

$ gdb reverse_me.bin
gdb$ break *0x8048054
Breakpoint 1 at 0x8048054
gdb$ run
no gdb down there buddy...

Program exited normally.

Catching to the rescue.. ptrace is a function but also, ultimately, a syscall

gdb$ catch syscall
Catchpoint 1 (any syscall)
gdb$ run
--------------------------------------------------------------------------[regs]
EAX: 0xFFFFFFDA EBX: 0x00000000 ECX: 0x00000000 EDX: 0x00000000 o d I t s Z a P c
ESI: 0x00000000 EDI: 0xBFFFF80C EBP: 0x0AE8DB34 ESP: 0xBFFFF80C EIP: 0x08048187
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0000 SS: 007B
--------------------------------------------------------------------------[code]
0x8048187: cmp eax,0x0
0x804818a: jne 0x80481fb
0x804818c: push 0x4
0x804818e: pop eax
0x804818f: cdq
0x8048190: xor ebx,ebx
0x8048192: inc ebx
0x8048193: push 0xa
--------------------------------------------------------------------------------

Catchpoint 1 (call to syscall 'ptrace'), 0x08048187 in ?? ()
gdb$ conti
--------------------------------------------------------------------------[regs]
EAX: 0xFFFFFFFF EBX: 0x00000000 ECX: 0x00000000 EDX: 0x00000000 o d I t s Z a P c
ESI: 0x00000000 EDI: 0xBFFFF80C EBP: 0x0AE8DB34 ESP: 0xBFFFF80C EIP: 0x08048187
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0000 SS: 007B
--------------------------------------------------------------------------[code]
0x8048187: cmp eax,0x0
0x804818a: jne 0x80481fb
0x804818c: push 0x4
0x804818e: pop eax
0x804818f: cdq
0x8048190: xor ebx,ebx
0x8048192: inc ebx
0x8048193: push 0xa
--------------------------------------------------------------------------------

Catchpoint 1 (returned from syscall 'ptrace'), 0x08048187 in ?? ()

There we have a check for eax, normally ptrace would return 0 but it's 0xFFFFFFFF since gdb is already active. Let's change it to 0 and continue.

gdb$ set $eax = 0
gdb$ conti
Catchpoint 1 (call to syscall 'write'), 0x080481ac in ?? ()
gdb$ conti
Get the flag

Catchpoint 1 (returned from syscall 'write'), 0x080481ac in ?? ()
$ conti

Execution seems to be in a infinite loop there. Break it...

^