Today I decided to refresh my memory of buffer overflows by writing a short vulnerable program and then an exploit for it. To make things more interesting, I decided to challenge myself to write an exploit for the program that would work with ASLR enabled.
The vulnerable program I wrote is found below. It uses the deprecated gets function which does not limit the amount of data being copied into its buffer. To avoid having to deal with DEP I decided to compile the program with the flag “-z execstack”.
1 2 3 4 5 6 7 8 9 10 |
|
Time to dive into exploitation. The first step was to calculate how many bytes were needed to overflow the buffer on the stack. I decided to streamline the process and use the script pattern_create.rb which is found in the metasploit framework.
1 2 3 4 5 |
|
Next step was to feed the pattern to the vulnerable program. It’s important to mention that before I did this I decided to enable core dumps to get an accurate representation of the program’s memory after it crashed.
1 2 |
|
To get the offset to the saved instructional pointer I just fed the address to pattern-offset.rb
1 2 3 4 5 6 |
|
To make sure this worked I wrote a one lined ruby command to make sure the program crashed to the address 0x42424242 (the ascii letter B) and then analyzed the core dump.
One technique for making the buffer overflow exploit position independent is to jump to a register rather than a hardcoded address on the stack. A good register for this is esp. This works because although the contents of the register esp will change, the opcode to jump to esp will not. This can be shown by running the program twice and printing the contents of the registers using gdb.
The next picture below just illustrates how esp in the second picture above points just after the value used for overflowing the stack. Perfect spot to store shellcode!
The next step is to find some location in the text segment that has the instruction jmp esp. For most programs written in linux the position of the text segment does not change each time the program is executed even with ASLR enabled. The start address of the text segment is actually a hard coded value found in the elf header file. Great! A tool that can help us look for the opcodes is msfelfscan.
After running the command I felt a little stumped. The program did not use the instruction jmp esp anywhere in the text segment! My solution to this problem was to try and find a register with a different address that could be manipulated. Looking back at the register values at the time of crash eax seemed to fit the bill perfectly! The value of eax at the time of the crash stored the starting address of the data being copied onto the stack from gets. I ran msfelfscan a second time but this time looking for calls or jumps to eax. Found it.
My solution for exploiting the program became the following:
- Generate the opcode for jump esp
- Overwrite the value on the stack pointed to by eax with that opcode
- Overwrite eip with the address of the call eax instruction.
Since I don’t have the entire x86 instruction set memorized cough cough. I decided to write a short assembly program using nasm to get the opcode for jump esp. First I compiled the file with nasm using the flag –f elf. Then I linked the program using ld and ran the a.out file it generated using objdump.
The full exploit, written in ruby, is found below. To test if it worked I used shellcode that should print a simple “hello world!” message.
1 2 3 4 5 6 7 8 9 10 11 |
|
And finally, pwnage.