# Heap Exploitation Dev

> Auth/lab dev: heap exploitability research; glibc/musl/Windows allocators, UAF/double-free/overflow models, heap shaping, mitigations.

- Skill: `aeondave/heap-exploitation-dev` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add aeondave/heap-exploitation-dev`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aeondave/heap-exploitation-dev/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- License: MIT
- Author: AeonDave (https://skillmd.com/u/aeondave)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aeondave/heap-exploitation-dev

---


# Heap Exploitation Development

Goal: turn a heap bug into a repeatable primitive and then into the right endgame for that allocator/version, not the most nostalgic House name.

## When to activate

- Heap overflow, off-by-one, UAF, double-free, arbitrary free, overlapping chunk, or stale-pointer bug touches heap-managed objects.
- Need allocator-aware exploit design instead of generic memory corruption advice.
- Need to choose between tcache poisoning, bin corruption, FSOP, setcontext/ROP, or data-only outcomes.
- Linux target may use glibc, musl, or custom allocators.
- Windows target uses the default process heap, a private heap, LFH, VS, or Segment Heap.

## First classify the environment

1. **Identify allocator and version**
  - `glibc/ptmalloc`: determine version first; most House viability is version-gated.
  - `musl mallocng`: assume group/slot shaping and application object corruption, not direct House portability.
  - `Windows`: determine whether the bug is on NT heap, LFH, VS, or Segment Heap, and whether it is a private heap.
  - `Custom allocator`: reverse metadata, pool headers, callback tables, and destructor paths before importing glibc assumptions.
2. **Classify the bug primitive**
  - overflow / off-by-one / null byte
  - UAF / stale pointer / double free
  - arbitrary free / fake chunk / pointer substitution
  - overlap / leak / relative write
3. **Decide the capability you actually need**
  - heap leak
  - libc leak
  - arbitrary allocation
  - arbitrary write
  - FILE overlap / FSOP
  - stack pivot / setcontext / ORW
  - data-only corruption
4. **Map mitigations before choosing the chain**
  - tcache
  - tcache double-free checks
  - safe-linking
  - FILE vtable validation
  - hook removal (`__malloc_hook`, `__free_hook`)
  - RELRO / PIE / ASLR
  - seccomp / sandboxing
  - Windows CFG / CET / heap termination on corruption

## Version-first selection

| Environment | Bias toward | Avoid or de-prioritize |
|---|---|---|
| glibc < 2.26 | Force, Orange, Roman, Storm, Rabbit, Lore, Spirit, unsafe unlink, unsorted/largebin classics | Tcache-first thinking |
| glibc 2.26-2.31 | tcache poisoning, Botcake, stashing unlink, fastbin reverse into tcache, Einherjar, early IO | Assuming hooks are gone or safe-linking exists |
| glibc 2.32-2.33 | safe-linking bypasses, House of IO, House of Water, Botcake, largebin-assisted tcache control | Blind fd poisoning without a heap leak or metadata route |
| glibc 2.34-2.41 | FSOP / House of Apple 2 or 3, stdout/stderr overlap, setcontext pivots, Water, Tangerine, tcache-relative write | `__free_hook` / `__malloc_hook` as default endgame |
| glibc 2.42+ | tcache metadata hijacking, Water, Tangerine, allocator-metadata overflow, FSOP | Assuming classic largebin or early-tcache metadata layouts still hold |
| musl mallocng | slot/group shaping, application-object overlap, type confusion, atexit / app-specific callback abuse | Direct porting of ptmalloc House techniques |
| Windows NT/LFH | same-size grooming, adjacent object corruption, private-heap determinism, CRT/FILE or return-address targets after AAR/AAW | Old "just corrupt FLink/BLink" folklore without build-specific proof |
| Windows Segment Heap / VS | application object corruption, pointer replacement, vtable/function-pointer chains, leak-first workflow | Assuming Segment Heap behaves like classic LFH or exposes easy freelist writes |

## House families worth prioritizing

| Family | Good fit | Typical result | Reality check |
|---|---|---|---|
| House of Spirit | arbitrary free / fake chunk | near-arbitrary allocation | Still a useful fake-chunk pattern, not a complete endgame |
| House of Lore | smallbin corruption | near-arbitrary allocation | Good for fake-chunk thinking; often a helper, not the finale |
| House of Einherjar | off-by-one null / `PREV_INUSE` clear | overlap + consolidation | Excellent default when null-byte primitive exists |
| House of Force | old top chunk overflow | arbitrary allocation | Classic only; top-chunk integrity kills the stock form on modern glibc |
| House of Orange | no `free()` path on old glibc | unsorted-bin + FSOP | Historical; keep for < 2.26 and for reasoning about Tangerine |
| House of Roman | leakless relative overwrite on old glibc | hook-era RCE | Strong conceptually, weak as modern default |
| House of Storm | unsorted + largebin choreography | forged chunk / arbitrary allocation | High setup, mainly old glibc |
| House of Corrosion | WAF + old/post-Orange stderr path | leakless libc writes + FSOP | Real but niche, entropy-heavy, build-sensitive |
| House of Red | staged `stderr` corruption + allocator-failure trigger | failure-driven `stderr` / FILE dispatch | Treat as a situational trigger pattern adjacent to Corrosion/Crust, not a first-choice primitive |
| House of Botcake | tcache double-free bypass | arbitrary allocation/write | Great modern default when double-free is involved |
| House of IO | safe-linking era with tcache-struct control | tcache poisoning without classic fd leak | Version-windowed and precondition-heavy |
| House of Water | leakless tcache-metadata control | leakless tcache takeover | Strong modern option when metadata is reachable |
| House of Tangerine | no explicit `free()`, top-chunk abuse | arbitrary allocation through freed wilderness | Modern Orange replacement; excellent on newer glibc |
| House of Apple 2 | post-hook glibc | FSOP via `system` or `setcontext` | One of the best 2.34+ endgames |
| House of Apple 3 | post-hook glibc | FSOP via `_codecvt` | Advanced but worth knowing |
| House of Rust / Crust | safe-linking + TSU/largebin + FSOP | leakless or low-leak stdout/stderr overlap | Powerful, but too brittle to be your first plan |
| House of Muney | mmapped chunk overlap into libc mapping | symbol-table / mapping corruption | Expert-only, RELRO-sensitive, rare in real targets |
| House of Blindness | one-byte / LSB writes into mmap-relative space (`link_map->l_addr`, `l_info[DT_*]`, `_r_debug`) | leakless escalation: byte write → mis-resolved `_dl_fixup` → arbitrary call via `_dl_fini` at `exit()` | Modern glibc (verified on 2.34, pepsipu Feb 2022); requires `_dl_fixup` reachable (partial RELRO) and `exit()` path; CTF-grade, invaluable when no leak / no IO |

Treat House names as indexed solution families, not trophies. Primitive + allocator + version wins over naming aesthetics.

## Mitigation-driven rules

- **Safe-linking (glibc 2.32+)**: do not plan blind tcache poisoning unless you have a heap leak or a metadata route such as House of Water or safe-link double-protect.
- **Hook removal (glibc 2.34+)**: if the exploit sketch ends at `__free_hook` or `__malloc_hook`, it is probably outdated unless `libc_malloc_debug.so.0` is explicitly involved.
- **FILE vtable validation**: assume valid jump-table regions only. Prefer Apple 2/3, `_wide_data`, `_codecvt`, or other in-section routes over fake arbitrary vtables.
- **Largebin hardening**: verify the exact libc. Classic largebin attack is not a universal assumption on 2.42+.
- **musl mallocng**: cycling offsets, guard pages, cookies, and `mmap()`-backed groups change heap shaping completely; validate adjacency and slot reuse empirically.
- **Windows modern heaps**: encoded metadata, heap isolation, safe unlinking, CFG, and CET push you toward adjacent-object corruption and post-primitive ROP/data-only goals, not nostalgic metadata-only exploits.
- **Seccomp / SUID / restricted shells**: prefer ORW or `setcontext`/ROP over `system("/bin/sh")`.
- **Zeroing / self-using write primitive**: if your only path to write a target is an allocation that **zeroes the returned chunk** (calloc / explicit `memset`/`rep stosq`) and the program then immediately *uses* that region (prints through it, re-reads it), an in-place forge over a libc stream/struct self-destructs before you can finish. Model the write primitive's side effects explicitly; when blocked, route to a **print-free / cross-stream write** (see `fsop-dev`: input-buffer redirection) or a second-thread/`free()`-deposited write rather than fighting the ordering.
- **Per-thread allocator state**: each thread has its **own arena + own tcache**, and `free()` uses the *calling thread's* tcache. A worker thread's `free()` of a main-arena chunk lands in the *worker's* tcache, not main's — so it does **not** create a same-bin double-free for the main thread. Confirm which thread/tcache a free targets before assuming overlap.

## Endgame selection

- **glibc < 2.34**: hooks, `_IO_list_all`, stdout/stderr corruption, or classic one-gadget chains may still fit.
- **glibc >= 2.34**: bias toward FSOP, House of Apple 2/3, `_wide_data` or `_codecvt` control, `setcontext+61`, or clean ORW. Once the allocator work is done and the hard part becomes libio dispatch/trigger selection, hand off to `offensive-coding/fsop-dev`.
- **SUID targets**: `system("/bin/sh")` can drop privilege; use `setcontext` or ROP to normalize credentials first.
- **No libc leak**: only choose Roman/Corrosion/Crust-like chains if the target really blocks easier leak paths and you can afford entropy/bruteforce.
- **Only heap-relative corruption available**: favor overlap-driven data-only attacks, allocator metadata hijack, or tcache-relative writes before chasing code execution.
- **Windows**: use the heap bug to get AAR/AAW, then pivot to vtable/function-pointer/IAT/stack targets with CFG-aware gadget choice.

## Reliability checklist

- Confirm exact allocator, heap type, and libc version before naming a technique.
- Cross-check named glibc techniques against a matching how2heap version folder when available; a House name is a hypothesis, not compatibility proof.
- Validate chunk sizes against the real bin class and alignment rules.
- Track whether the victim chunk will land in tcache, fastbin, unsorted, smallbin, largebin, LFH, VS, or Segment Heap.
- Map aliases between allocator metadata and attacker-used storage. A tcache entry, bin link, chunk field, or application slot may be the same qword; allocator maintenance can destroy a primitive that worked in isolation.
- Re-run later helper allocations after the full corruption sequence. A parser's internal `malloc` or `realloc` is part of the exploit state machine, not an independent trigger.
- When a later allocation must bypass sacrificial metadata, test the exact normalized size. A merely larger victim may be sorted and force the allocator to validate the next corrupted node.
- Prove the leak first if the chain needs libc or heap base.
- Model trigger paths separately from corruption paths; many House chains fail at the final call site, not the heap step.
- Stress the exploit under multiple runs and slightly different heap schedules.
- Prefer the shortest stable chain, not the fanciest multi-House stack.

## Anti-patterns

- Recommending `__free_hook` on modern glibc by reflex.
- Assuming House names transfer unchanged across glibc, musl, jemalloc, tcmalloc, and Windows heaps.
- Treating Windows LFH or Segment Heap as if they were old-school unsafe unlink playgrounds.
- Chasing code execution when a stable data-only or ORW path is enough.
- Cargo-culting a public writeup without checking allocator version, build quirks, or mitigation deltas.

## Resources

- [references/glibc-techniques.md](references/glibc-techniques.md) — glibc era map, House families, how2heap-backed compatibility workflow, latest tcache-metadata routes, and version-aware selection.
- [references/house-family-atlas.md](references/house-family-atlas.md) — dedicated atlas of classic, modern, and post-hook House families with status, prerequisites, and when to de-prioritize them.
- [references/patterns-and-mitigations.md](references/patterns-and-mitigations.md) — primitive taxonomy, allocator comparison, and mitigation-driven decision rules.
- [references/fsop-and-post-hook-targets.md](references/fsop-and-post-hook-targets.md) — Apple 2/3, FSOP paths, and post-hook endgames.
- [../fsop-dev/SKILL.md](../fsop-dev/SKILL.md) — standalone FSOP router for libio-specific dispatch, trigger, and endgame selection once stream overlap is already on the table.
- [references/windows-techniques.md](references/windows-techniques.md) — NT/LFH/Segment Heap notes, realistic primitives, and Windows-specific caveats.
- Upstream methodology: `offensive-techniques/binary-exploitation-technique` (primitive→impact strategy, mitigation selection) and `offensive-ctf/pwn-ctf/references/heap.md` (concrete recipes).

Load the reference files only after allocator, version, primitive, and intended endgame are clear; they hold the depth that does not belong in this routing file.

