format-string-exploitation
Format string exploitation playbook. Use when printf-family functions receive user-controlled format strings, enabling arbitrary stack reads (%p/%s), arbitrary memory writes (%n/%hn/%hhn), GOT/hook overwrites, and canary/libc/PIE leaks.
By yaklang · 3,025 installs
npx skills add yaklang/hack-skills --skill format-string-exploitation
Source repository · Upstream listing
SKILL: Format String Exploitation — Expert Attack Playbook
AI LOAD INSTRUCTION : Expert format string techniques. Covers stack reading, arbitrary write via %n, GOT overwrite, malloc hook overwrite, pointer chain exploitation, blind format string, FORTIFY SOURCE bypass, 64 bit null byte handling, and pwntools automation. Distilled from ctf wiki fmtstr, CTF patterns, and real world scenarios. Base models often miscalculate positional parameter offsets or forget 64 bit address placement after format string.
0. RELATED ROUTING
[stack overflow and rop](../stack overflow and rop/SKILL.md) — combine format string leak with stack overflow for full exploit
[binary protection bypass](../binary protection bypass/SKILL.md) — format string is the primary canary/PIE/ASLR leak method
[arbitrary write to rce](../arbitrary write to rce/SKILL.md) — convert format string write primitive to code execution targets
[heap exploitation](../heap exploitation/SKILL.md) — heap address leak via format string for heap exploitation
1. VULNERABILITY IDENTIFICATION
Vulnerable Pattern
Quick Test
2. READING MEMORY
Stack Leak (%p)
Format Action Use
%p Print next stack value as pointer Sequential stack dump
%N$p Print N th parameter as pointer Direct positional access
%N$lx Same as %p but explicit hex (64 bit) Portable
%N$s Dereference N th parameter as string pointer Read memory at pointer value
Finding Your Input Offset
Leaking Specific Values
Target Method Stack Position
Canary %N$p where N = canary offset from format string Typically at offset buf size/8 + few
Saved RBP %N$p (just above return address) Leaks stack address → stack base
Return address %N$p Leaks .text address (PIE base = leak & ~0xfff offset)
Libc address %N$p where N points to libc start main+XX return on stack libc base = leak offset
Reading Arbitrary Address (%s)
3. WRITING MEMORY (%n)
Write Specifiers
Specifier Bytes Written Width
%n 4 bytes (int) Characters printed so far
%hn 2 bytes (short) Characters printed so far (mod 0x10000)
%hhn 1 byte (char) Characters printed so far (mod 0x100)
%ln 8 bytes (long) Characters printed so far
Arbitrary Write Technique
Goal : Write value V to address A .
32 bit (address on stack directly):
64 bit (address AFTER format string):
Byte by Byte Write with %hhn
Write one byte at a time for precision (6 writes for full 48 bit address on 64 bit):
4. PWNTOOLS fmtstr payload()
FmtStr Class (Interactive Exploitation)
5. GOT OVERWRITE VIA FORMAT STRING
Common Targets
Overwrite With Trigger
printf@GOT system Next printf(user input) → system(user input) , send /bin/sh
strlen@GOT system If strlen(user input) called
puts@GOT system If puts(user input) called
atoi@GOT system If atoi(user input) called (send sh as "number")
stack chk fail@GOT Controlled addr Bypass canary check entirely
exit@GOT main Create infinite loop for multi shot exploit
Hook Targets (glibc < 2.34)
Target One gadget Trigger
malloc hook one gadget addr Any printf with large format → internal malloc
free hook system Trigger free("/bin/sh")
6. STACK POINTER CHAIN EXPLOITATION
When format string is not directly on the stack (e.g., stored in a heap buffer referenced by stack pointer), use pointer chains on the stack to achieve arbitrary write.
Two Stage Write
This requires finding existing pointer chains on the stack (e.g., saved frame pointers forming a chain: rbp → prev rbp → prev prev rbp).
Finding Pointer Chains
7. BLIND FORMAT STRING
Remote service, no binary, no source — exploit format string blind.
Methodology
Step Action Purpose
1 Send %p × 50 Dump stack, identify address patterns
2 Identify offsets Find libc addrs (0x7f...), stack addrs (0x7ff...), code addrs
3 Find input offset Send AAAA%N$p for N=1..50, find 0x41414141
4 Identify binary base Code addresses reveal PIE base (or fixed base if no PIE)
5 Leak GOT entries If binary base known, read GOT via %N$s with GOT address
6 Calculate libc base GOT value libc symbol offset
7 Overwrite GOT %n to rewrite GOT entry with system address
8. FORTIFY SOURCE BYPASS
FORTIFY SOURCE (gcc D FORTIFY SOURCE=2 ) replaces printf with printf chk which forbids %N$n (positional writes).
Bypass Techniques
Method Detail
Use %hn sequentially (no positional) Print exact byte count, %hn , adjust, %hn — fragile but works
Stack based exploit If format string is on stack, use non positional %n with stack position control
Heap overflow instead FORTIFY doesn't protect heap — combine with heap bug
Return to printf ROP to call unfortified printf (if available in binary or libc)
9. 64 BIT CONSIDERATIONS
Challenge Solution
Addresses contain \x00 (null byte terminates format string) Place addresses AFTER format specifiers, pad to alignment
Address width: 6 significant bytes Write 3 × %hn (2 bytes each) or 6 × %hhn
Larger stack offset range Input may be at offset 6+ due to 6 register args saved
48 bit address space Only bottom 48 bits of 64 bit used
Layout Template (64 bit)
10. DECISION TREE