Protection & Security

a buffer overflow

Imagine a row of mailboxes built into a wall, each just big enough for the day's letters. If a careless postal worker keeps stuffing letters into box number 5 after it is full, the overflow does not vanish — it spills into box 6, then box 7, overwriting whatever was meant to be there. A buffer overflow is exactly this in memory: a program writes more data into a fixed-size storage region (a buffer) than the region can hold, and the extra bytes spill over and clobber whatever sits next to it in memory.

The dangerous version is the classic stack smash. When a function runs, the CPU keeps its local variables — including fixed-size buffers — together with bookkeeping data on the stack, and crucially that bookkeeping includes the return address: where execution should jump back to when the function finishes. Now suppose the program copies user-supplied input into a 64-byte buffer without checking the length, using something like an old strcpy. If the attacker supplies 200 bytes, the write runs past the buffer and overwrites the saved return address. The attacker chooses those bytes so the return address now points at code they planted (often inside the very input they sent). When the function returns, the CPU jumps to the attacker's code and runs it with the program's privileges. That is code injection: untrusted data has been turned into executed instructions.

Buffer overflows have been one of the most damaging classes of vulnerability for decades, and they are the reason several defenses in this field exist. Stack canaries put a secret guard value just before the return address and check it before returning, so an overflow that smashed the canary is caught. No-execute (NX/DEP) memory marks the stack non-executable, so even if attackers place code there the CPU refuses to run it. Address-space layout randomization scrambles where things live, so the attacker cannot reliably guess the address to jump to. The honest truth is none of these is a cure — attackers responded with return-oriented programming and other tricks that reuse existing executable code — which is why the real fix is bounds checking and memory-safe languages, and why overflows still appear in old C and C++ code today.

char buf[64]; strcpy(buf, input); — if input is 200 bytes, strcpy writes all 200, overrunning buf by 136 bytes and overwriting the saved return address on the stack. A crafted input redirects that return address to attacker-chosen code. Replacing strcpy with a length-bounded copy (writing at most 64 bytes) closes the hole.

Unchecked input overruns the buffer and overwrites the return address.

The defenses (canaries, NX, ASLR) raise the bar but none is a cure — attackers adapted with code-reuse tricks like return-oriented programming. The real fix is bounds checking and memory-safe languages, which is why overflows persist in old C and C++ code.

Also called
stack smashingstack-based buffer overflowbuffer overrun緩衝區溢出堆疊破壞攻擊