Read-Counter Manipulation (Canary Skip)
- •
What it is
- •
Overwrite a read loop's on-stack progress counter so its next write jumps past the canary. The canary remains unchanged because the skipped bytes are never written.
- •
- •
How it works
- •
Vulnerable pattern:
while (n < size) { n += read(0, input + n, 1); }— reads one byte at a time, always to offsetn, andnitself
lives on the stack at some fixed offset from the buffer. - •
When input reaches the counter, overwrite it so the next iteration uses a later destination offset. Confirm when the increment occurs.
- •
This lets the next write skip directly to any later offset (e.g. the saved return address) — the canary's bytes in between are never touched, so the epilogue's canary check still passes.
- •
[ buffer ][ counter ][ canary ][ saved rbp ][ return address ] └── change next write offset ────────────────┘ - •
The overflow's declared "size" in these harnesses marks the right-most offset ever written, not the count of bytes actually transmitted — bytes at skipped offsets are simply never sent at all.
- •
- •
When to use it
- •
Banner or source discloses a byte-at-a-time read loop implementation with an on-stack counter variable, and gives that counter's exact offset relative to the input buffer.
- •
checksec/banner confirms a canary is present (unlike prior challenges in this log) — this technique exists specifically because a plain overflow would corrupt it and abort the program. - •
Counter manipulation can preserve the canary, but knowing the final target address is a separate issue. See Address Space Layout Randomization (ASLR).
- •
- •
Examples
- •
Counter at offset 36, return address at 56: write
55into the counter's low byte; if the loop increments it, the next write lands at 56.
- •
- •
pwntools
- •
payload = b'A' * 36 + p8(55) + p64(target)[:2] # Lab-specific offsets; verify the counter increment and declared limit.
- •
- •
Debugging
- •
disas challenge x/8gx $rsp # Check counter and guard positions.
- •
- •
- •
Cards
- •
Why doesn't skipping over the canary's offset range trigger the canary check on return?
- •
The check only fails if the canary's stored value differs from what was set at the start — if those bytes are never written to at all, they're never changed, so the check still passes.
- •
- •
In this technique, what does the overflow's "size" parameter actually control?
- •
The rightmost offset the read loop will ever write to — not the literal number of bytes the attacker transmits, since manipulating the counter lets some offsets be skipped without being sent.
- •
- •