Exploit Exercises: Protostar: Stack 6


This time we’re going to compromise Stack 6 from the Exploit Exercises Protostar VM. The description of this challenge states that it can be solved a few ways –
  1. Finding the payload duplicate
  2. The ret2libc method
  3. Using ROP
We’re going to use method 2, using this excellent PDF as our guiding light.

The Vulnerability

The vulnerability here is the same as the other Stack* exercises – we’re able to jam too much data into too small a buffer, allowing us to take control of EIP.
This particular exercise checks the return address after the gets() call and checks to see if it starts with 0xbf AKA, is the return address now randomly pointing at memory allocated for the stack. Obviously return addresses which start with that value are definitely trying to do something naughty!

The Attack

The attack here is quite novel. We’re going to do the following –
  1. Establish the address where the system() function lives in libc
  2. Jam a load of rubbish into the buffer up to the return address
  3. Overwrite the return address with the address found in step 1
  4. Write rubbish over the next 4 bytes (which is just part of the previous stack frame)
  5. Set the following bytes to a pointer to “/bin/bash”
This will have the effect of the getpath() function “returning” to the system() function, and due to step 5 above, it will have the effect of passing “/bin/bash” as an argument to system.
In C, system(“/bin/bash”); will have the effect of spawning a shell. 🙂

Where does system() live?

First up we’ll find the address of system. Luckily GDB makes this easy for us.

Highlighted in green above is the address of system().

How do we get a pointer to “/bin/bash”

The PDF which I linked above makes an environment variable named “EGG” containing the name of a shell. That’s a super inventive solution, but what we’re going to do instead is take advantage of the fact that the gets function returns a pointer to the start of the buffer.. So if we start our buffer with “/bin/bash -px00” and supply the pointer returned from gets() as an argument to system().

Putting it all together

Now that we’ve got the things which we need, it’s just a simple case of making a crafted payload like the previous 6 challenges!
We’ll use Python again.
At this point you know how to find the return address, so I’ll skip that in the interest of brevity – the return address on my box was located precisely 16 bytes after the end of the buffer, so I’ll use that value in my BOF.
Additionally, I used this guide to help find the pointer returned by gets

The format’s a bit crazy BUT we can see that gets returned a pointer to 0xbffff6ec, so we’ll use that in our buffer overflow Python script.

We’ve got all of the pieces of the puzzle now so we can use the following script to make the magic happen –

And here it is in action –



Phew! This was a hard / fun one, these challenges are starting to get difficult now.
I learned a lot doing this challenge and writing it up helped to cement that knowledge. Hope you enjoyed reading this.
One Comment

Add a Comment

Your email address will not be published. Required fields are marked *