Linux heap exploitation
TL;DR: Modern glibc heap exploitation revolves around corrupting tcache, fastbin, or unsorted-bin metadata to forge a write-what-where or leak libc, usually starting from a UAF or single-byte overflow.
What it is
glibc’s ptmalloc2 manages freed chunks in per-size lists (tcache and fastbins for small allocations, unsorted/small/large bins for larger ones). Each list is a singly or doubly linked list whose fd/bk pointers live inside the freed chunk itself. Corrupting those pointers — via UAF, off-by-null, single-byte overflow into chunk size, or double-free — gives an attacker control over the next malloc return address.
Preconditions / where it applies
- Heap-corruption primitive: UAF, double-free, linear overflow, off-by-one, off-by-null
- glibc target — version dictates which mitigations apply (tcache key/safe-linking land in 2.32+)
- Ability to allocate and free chunks of controlled sizes (most CTF menus expose this; real bugs often need a heap groom)
Technique
Pick the cheapest primitive that fits the bug class:
- tcache poisoning (glibc ≥ 2.26): after a free, overwrite the chunk’s first qword with a target address; the next two allocations of that size hand it back.
- fastbin dup: double-free a fastbin chunk, then redirect
fdto a near-arbitrary location whose fake-size field matches the bin. - unsorted-bin attack / leak: a chunk freed into the unsorted bin has libc
main_arenapointers infd/bk— reading it back leaks libc base, the standard step before a one-gadget ret2libc. - House of Force / Spirit / Botcake: classical large-bin and top-chunk corruption recipes; how2heap catalogues each.
Safe-linking (glibc 2.32+) XORs fd with (pos >> 12), so tcache/fastbin poisoning now needs a heap-base leak first:
1
2
// safe-linking obfuscation
#define PROTECT_PTR(pos, ptr) ((__typeof(ptr))((((size_t)pos) >> 12) ^ (size_t)ptr))
Typical chain: heap leak → libc leak via unsorted bin → tcache poison overwriting __free_hook or __malloc_hook (≤ 2.33) or an exit handler / FILE vtable (2.34+).
Detection and defence
- Compile with
MALLOC_CHECK_=3orGLIBC_TUNABLES=glibc.malloc.check=3to assert on bad chunk metadata during fuzzing - AddressSanitizer / HWASan catches UAF and overflows at allocation granularity
- Keep glibc current — safe-linking, tcache double-free keys (
tcache_key), and removal of__malloc_hook(2.34) close most legacy paths - Use
mallopt(M_MXFAST, 0)to disable fastbins where compatibility allows
References
- how2heap (shellphish) — canonical catalogue of glibc heap techniques per version
- Safe-linking writeup (Check Point) — what 2.32 changed
- HackTricks: Linux heap — quick technique index
Related: ret2libc, srop, ret2csu, format-string-bugs