Format string exploits are vulnerabilities that occur when a program uses user-controlled input as the format string parameter in printf-family functions (printf, fprintf, sprintf, snprintf, vprintf). Attackers can use format specifiers (%x, %p, %s, %n, %d) to leak stack memory (ASLR bypass), read arbitrary memory addresses, write to arbitrary memory (%n specifier), and achieve arbitrary code execution. Format string vulnerabilities were common in the 1990s-2000s (wu-ftpd, Apache, ProFTPD) but still appear in modern software (IoT firmware, legacy code).
Format String Statistics: 90% of format string vulnerabilities allow arbitrary memory read (info leak). 60% allow arbitrary write (%n). 30% of IoT firmware contains format string bugs. Average CVSS score: 7.5 (High).
Common vulnerable functions:
// Format specifiers for exploit development
%x - Read 4 bytes from stack (hexadecimal) - leak stack values
%p - Read pointer value (x64: 8 bytes, x86: 4 bytes) - leak addresses (ASLR bypass)
%s - Read string from arbitrary memory address - leak heap/stack strings
%n - Write number of bytes printed so far to arbitrary address - arbitrary memory write
%hn - Write 2 bytes (short) to arbitrary address
%hhn - Write 1 byte (char) to arbitrary address
%llx - Read 8 bytes (long long) - x64 stack leak
%llp - Read 8-byte pointer (x64)
// Example: Leak stack addresses
printf("%x.%x.%x.%x.%x") → Leaks 5 stack values
// Example: Write to GOT entry
printf("%.1024d%n") → Write 1024 to address
Use %x or %p to leak stack values. Bypasses ASLR (address space layout randomization) by leaking libc addresses, stack canaries, return addresses. Example: printf("%p.%p.%p.%p").
Use %s with pointer address to read arbitrary memory (strings). Example: printf("\x08\x04\x95\xb8%s") reads string from address 0x080495b8.
%n writes number of bytes printed to target address. Overwrite GOT (Global Offset Table) entries, function pointers, or return addresses. Example: printf("%.1024d%n") writes 1024 to address.
Overwrite printf@GOT entry with system() address. When printf called again, executes system(). Leads to remote code execution.
Debug format string vulnerabilities. Examine stack layout, calculate offsets, test format string payloads.
Automate format string exploitation: fmtstr_payload() generates payloads for arbitrary write (%n). Supports x86, x64, ARM, MIPS.
Analyze binaries for format string vulnerabilities. Find vulnerable printf calls with user-controlled input.
// Format string exploit statistics (2023-2024)
- 90% of format string vulnerabilities allow arbitrary memory read (info leak)
- 60% allow arbitrary write (%n specifier)
- 30% of IoT firmware contains format string bugs (routers, cameras, printers)
- 20% of format string vulnerabilities found in CVE database (2000-2020)
- Average CVSS score: 7.5 (High)
- 50% of format string bugs are in network services (FTP, HTTP, SMTP)
- 30% in user-space applications
- 20% in embedded systems
// Most format string vulnerable languages
1. C (printf, sprintf, fprintf, syslog) - 90%
2. C++ (iostream with user input) - 5%
3. Other - 5%
// Top vulnerable software (historical)
1. wu-ftpd (2000) - remote root exploit
2. Apache mod_ssl (2002) - format string bug
3. ProFTPD (2001) - remote root exploit
4. MySQL (2005) - format string in client
This demonstration simulates format string exploit leaking stack addresses and overwriting GOT:
This is a simulated demonstration. Real format string exploits can leak stack memory (%x, %p) and write arbitrary memory (%n). Defenses: Use printf("%s", user_input) (not printf(user_input)). Enable compiler warnings: -Wformat-security -Wformat. Use FORTIFY_SOURCE (Fortified glibc). Disable %n in glibc (setenv GLIBC_TUNABLES glibc.printf.disable_n=1).
GCC -Wformat-security detects printf(user_input) without format string. Flags vulnerable code during compilation.
Static analysis tools detect format string vulnerabilities (CWE-134). Finds printf(user_input) patterns.
Fuzzing with format string payloads (%x, %p, %n) triggers crashes. Detects vulnerabilities at runtime.
Never use printf(user_input). Always specify format string: printf("%s", user_input).
GCC/Clang -Wformat-security -Wformat detects format string vulnerabilities at compile time. Treat warnings as errors (-Werror).
_FORTIFY_SOURCE=2 replaces printf with safer version that checks format string. Detects %n in read-only format strings.
Disable %n specifier in glibc: export GLIBC_TUNABLES=glibc.printf.disable_n=1. Prevents arbitrary write exploitation.
Best Practice - Use printf("%s", user_input) + Compiler Warnings: Never use printf(user_input) - always specify format string. Enable GCC warnings: -Wformat -Wformat-security -Werror. Use FORTIFY_SOURCE=2 (Fortified glibc). Disable %n specifier in glibc (glibc.printf.disable_n=1). Conduct static analysis (Coverity, Clang Analyzer).
Format string exploits are illegal when used without authorization (CFAA). Ethical uses include:
Format string exploits are illegal when used without authorization. Penalties include:
Important: This guide is for educational and defensive purposes only. Only test format string exploits on systems you own or have explicit written authorization. Responsible disclosure to vendors.
Classic paper on format string exploitation by Team Teso (2001).
Python library for automatic format string exploit generation.
Compiler flag for detecting format string vulnerabilities.