This project demonstrates a stack-based control-flow hijacking attack by exploiting a format-string vulnerability in a C program.
By abusing unsafe usage of snprintf() with attacker-controlled input, the exploit achieves arbitrary memory writes, overwrites a function’s return address, and redirects execution to attacker-supplied shellcode resulting in interactive shell execution.
The project focuses exclusively on low-level binary exploitation, emphasizing stack analysis, precise memory writes, and exploit reliability.
The target program contains a format-string vulnerability caused by passing user-controlled input directly as the format string to snprintf().
This allows an attacker to:
- Read stack memory using format specifiers (
%x,%p) - Write to arbitrary memory using
%n/%hn - Overwrite control-flow data stored on the stack
In this project, the vulnerability is exploited to overwrite the return address of a vulnerable function and hijack control flow.
To enable deterministic exploit development and reliable control-flow hijacking, the following runtime and compilation settings are required.
ASLR must be disabled to ensure stable stack and shellcode addresses across executions.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_spaceAlternatively, to persist across reboots:
sudo sysctl -w kernel.randomize_va_space=0This is because the exploit relies on precise stack addresses (return address and shellcode location). ASLR would randomize these addresses and break exploit reliability.
The vulnerable binary is compiled with an executable stack. Because, the Shellcode is injected into process memory and executed directly. A non-executable (NX) stack would prevent shellcode execution.
The binary is compiled without stack canaries (-fno-stack-protector). Because, stack canaries would detect return-address corruption and terminate the program before control-flow hijacking occurs.
The vulnerable program is installed and executed from /tmp/cstarget
- Ensures a predictable execution environment
- Avoids permission and path-related side effects
- Matches runtime assumptions used during exploit construction
Note: The binary must not be recompiled, as compilation flags are security-critical
The exploit development begins with runtime stack inspection using GDB:
- Breakpoints are placed at
main()and the vulnerable function - The stack frame layout is analyzed to locate:
- The function return address
- The position of attacker-controlled input (
argv[1]) - The runtime address of injected shellcode
Figure 1 below shows GDB inspection of stack memory and attacker-controlled arguments during exploit execution.
To reliably hijack control flow, the exploit performs two precise half-word writes using %hn:
- The target return address is split into:
- Lower 2 bytes
- Upper 2 bytes
- Each half is written separately to adjacent stack locations
- Printed byte counts are carefully calculated to ensure correct values are written
This approach avoids instability associated with full-word %n writes and improves exploit reliability.
Once the return address is overwritten:
- Execution flow is redirected to attacker-controlled shellcode
- The shellcode executes
/bin/sh - A fully interactive shell is obtained without modifying the binary on disk
Figure 2 shows successful control-flow redirection and shell execution.
- Format-string exploitation (
%hn) - Stack-based control-flow hijacking
- Return address manipulation
- Half-word memory writes for reliability
- Stack frame layout analysis
- GDB-assisted exploit development
- C – Vulnerable program and exploit payload
- GDB – Binary analysis and stack inspection
- Linux – Execution and debugging environment
This project highlights how improper format-string handling can lead to:
- Arbitrary memory writes
- Control-flow hijacking
- Arbitrary code execution
It underscores the importance of:
- Always using fixed format strings
- Enabling compiler protections
- Applying runtime exploit mitigations
- Jon Erickson, Hacking: The Art of Exploitation
- Aleph One, Smashing the Stack for Fun and Profit
- Feng Wei, Format String Exploitation Slides
- Linux
printf/snprintfManual Pages

