Exploit Exercises Protostar Guide, Part 1

In order to better understand the material from the Software Security course on Coursera, I decided to take a stab at the challenges on Exploit Exercises.

So far it has been an amazing way to really cement the concepts from the course, so I decided to document my progress here for anybody else interested in making their way through the levels.

I’ve been running through these challenges by setting up the downloadable ISOs from the Exploit Exercises downloads page in VirtualBox, then sshing in so I don’t have to deal with VirtualBox as much.

Stack 0

In stack0, the program defines an int variable named modified, followed by a 64 byte char buffer. It then gets input from STDIN, using buffer as its destination, before printing a string dependent on the contents of modified.

By passing input with a length greater than 64 bytes to the program, the buffer variable will overflow onto the modified variable, giving you the target output. The first 64 bytes will fill the buffer, with the 65th byte overwriting the value of modified.

echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | ./stack0

Typing all those characters is exhausting though. Let’s use Ruby.

ruby -e "puts('A' * 65)" | ./stack0

Stack 1

This program expands upon the previous example by requiring that you use a specific value as your overflow. It works similarly to stack0, except the exploit only succeeds when modified matches 0x61626364.

To fill the buffer variable, we again need 64 bytes of padding, followed by the value to overwrite modified with. The value 0x61626364 conveniently matches the first 4 lowercase alphabetical characters in the ASCII character set (abcd). By adding that to the end of the padding string, the conditional should succeed.

There’s one caveat: the VM that Protostar is running in is little-endian, meaning that the order of the characters needs to be reversed before being appended to the string.

./stack1 `ruby -e "puts(('A' * 64) + 'dcba')"`

Stack 2

This challenge is very similar to the previous one, except that the malicious string needs to be set as an environment variable instead.

Note that I’m also using hex values directly, as these don’t nicely translate to ASCII characters.

GREENIE=`ruby -e "puts(('A' * 64) + \"\x0a\x0d\x0a\x0d\")"`
export GREENIE
./stack2

Stack 3

This challenge asks us to overwrite a pointer value stored on the stack with that of another function. The tricky aspect of this one is finding the address of the function we want to call.

objdump is a tool which prints information about binaries – time to put it to use by finding the address of the win function.

$ objdump -d stack3 | grep win
08048424 <win>:

The address of win looks to be 0x08048424. Nice! That will serve as the value of our overflow, formatted as little-endian once again.

ruby -e 'puts(("A" * 64) + "\x24\x84\x04\x08")' | ./stack3

Stack 4

This was a pretty fun challenge to figure out. The idea is that you have to overwrite the eip pointer on the stack, while dealing with the compiler which will insert an undetermined amount of padding between you and eip on the stack.

After some research, I found a few mentions of a technique used to exploit code like this. The idea is to generate a unique, non-repeating string, and use that to find the offset by providing it as the value of the overflow.

I used this handy tool to generate a string. Pass that string to the program, and look at the result when it hits eip. (A quick note on this part: you will need to open and run the program in gdb to see the value that is being called.)

Take the value and pass it back to the buffer overflow tool to figure out the offset (76, in this case). Use objdump to find the address of win once more, and then you have yourself an exploit.

ruby -e 'puts(("A" * 76) + "\xf4\x83\x04\x08")' | ./stack4