Project 3: The Format String Bug Lab
A vulnerable program that takes user input and passes it directly to
printf. This lab has three stages: (1) Use format specifiers like%xto leak data from the stack. (2) Use the%sspecifier to read a secret string from a known address. (3) Use the%nspecifier to overwrite a variable in memory and gain admin privileges.
Quick Reference
| Attribute | Value |
|---|---|
| Primary Language | C |
| Alternative Languages | N/A |
| Difficulty | Level 3: Advanced |
| Time Estimate | 1-2 weeks |
| Knowledge Area | Exploit Development / Memory Disclosure / Arbitrary Write |
| Tooling | GCC/Clang, GDB, Python |
| Prerequisites | Project 2 (Stack Smashing). |
What You Will Build
A vulnerable program that takes user input and passes it directly to printf. This lab has three stages: (1) Use format specifiers like %x to leak data from the stack. (2) Use the %s specifier to read a secret string from a known address. (3) Use the %n specifier to overwrite a variable in memory and gain admin privileges.
Why It Matters
This project builds core skills that appear repeatedly in real-world systems and tooling.
Core Challenges
- Leaking stack data with
%x→ maps to understanding how printf walks the stack - Positioning an address on the stack for
%s→ maps to crafting a precise payload - Using
%nto write a value → maps to the concept of an arbitrary-write primitive - Calculating offsets and padding for a precise write → maps to fine-grained payload construction
Key Concepts
- Format String Exploitation: A classic paper on the topic is “Exploiting Format String Vulnerabilities” by scut / Team Teso.
- Variadic Functions: Understanding how functions like
printf(const char*, ...)work.
Real-World Outcome
// The C code
int check_auth() {
char password[16];
int auth_flag = 0; // Should be 1 for admin
char secret_message[] = "TheLaunchCodesAre0123";
printf("Enter password: ");
fgets(password, sizeof(password), stdin);
printf("Log: ");
printf(password); // Vulnerable!
if (auth_flag) {
printf("\nAccess Granted. %s\n", secret_message);
} else {
printf("\nAccess Denied.\n");
}
}
Implementation Guide
- Reproduce the simplest happy-path scenario.
- Build the smallest working version of the core feature.
- Add input validation and error handling.
- Add instrumentation/logging to confirm behavior.
- Refactor into clean modules with tests.
Milestones
- Milestone 1: Minimal working program that runs end-to-end.
- Milestone 2: Correct outputs for typical inputs.
- Milestone 3: Robust handling of edge cases.
- Milestone 4: Clean structure and documented usage.
Validation Checklist
- Output matches the real-world outcome example
- Handles invalid inputs safely
- Provides clear errors and exit codes
- Repeatable results across runs
References
- Main guide:
LEARN_C_SECURE_CODING_DEEP_DIVE.md - “The Shellcoder’s Handbook”