> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-15/information-leak/trick-0449/pwn-information-leak-stack-leak.md).

# Stack Leak

## Leak Executable Base Address From Overflow Output

After triggering a buffer overflow, observe the program's output. If a print function subsequently reads stack data (often due to not encountering a null byte after the overflow), it might leak the original return address. This leaked address points into the executable's text segment. To find the PIE base address, calculate:

```
base_address = leaked_return_address - offset_of_leaked_address_in_binary
```

Find the `offset_of_leaked_address_in_binary` by disassembling the program and locating where that leaked return address would point statically (e.g., the instruction address immediately after the `call` that got overwritten). Tools like `objdump` or `readelf` can be used to disassemble or inspect the binary and find the static addresses (offsets) of functions or specific code points.

For example, to find the offset of the `main` function using `objdump`:

```bash
objdump -d ./pie_level1 | grep main
```

This command might output something like `0000000000001149 <main>:`, where `0x1149` is the static offset of `main`. Alternatively, `readelf -s` can also show symbol offsets:

```bash
readelf -s ./pie | grep main
```

This could yield `13: 0000000000001159 36 FUNC GLOBAL DEFAULT 13 main`, indicating `0x1159` as the offset.

Once you have the leaked address and the static offset of that address within the binary, you can calculate the base address. This calculation is often performed within the exploit script itself. Using a library like `pwntools` in Python, this might look like:

```python
# Assume p is the pwntools process object and leaked_addr is received
leaked_addr = int(p.recvline(), 16) # Example: receiving leaked address as hex string
log.info(f"Leaked address: {hex(leaked_addr)}")

# Calculate base address
main_offset = 0x1149 # Replace with the actual offset found via objdump/readelf
base_address = leaked_addr - main_offset
log.info(f"Base address: {hex(base_address)}")
```

This base address can then be used to calculate the runtime addresses of other functions or gadgets in the binary by adding their static offsets to the calculated base address.
