Check out my gitHub page! and my updated CV!

Saturday, November 2, 2013

Hacklu 2012: safehouse (binary 150) writeup

Yes, i know we are in 2013, but I still want to do a quick writeup of the binary safehouse from hacklu 2012, as I found this to be one of the best challenges I ever did in my life, really didactic!

So first of all, we have to ssh a web page, here is what we got:

beginning screen (from https://f00l.de/blog/)
ok, a nice setuid executable and its flag. As you can see, our user is called ctf, the target one (the one we want to impersonate) is called safe house.
So, let's start!

file command gives us "setuid setgid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5446b9058fdd04404a8b84827d5873028204ee90, not stripped"
Ok fine, so a 64bit executable, setuid (as we already know), not stripped lucky us!

run the program, nothing happen, exit 0.
Run the program with an argument display the following string:


Mmm.. me lika string! let's open it with IDA and look for the string!

A quick look on the binary let us find the function in charge of displaying our string:

Function display the string "Zombie detected"

Ok, as presumed, if this function is called it will display the string and then exit.
Looking a bit more in the binary we find where this function is called and what the binary is doing:

Series of actions for the main
Ok, so basically our program is checking for the number of args (not displayed, but it's just "if argc ==0 exit"), then drop the privileges and set our function as a handler for signals (in particular SIGSEGV). Then it allocates a page, and declare it as WRX.

Then it writes on this page all strings we give as input as a double-word converted with strtoul function, appending 0xc3 as 4th byte and then call it! After calling all our "inputs", if no signal were received in the mean time it pops up a shell.

We begin to have an idea about what we have to do, we basically have to inject a shellcode so that the program will acquire the privileges of safehouse (without going in segfault), then the program itself is going to pop up a shell for us! the only limitation is given by that 0xC3 injection as the fourth byte on every double word, we need a clever way to write our shell code.

We know that setuid is a a system call,  therefore we can call it by mean of a int 0x80h instruction.
Looking here we have a nice table of all system call, with relative parameters.
Gotcha! an int 0x80h with a 0x17 in eax will call sys_setuid, what we need! uid_t should be in ebx register, and we know safehouse is uid=1006 (in hex 0x3ee).

Now we need to divide our input in several pieces, all of them smaller than 4 bytes:

mov al, 0x17 -> b0 17
mov bh, 0x3 -> b7 03 //highest part of 1006
mov bl, 0xee -> b3 ee //lowest part of 1006
int 0x80 -> 80 cd

Wow! we just need to split the setting of the bx register in two parts, and all our input is nicely divided in block 2 bytes-long!
Obviously we still need to fill up 1 byte without letting the process crash, what's better than a nice old 0x90!?

we just built 4 arguments then (remember LITTLE ENDIAN!):

'0x9017b0', '0x9003b7', '0x90eeb3', '0x9080cd'

Now it's just a matter of converting them to integer and we should be cool!

[9443248, 9438135, 9498291, 9470157]

Trying to call the program with these arguments give us


And a nice little shell for us!

that's it, I found this easy exploitation very didactic for building up a custom shellcode, a very nice piece of work!

There was also another version of this challenge a bit more complex, it will be for next time!

This is a link (from LeetMore writeup) for downloading the binary.

Enjoy!



No comments:

Post a Comment