$npx -y skills add Prohao42/aimy-skill --skill heap-exploitationHeap exploitation playbook. Use when targeting ptmalloc2/glibc heap vulnerabilities including UAF, double free, overflow, off-by-one/null, and leveraging tcache/fastbin/unsortedbin attacks for arbitrary write or code execution.
| 1 | # SKILL: Heap Exploitation — Expert Attack Playbook |
| 2 | |
| 3 | > **AI LOAD INSTRUCTION**: Expert glibc heap exploitation techniques. Covers ptmalloc2 internals, bin structures, tcache mechanics, libc/heap leak methods, and attack selection by glibc version. Distilled from ctf-wiki heap sections, how2heap, and real-world exploitation. Base models often confuse glibc version constraints and miss safe-linking (PROTECT_PTR) introduced in 2.32. |
| 4 | |
| 5 | ## 0. RELATED ROUTING |
| 6 | |
| 7 | - [stack-overflow-and-rop](../stack-overflow-and-rop/SKILL.md) — when the overflow is on the stack rather than the heap |
| 8 | - [format-string-exploitation](../format-string-exploitation/SKILL.md) — leak heap/libc addresses via format string |
| 9 | - [arbitrary-write-to-rce](../arbitrary-write-to-rce/SKILL.md) — convert heap arbitrary write into code execution |
| 10 | - [binary-protection-bypass](../binary-protection-bypass/SKILL.md) — bypass ASLR/RELRO to use heap write effectively |
| 11 | |
| 12 | ### Advanced References |
| 13 | |
| 14 | - [HOUSE_OF_TECHNIQUES.md](./HOUSE_OF_TECHNIQUES.md) — House of Force/Spirit/Orange/Einherjar/Roman/Pig/Banana/Cat/Apple and tcache attacks |
| 15 | - [IO_FILE_EXPLOITATION.md](./IO_FILE_EXPLOITATION.md) — _IO_FILE vtable hijack, FSOP, stdout/stdin abuse, exit flow exploitation |
| 16 | |
| 17 | --- |
| 18 | |
| 19 | ## 1. PTMALLOC2 STRUCTURE QUICK REFERENCE |
| 20 | |
| 21 | ### malloc_chunk Layout (64-bit) |
| 22 | |
| 23 | ``` |
| 24 | chunk pointer (returned by malloc - 0x10) |
| 25 | ┌──────────────────────────┐ |
| 26 | 0x00 │ prev_size (if prev free)│ |
| 27 | 0x08 │ size | A | M | P │ ← P=PREV_INUSE, M=IS_MMAPPED, A=NON_MAIN_ARENA |
| 28 | ├──────────────────────────┤ ← user data starts here (returned pointer) |
| 29 | 0x10 │ fd (if free) │ ← forward pointer to next free chunk |
| 30 | 0x18 │ bk (if free) │ ← backward pointer to prev free chunk |
| 31 | 0x20 │ fd_nextsize (large only)│ |
| 32 | 0x28 │ bk_nextsize (large only)│ |
| 33 | └──────────────────────────┘ |
| 34 | ``` |
| 35 | |
| 36 | ### Bin Types |
| 37 | |
| 38 | | Bin | Size Range (64-bit) | Structure | LIFO/FIFO | |
| 39 | |---|---|---|---| |
| 40 | | tcache (per-thread) | ≤ 0x410 (7 entries per size) | Singly linked (next pointer) | LIFO | |
| 41 | | fastbin | ≤ 0x80 (default) | Singly linked (fd) | LIFO | |
| 42 | | unsortedbin | Any freed size | Doubly linked circular | FIFO | |
| 43 | | smallbin | < 0x400 | Doubly linked circular | FIFO | |
| 44 | | largebin | ≥ 0x400 | Doubly linked + size-sorted | Sorted | |
| 45 | |
| 46 | ### Key Global Structures |
| 47 | |
| 48 | | Structure | Location | Purpose | |
| 49 | |---|---|---| |
| 50 | | `main_arena` | libc .data segment | Contains bin heads, top chunk, system_mem | |
| 51 | | `mp_` | libc .data | malloc parameters (tcache settings, mmap threshold) | |
| 52 | | `tcache_perthread_struct` | Heap (first allocation) | Per-thread tcache bins and counts | |
| 53 | |
| 54 | --- |
| 55 | |
| 56 | ## 2. LEAK METHODS |
| 57 | |
| 58 | ### Libc Base Leak |
| 59 | |
| 60 | | Method | Precondition | Technique | |
| 61 | |---|---|---| |
| 62 | | Unsortedbin fd/bk | Free a chunk > tcache range (or fill tcache) | fd/bk → `main_arena + 0x60` (or +0x70 depending on version) → libc base | |
| 63 | | Smallbin fd/bk | Chunk moved from unsortedbin to smallbin | Same as unsortedbin leak | |
| 64 | | stdout FILE leak | Write to `_IO_2_1_stdout_` | Corrupt `_IO_write_base` to leak libc data (see IO_FILE) | |
| 65 | |
| 66 | ### Heap Base Leak |
| 67 | |
| 68 | | Method | Precondition | Technique | |
| 69 | |---|---|---| |
| 70 | | Tcache fd pointer | Free two tcache chunks, read first's fd | fd → heap address (XOR'd in ≥ 2.32) | |
| 71 | | Fastbin fd | Free two fastbin chunks | fd → heap address | |
| 72 | | UAF read | Use-after-free on freed chunk | Read fd/bk directly | |
| 73 | |
| 74 | ### Safe-Linking Decode (glibc ≥ 2.32) |
| 75 | |
| 76 | ```python |
| 77 | # PROTECT_PTR: fd_stored = (chunk_addr >> 12) ^ real_fd |
| 78 | # To decode: real_fd = fd_stored ^ (chunk_addr >> 12) |
| 79 | # To encode: fd_stored = (chunk_addr >> 12) ^ target_addr |
| 80 | |
| 81 | def deobfuscate(stored_fd, chunk_addr): |
| 82 | return stored_fd ^ (chunk_addr >> 12) |
| 83 | |
| 84 | def obfuscate(target, chunk_addr): |
| 85 | return (chunk_addr >> 12) ^ target |
| 86 | ``` |
| 87 | |
| 88 | --- |
| 89 | |
| 90 | ## 3. ATTACK CATEGORIES BY GLIBC VERSION |
| 91 | |
| 92 | ### glibc < 2.26 (No tcache) |
| 93 | |
| 94 | | Attack | Primitive Needed | Result | |
| 95 | |---|---|---| |
| 96 | | Fastbin dup | Double free | Arbitrary allocation | |
| 97 | | Unsortedbin attack | Corrupt unsortedbin bk | Write `main_arena` addr to target (used for __malloc_hook nearby overwrite) | |
| 98 | | Unlink attack | Heap overflow into prev_size + fd/bk | Arbitrary write (with known heap pointer) | |
| 99 | | House of Force | Top chunk size overwrite | Arbitrary allocation | |
| 100 | | House of Spirit | Write fake chunk header | Fastbin allocation at fake chunk | |
| 101 | | Off-by-one null | Null byte overflow into next chunk size | Overlapping chunks | |
| 102 | |
| 103 | ### glibc 2.26–2.28 (tcache, no key) |
| 104 | |
| 105 | | Attack | Notes | |
| 106 | |---|---| |
| 107 | | Tcache poisoning | Overwrite tcache fd → arbitrary allocation, no size check | |
| 108 | | Tcache dup | Double free into tcache (no double-free detection yet) | |
| 109 | | All previous attacks | Still work, but chunks go to tcache first | |
| 110 | |
| 111 | ### glibc 2.29–2.31 (tcache key introdu |