<< All versions

Skill v1.0.0

currentAutomated scan100/100
prohao42/aimy-skill/heap-exploitation
──Details
PublishedSeptember 28, 2026 at 08:05 PM
Content Hashsha256:aa73ba2c7b9fd6af...
Git SHA195da56295e4
──Files
Files (1 file, 9.1 KB)
SKILL.md9.1 KBactive
SKILL.md · 219 lines · 9.1 KB

version: "1.0.0" name: heap-exploitation description: >- Heap 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.


SKILL: Heap Exploitation — Expert Attack Playbook

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.

0. RELATED ROUTING

Advanced References


1. PTMALLOC2 STRUCTURE QUICK REFERENCE

malloc_chunk Layout (64-bit)

chunk pointer (returned by malloc - 0x10)
┌──────────────────────────┐
0x00 │ prev_size (if prev free)│
0x08 │ size | A | M | P │ ← P=PREV_INUSE, M=IS_MMAPPED, A=NON_MAIN_ARENA
├──────────────────────────┤ ← user data starts here (returned pointer)
0x10 │ fd (if free) │ ← forward pointer to next free chunk
0x18 │ bk (if free) │ ← backward pointer to prev free chunk
0x20 │ fd_nextsize (large only)│
0x28 │ bk_nextsize (large only)│
└──────────────────────────┘

Bin Types

BinSize Range (64-bit)StructureLIFO/FIFO
tcache (per-thread)≤ 0x410 (7 entries per size)Singly linked (next pointer)LIFO
fastbin≤ 0x80 (default)Singly linked (fd)LIFO
unsortedbinAny freed sizeDoubly linked circularFIFO
smallbin< 0x400Doubly linked circularFIFO
largebin≥ 0x400Doubly linked + size-sortedSorted

Key Global Structures

StructureLocationPurpose
main_arenalibc .data segmentContains bin heads, top chunk, system_mem
mp_libc .datamalloc parameters (tcache settings, mmap threshold)
tcache_perthread_structHeap (first allocation)Per-thread tcache bins and counts

2. LEAK METHODS

Libc Base Leak

MethodPreconditionTechnique
Unsortedbin fd/bkFree a chunk > tcache range (or fill tcache)fd/bk → main_arena + 0x60 (or +0x70 depending on version) → libc base
Smallbin fd/bkChunk moved from unsortedbin to smallbinSame as unsortedbin leak
stdout FILE leakWrite to _IO_2_1_stdout_Corrupt _IO_write_base to leak libc data (see IO_FILE)

Heap Base Leak

MethodPreconditionTechnique
Tcache fd pointerFree two tcache chunks, read first's fdfd → heap address (XOR'd in ≥ 2.32)
Fastbin fdFree two fastbin chunksfd → heap address
UAF readUse-after-free on freed chunkRead fd/bk directly

Safe-Linking Decode (glibc ≥ 2.32)

python
# PROTECT_PTR: fd_stored = (chunk_addr >> 12) ^ real_fd
# To decode: real_fd = fd_stored ^ (chunk_addr >> 12)
# To encode: fd_stored = (chunk_addr >> 12) ^ target_addr
def deobfuscate(stored_fd, chunk_addr):
return stored_fd ^ (chunk_addr >> 12)
def obfuscate(target, chunk_addr):
return (chunk_addr >> 12) ^ target

3. ATTACK CATEGORIES BY GLIBC VERSION

glibc < 2.26 (No tcache)

AttackPrimitive NeededResult
Fastbin dupDouble freeArbitrary allocation
Unsortedbin attackCorrupt unsortedbin bkWrite main_arena addr to target (used for __malloc_hook nearby overwrite)
Unlink attackHeap overflow into prev_size + fd/bkArbitrary write (with known heap pointer)
House of ForceTop chunk size overwriteArbitrary allocation
House of SpiritWrite fake chunk headerFastbin allocation at fake chunk
Off-by-one nullNull byte overflow into next chunk sizeOverlapping chunks

glibc 2.26–2.28 (tcache, no key)

AttackNotes
Tcache poisoningOverwrite tcache fd → arbitrary allocation, no size check
Tcache dupDouble free into tcache (no double-free detection yet)
All previous attacksStill work, but chunks go to tcache first

glibc 2.29–2.31 (tcache key introduced)

AttackBypass for tcache key
Tcache dupCorrupt key field (at chunk+0x18) before second free
House of BotcakeDouble free: one in unsortedbin, one in tcache → overlapping
Tcache stashing unlinkAbuse smallbin→tcache refill to get arbitrary chunk

glibc 2.32–2.33 (safe-linking / PROTECT_PTR)

AttackAdaptation
Tcache poisoningEncode target with (chunk_addr >> 12) ^ target
Heap leak requiredNeed heap addr to decode/encode safe-linked pointers
Fastbin dupSame encoding required

glibc ≥ 2.34 (hooks removed)

ChangeImpact
__malloc_hook removedCannot overwrite hook for one_gadget
__free_hook removedCannot overwrite hook
__realloc_hook removedCannot use realloc trick for one_gadget constraints

Post-2.34 targets: see arbitrary-write-to-rce for _IO_FILE, exit_funcs, TLS_dtor_list, _dl_fini.


4. COMMON VULNERABILITY PATTERNS

VulnerabilityDescriptionExploitation Path
UAF (Use-After-Free)Access chunk after freeRead: leak fd/bk; Write: corrupt fd for tcache poisoning
Double Freefree() same chunk twiceTcache dup (bypass key) or fastbin dup
Heap OverflowWrite past chunk boundaryCorrupt next chunk's metadata (size, fd, bk)
Off-by-oneOne byte overflowNull byte → shrink next chunk size → overlapping chunks
Off-by-nullSpecifically \x00 overflowClear PREV_INUSE → trigger backward consolidation
Uninitialized readRead heap memory without clearingLeak fd/bk from recycled chunk

5. TOOLS

bash
# pwndbg heap inspection
pwndbg> heap # display all chunks
pwndbg> bins # show all bin contents
pwndbg> tcachebins # tcache status
pwndbg> fastbins # fastbin status
pwndbg> unsortedbin # unsortedbin content
pwndbg> vis_heap_chunks # visual heap layout
pwndbg> find_fake_fast &__malloc_hook # find nearby fake fastbin chunks
# how2heap — reference implementations
git clone https://github.com/shellphish/how2heap
# heapinspect
pip install heapinspect
heapinspect <pid>
# pwntools helpers
from pwn import *
libc = ELF('./libc.so.6')
print(hex(libc.symbols['__malloc_hook']))
print(hex(libc.symbols['__free_hook']))

6. DECISION TREE

Heap vulnerability identified
├── What is the primitive?
│ ├── UAF (read + write)
│ │ ├── Can read freed chunk? → Leak libc (unsortedbin) or heap (tcache fd)
│ │ └── Can write freed chunk? → Tcache poisoning / fastbin dup
│ ├── Double free
│ │ ├── glibc < 2.29 → direct tcache dup
│ │ ├── glibc 2.29-2.31 → corrupt tcache key first, or House of Botcake
│ │ └── glibc ≥ 2.32 → need heap leak for safe-linking encode
│ ├── Heap overflow (controlled size)
│ │ ├── Overwrite next chunk size → overlapping chunks → UAF
│ │ └── Overwrite fd directly → arbitrary allocation
│ ├── Off-by-one / off-by-null
│ │ ├── Null byte into size → House of Einherjar (backward consolidation)
│ │ └── One byte into size → shrink chunk, create overlap
│ └── Arbitrary write (from overlap or poisoned allocation)
│ ├── glibc < 2.34 → __malloc_hook / __free_hook → one_gadget
│ ├── glibc ≥ 2.34 → _IO_FILE vtable, exit_funcs, TLS_dtor_list
│ └── Partial RELRO → GOT overwrite
│
├── Need libc leak?
│ ├── Free chunk into unsortedbin (size > 0x410 or fill 7 tcache)
│ ├── Read fd/bk → main_arena offset → libc base
│ └── Alternative: stdout FILE partial overwrite for leak
│
└── Need heap leak? (glibc ≥ 2.32)
├── Read tcache fd from freed chunk
└── Decode: real_addr = stored_fd ^ (chunk_addr >> 12)
All versions