exploit-memory-corruption

Turn a memory-corruption bug in a native binary into code execution — stack overflows, format strings, and ROP against modern mitigations. Load when you control input to a compiled program and it cras

SKILL.md

GitHub

Memory-corruption exploitation

When it applies

You have a native binary or service on an authorized target that mishandles your input — a network-facing daemon, a thick-client, a setuid helper found during privesc, or a binary carved from firmware (reverse-eng-firmware). reverse-eng-binary-triage located the bug; this skill turns that crash into controlled execution. Pentest-only — this is destructive and can crash the service.

Why it works

C/C++ has no memory safety: writing past a buffer overwrites saved return addresses and pointers, and a user-controlled format string reads/writes arbitrary memory. Redirect execution to your code or to existing code (ROP) and the process does your bidding. Modern mitigations (NX, ASLR, PIE, stack canaries) don't remove the bug — they shape the technique.

Method

  1. Check protections first — checksec ./bin (or pwntools): NX, PIE, RELRO, canary. This decides everything. No canary + NX → ROP; PIE → you need a leak; no PIE, no NX → maybe shellcode.
  2. Find the offset — send a cyclic pattern (cyclic 200 / pattern_create), crash it under gdb+GEF/pwndbg, read the value in $rip/$eip, and cyclic -l <value> for the exact offset to the saved return address.
  3. Pick the primitive by protections:
    • ret2win — a target function already in the binary; overwrite the return address with it.
    • ret2libc / ROP — with NX, chain gadgets: leak a libc address (call puts(puts@got) via the PLT), compute the libc base, return to system("/bin/sh") or a one_gadget. Build gadgets with ROPgadget/ropper, the chain with pwntools ROP().
    • Format string (printf(user)) — leak stack/canary/PIE base with %p, then do arbitrary writes with %n (GOT overwrite → redirect a call to system). fmtstr_payload automates it.
  4. Defeat mitigations with leaks — ASLR/PIE need a leaked address (from a format string or an info-leak bug) to rebase; a stack canary must be leaked (or brute-forced byte-by-byte on a forking server) and replayed in your overflow so the check passes.
  5. Build it with pwntools — a repeatable script: process()/remote(), recvuntil, pack with p64(), stage the leak, then send the final chain; iterate locally, then fire at the target.
  6. Land a shell — reuse payloads-reverse-shells for what to run once you have execution.

Gotchas

  • Match the exact libc — remote exploitation fails on the wrong libc version/offsets; identify it (leaked addresses → a libc-database lookup) before computing system/one_gadget.
  • Bad bytes — \x00, \x0a, \x20 can truncate input depending on the read function; check and avoid them in addresses/payload.
  • Local works, remote doesn't — environment/stack alignment differs; the movaps alignment crash before system is fixed by an extra ret gadget.
  • This crashes the target — it's inherently disruptive; only on authorized pentest targets, never a live bug-bounty production service, and note the risk in the RoE.

Verify success

Reliable control of execution demonstrated on the target — a returned shell, a run command, or a controlled $rip with a working ROP chain — reproducible from your pwntools script.

References

pwntools docs & tutorials; checksec; GEF/pwndbg; ROPgadget/ropper; one_gadget; libc-database. Find the bug with reverse-eng-binary-triage; shell payloads in payloads-reverse-shells.