I haven’t blogged in a while — the reason is I have been doing Hack The Box challenges. These challenges are typically still live when I finish them so I cannot post the write ups. Recently however I have been getting into reverse engineering. I decided my first ret2libc challenge is a good point to write about the exploits as the others were quite simple.

Lets begin with the code for the challenge. Here is a snapshot:

stack6.c

First things first, we know from previous challenges there will be a buffer to overflow. As we can see in the code, all the stuff we need is in the function getpath() so lets do an objdump:

objdump -S /opt/protostar/bin/stack6

objdump of getpath in stack6.c

Without seeing the code, we can look at this output and determine a few things. 1) There is a gets which we know is vulnerable. In the man page for gets it says “Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets()

will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security.

Use fgets() instead.”

Next we see a compare at 0x80484bd then a jump if not equal at 0x80484c2. This tells us there is some sort of comparison, then a jump if it is not true. In the code snippet we see this as

if(( ret & 0xbf000000) == 0xbf000000) {

If we overflow our buffer, we may be able to write to the stack pointer and point to another function outside the stack. Lets throw a large string at it, say 4 A’s, 4 B’c, etc. Using gdb, we disassemble the getpath function, and set breakpoints at the gets and ret functions.:

We can see the ebp and eip have been overwritten with 54 and 55. This gives us a clue that we can overwrite the eip with a new address. We can find out which values in our buffer overflow were successful at overwriting the eip using python:

>>> chr(0x54)

‘T’

>>> chr(0x55)

‘U’

Now we know we can stick a new address in the eip variable, which will jump to at the end of the program. We can use the system() function to call system commands. To find the address of this we can do

(gdb) p system

$1 = {<text variable, no debug info>} 0xb7ecffb0 <__libc_system>

Our address of system is 0xb7ecffb0. We add that as a new variable in our exploit script:

system = struct.pack(“I”, 0xb7ecffb0)

Next, we need a string which is known to containt “/bin/sh” . the library libc contains the string “/bin/sh”, but we dont know where it is located. We can use the tool “strings” to find the offset from the beginning of the file:

user@protostar:/tmp$ strings -t d /lib/libc.so.6 | grep /bin/sh

1176511 /bin/sh

Ok, we have the offset. But we need the address that libc starts. We can run

There we go! Now we know the address of libc and the offset of where the string “/bin/sh” is stored. Lets add that to our exploit:

Now lets run it against our program with

(python exploit.py; cat) | /opt/protostar/bin/stack6

Oh great, a new segmentation fault. The best thing I have learned to do in this situation is add padding — a few “A”s shall suffice.

ok, lets run again

Boom, we have root!

If you want a bit more of a detailed look into this exploit, check out liveoverflow on youtube. He has a playlist just on exploiting binary challenges on protostar. Till next time!