Buffer Overflow 101
A stack-based buffer overflow is the oldest trick in the book and still one of the most instructive. We start with a vulnerable C program, compile it without canaries, and walk through EIP control step by step.
The target binary accepts user input via gets() — a function so dangerous that
modern compilers emit a warning just for including it. We feed it a carefully
crafted payload: 64 bytes of padding, followed by the address of our shellcode
sitting on the stack.
Key takeaways: always compile test binaries with -fno-stack-protector -z execstack
when learning, and never on a production box.
What makes this topic timeless is not the exact exploit recipe, but the mental model it gives you: memory layout, calling convention, control-flow integrity, and why unsafe copy primitives are dangerous by construction.
Reliable lab workflow
- Confirm binary protections (
checksecstyle checks). - Crash with pattern input to find exact overwrite offset.
- Validate instruction pointer control with marker values.
- Build payload in small increments and verify each stage.
- Only then attempt shellcode or return-oriented payloads.
Expected outcome before each run should be explicit. If behavior differs, do not “try random bytes”; explain the difference first. That habit turns exploit practice into engineering instead of cargo cult.
Defensive mirror
Learning offensive mechanics should immediately map to mitigation:
- remove dangerous APIs (
gets, uncheckedstrcpy) - enable stack canaries, NX, PIE, and RELRO
- reduce attack surface in parser and input-heavy code paths
- test with sanitizers during development
Related reading: