Gera's Insecure Programming warming up stack #1 (ROP NX/ASLR Bypass)
Oct 21, 2011 - lixor_
5 minute read
I started gera’s exercises on format strings vulnerabilities. I am going to start on the stack next. This post will be my first ROP practice and it was fun :). The main purpose of “warming up the stack” exercises is to just bypass the canary. However, I wanted to make it harder and get a shell out of it.
The targeted platform was Debian 6.0.2 with linux-image-2.6-686-bigmem (PAE).
The binary, obviously, just prints to the screen. The cookie variable needs to be written with values of 0x41424344. The variable cookie is before the buffer so it can be overwritten. Attentive readers will know these are ASCII values. Since the characters are being read from stdin into a buffer, the cookie needs to be overwritten with DCBA.
Yay, the cookie “protection” was bypassed and now for the real fun.
I used a neat ROP tool from vnsecurity called ROPeMe . Curious readers can find more information about the tool in the reference section. I found 4 useful gadgets in this small binary.
Only using these 4 gadgets do not do anything useful. I repeated (2) after (2) to get a perfectly working ROP payload (doing GOT dereferencing).
The entire gadget list can be found here stack1.ggt.
I could not really find any simple pop eax gadget without it having a trailing leave instruction; which I tried to avoid as much as I can due to ASLR. The xchg esi, eax; instruction is good enough.
The leave instruction is similar to mov esp, ebp; pop ebp; resulting in my current stack pointer pointing at a different location.
The approach I used to perform ROP was GOT dereferencing as mentioned in the paper “Surgically returning to randomized lib(c)” .
Ideally, I want eax to have the address of system() and the GOT address of an offset function in ebx. Since I have a few gadgets with additional calculations, I will need some dummy values for (2).
The two gadgets (2) and (4) accesses a memory location at a particular offset, +0x5d5b04c4 and -0xb8a0008 respectively. Using simple mathematics, I just need to subtract 0x5d5b04c4 and add 0xb8a0008 to remove the offset from the equation.
I choose gmon_start to be used in the first memory access (2) and puts for the actual function to find system().
In (2), there is small issue that eax is being added with 0x8. I need to subtract 0x00000008 from the value stored in eax (giving me the original value in eax).
A string is needed, preferably pointing to /bin/sh, to supply it to system(). There are different ways to do this. I found a string ‘GNU’ at .note.gnu.build-id.
At this point, I hit a wall because it should have drop me into a shell. I was able to execute other commands, but not any shells. After debugging and few ideas from the NYSEC crew, I found out that since I was piping into the binary there is no controlling terminal for the processes. This prevents the shell from reading STDIN. I needed to open the console. A few google searches later I found a forum post  that addressed my issue: needed to find the process’s pts and perform some I/O redirections.
Here is the script with minor modifications:
Now when I create the new symlink and add my local directory to my PATH, I should get a shell.