Buffer Overflow 101

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

  1. Confirm binary protections (checksec style checks).
  2. Crash with pattern input to find exact overwrite offset.
  3. Validate instruction pointer control with marker values.
  4. Build payload in small increments and verify each stage.
  5. 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, unchecked strcpy)
  • enable stack canaries, NX, PIE, and RELRO
  • reduce attack surface in parser and input-heavy code paths
  • test with sanitizers during development

Related reading:

2025-11-03