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.
stack0, the program defines an
int variable named
modified, followed by a 64 byte
char buffer. It then gets input from
buffer as its destination, before printing a string dependent on the contents of
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
echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | ./stack0
Typing all those characters is exhausting though. Let’s use Ruby.
ruby -e "puts('A' * 65)" | ./stack0
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
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')"`
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
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
$ 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
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