How stack frames work
When a function is called, the CPU pushes the return address onto the stack, the callee saves the old frame pointer, and then allocates space for local variables. A typical 64-bit frame looks like this:gets, strcpy, strcat, and sprintf copy data without checking the destination size, making them classic vulnerability triggers.
Finding the offset to the return address
Using a De Bruijn (cyclic) pattern
Send a non-repeating pattern as input, observe which bytes end up in the instruction pointer after the crash, and calculate the offset.- pwntools
- GEF
Exploitation techniques
Ret2win
A ret2win challenge has a function inside the binary that is never called during normal execution — typically namedwin, secret, or similar. The exploit overwrites the return address with that function’s address.
ASLR is typically disabled in ret2win challenges because the binary is not PIE; the function address is fixed at link time.
Stack shellcode
If the stack is executable (NX absent) and ASLR is disabled, you can place shellcode in the buffer and redirect execution to it.ROP (when NX is enabled)
When the stack is non-executable, use Return-Oriented Programming to chain existing code fragments. See the dedicated ROP page.Windows SEH overflow
On 32-bit Windows, structured exception handler (SEH) records are stored on the stack. An overflow can overwrite the SEH chain:- The
nSEHfield (4 bytes before the handler pointer) is set to a short jump (\xeb\x06\x90\x90) that skips over the handler pointer. - The handler pointer is replaced with the address of a
POP POP RETgadget. - When the exception fires,
POP POP RETredirects execution tonSEH, which jumps into the payload buffer.
Real-world examples
CVE-2026-2329 — Grandstream GXP1600 (ARM, no auth)
CVE-2026-2329 — Grandstream GXP1600 (ARM, no auth)
The
/cgi-bin/api.values.get endpoint copies each colon-delimited token into a 64-byte stack buffer without length checks. A token longer than 64 bytes corrupts saved registers. NX is enabled but there is no canary or PIE, so a ROP chain built from fixed addresses achieves code execution.CVE-2025-40596 — SonicWall SMA100 (sscanf overflow)
CVE-2025-40596 — SonicWall SMA100 (sscanf overflow)
An unbounded
%s conversion in sscanf fills a 0x800-byte stack buffer from user-supplied URI data. Inputs longer than 0x800 bytes corrupt the stack canary and saved return address, causing a pre-authentication denial of service (and potentially RCE with an additional info leak).CVE-2025-23310 — NVIDIA Triton Inference Server (alloca exhaustion)
CVE-2025-23310 — NVIDIA Triton Inference Server (alloca exhaustion)
alloca() is called with a size proportional to the number of HTTP chunked-transfer segments (16 bytes per segment). Sending hundreds of thousands of 6-byte chunks causes stack exhaustion without any bounds check, crashing the server.Heap overflows
Overflows are not always on the stack. Heap-based overflows corrupt adjacent allocations and are covered in heap exploitation.Protections quick reference
| Protection | What it does | Common bypass |
|---|---|---|
| Stack canary | Detects linear overwrites before return | Info leak, bruteforce in forking servers |
| NX / DEP | Non-executable stack | Return-Oriented Programming |
| ASLR | Randomises stack/heap/lib addresses | Info leak, partial overwrite |
| PIE | Randomises binary base | Info leak of code pointer |
| Full RELRO | Read-only GOT | Requires info leak and ROP |