heap-exploitation — скилл для Claude Code: атаки на glibc heap
Плейбук по эксплуатации кучи ptmalloc2: UAF, double free, overflow и атаки через tcache, fastbin и unsortedbin. Пригодится на CTF и при разборе уязвимостей glibc.
npx skills add yaklang/hack-skills --skill heap-exploitation -a claude-codeЧто делает heap-exploitation
Скилл даёт агенту справочник по внутренностям ptmalloc2: раскладку malloc_chunk, таблицу бинов с размерами и порядком LIFO/FIFO, расположение main_arena, mp_ и tcache_perthread_struct. Отдельный раздел — способы утечки адресов libc и heap, включая декодирование safe-linking через XOR со сдвигом адреса чанка на 12 бит.
Дальше идёт выбор атаки по версии glibc. До 2.26 это fastbin dup, unsortedbin attack, unlink и House of Force. В 2.26–2.28 появляется tcache без проверки ключа, в 2.29–2.31 ключ уже есть и его обходят через House of Botcake или tcache stashing unlink. С 2.32 включается PROTECT_PTR, поэтому для подделки указателей сначала нужна утечка адреса кучи. С 2.34 убрали __malloc_hook, __free_hook и __realloc_hook — на этих версиях скилл отправляет к _IO_FILE, exit_funcs и TLS_dtor_list.
Внутри есть разбор типовых багов: use-after-free, double free, переполнение чанка, off-by-one и off-by-null с затиранием PREV_INUSE. Для отладки приведены команды pwndbg — heap, bins, tcachebins, fastbins, unsortedbin. Если переполнение живёт на стеке, а не в куче, скилл перенаправляет на stack-overflow-and-rop.
Какие задачи решает
- подобрать атаку под конкретную версию glibc
- утечь адрес libc через unsortedbin
- обойти safe-linking при подделке fd в tcache
- превратить double free в выделение по произвольному адресу
- найти цель для записи на glibc 2.34 и новее
Примеры запросов агенту
- разбери бинарь, найди UAF и предложи цепочку эксплуатации кучи
- какая атака на tcache сработает на glibc 2.31?
- посчитай safe-linking для fd, если адрес чанка известен
Как установить heap-exploitation
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill heap-exploitation -a claude-code2Вручную: положить файлы
~/.claude/skills/heap-exploitation/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/heap-exploitation/
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill heap-exploitation -a codex2Вручную: положить файлы
.agents/skills/heap-exploitation/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill heap-exploitation -a cursor2Вручную: положить файлы
.cursor/skills/heap-exploitation/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install yaklang/hack-skills heap-exploitation2Вручную: положить файлы
.github/skills/heap-exploitation/SKILL.md1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill heap-exploitation -a gemini-cli2Командой платформы
gemini skills install https://github.com/yaklang/hack-skills --path skills/heap-exploitationВручную: положить файлы
.devin/skills/heap-exploitation/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill heap-exploitation -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора93
Похожие
Вопросы о heap-exploitation
Как установить heap-exploitation в Claude?
Выполните npx skills add yaklang/hack-skills --skill heap-exploitation -a claude-code. После этого файл скилла появится по пути ~/.claude/skills/heap-exploitation/SKILL.md.
Что делает heap-exploitation?
Это плейбук по эксплуатации кучи glibc: структура ptmalloc2, бины, методы утечки адресов и подбор атаки по версии glibc. Агент опирается на него, когда в задаче есть UAF, double free или переполнение чанка.
Почему на glibc 2.34 не работает перезапись хуков?
В этой версии удалили __malloc_hook, __free_hook и __realloc_hook, поэтому трюк с one_gadget через хук не проходит. Скилл предлагает другие цели: _IO_FILE, exit_funcs, TLS_dtor_list.
Исходный текст
SKILL.md · MIT
---
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
- [stack-overflow-and-rop](../stack-overflow-and-rop/SKILL.md) — when the overflow is on the stack rather than the heap
- [format-string-exploitation](../format-string-exploitation/SKILL.md) — leak heap/libc addresses via format string
- [arbitrary-write-to-rce](../arbitrary-write-to-rce/SKILL.md) — convert heap arbitrary write into code execution
- [binary-protection-bypass](../binary-protection-bypass/SKILL.md) — bypass ASLR/RELRO to use heap write effectively
### Advanced References
- [HOUSE_OF_TECHNIQUES.md](./HOUSE_OF_TECHNIQUES.md) — House of Force/Spirit/Orange/Einherjar/Roman/Pig/Banana/Cat/Apple and tcache attacks
- [IO_FILE_EXPLOITATION.md](./IO_FILE_EXPLOITATION.md) — _IO_FILE vtable hijack, FSOP, stdout/stdin abuse, exit flow exploitation
---
## 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
| Bin | Size Range (64-bit) | Structure | LIFO/FIFO |
|---|---|---|---|
| tcache (per-thread) | ≤ 0x410 (7 entries per size) | Singly linked (next pointer) | LIFO |
| fastbin | ≤ 0x80 (default) | Singly linked (fd) | LIFO |
| unsortedbin | Any freed size | Doubly linked circular | FIFO |
| smallbin | < 0x400 | Doubly linked circular | FIFO |
| largebin | ≥ 0x400 | Doubly linked + size-sorted | Sorted |
### Key Global Structures
| Structure | Location | Purpose |
|---|---|---|
| `main_arena` | libc .data segment | Contains bin heads, top chunk, system_mem |
| `mp_` | libc .data | malloc parameters (tcache settings, mmap threshold) |
| `tcache_perthread_struct` | Heap (first allocation) | Per-thread tcache bins and counts |
---
## 2. LEAK METHODS
### Libc Base Leak
| Method | Precondition | Technique |
|---|---|---|
| Unsortedbin fd/bk | Free a chunk > tcache range (or fill tcache) | fd/bk → `main_arena + 0x60` (or +0x70 depending on version) → libc base |
| Smallbin fd/bk | Chunk moved from unsortedbin to smallbin | Same as unsortedbin leak |
| stdout FILE leak | Write to `_IO_2_1_stdout_` | Corrupt `_IO_write_base` to leak libc data (see IO_FILE) |
### Heap Base Leak
| Method | Precondition | Technique |
|---|---|---|
| Tcache fd pointer | Free two tcache chunks, read first's fd | fd → heap address (XOR'd in ≥ 2.32) |
| Fastbin fd | Free two fastbin chunks | fd → heap address |
| UAF read | Use-after-free on freed chunk | Read 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)
| Attack | Primitive Needed | Result |
|---|---|---|
| Fastbin dup | Double free | Arbitrary allocation |
| Unsortedbin attack | Corrupt unsortedbin bk | Write `main_arena` addr to target (used for __malloc_hook nearby overwrite) |
| Unlink attack | Heap overflow into prev_size + fd/bk | Arbitrary write (with known heap pointer) |
| House of Force | Top chunk size overwrite | Arbitrary allocation |
| House of Spirit | Write fake chunk header | Fastbin allocation at fake chunk |
| Off-by-one null | Null byte overflow into next chunk size | Overlapping chunks |
### glibc 2.26–2.28 (tcache, no key)
| Attack | Notes |
|---|---|
| Tcache poisoning | Overwrite tcache fd → arbitrary allocation, no size check |
| Tcache dup | Double free into tcache (no double-free detection yet) |
| All previous attacks | Still work, but chunks go to tcache first |
### glibc 2.29–2.31 (tcache key introduced)
| Attack | Bypass for tcache key |
|---|---|
| Tcache dup | Corrupt `key` field (at chunk+0x18) before second free |
| House of Botcake | Double free: one in unsortedbin, one in tcache → overlapping |
| Tcache stashing unlink | Abuse smallbin→tcache refill to get arbitrary chunk |
### glibc 2.32–2.33 (safe-linking / PROTECT_PTR)
| Attack | Adaptation |
|---|---|
| Tcache poisoning | Encode target with `(chunk_addr >> 12) ^ target` |
| Heap leak required | Need heap addr to decode/encode safe-linked pointers |
| Fastbin dup | Same encoding required |
### glibc ≥ 2.34 (hooks removed)
| Change | Impact |
|---|---|
| `__malloc_hook` removed | Cannot overwrite hook for one_gadget |
| `__free_hook` removed | Cannot overwrite hook |
| `__realloc_hook` removed | Cannot use realloc trick for one_gadget constraints |
**Post-2.34 targets**: see [arbitrary-write-to-rce](../arbitrary-write-to-rce/SKILL.md) for `_IO_FILE`, `exit_funcs`, `TLS_dtor_list`, `_dl_fini`.
---
## 4. COMMON VULNERABILITY PATTERNS
| Vulnerability | Description | Exploitation Path |
|---|---|---|
| UAF (Use-After-Free) | Access chunk after free | Read: leak fd/bk; Write: corrupt fd for tcache poisoning |
| Double Free | free() same chunk twice | Tcache dup (bypass key) or fastbin dup |
| Heap Overflow | Write past chunk boundary | Corrupt next chunk's metadata (size, fd, bk) |
| Off-by-one | One byte overflow | Null byte → shrink next chunk size → overlapping chunks |
| Off-by-null | Specifically `\x00` overflow | Clear PREV_INUSE → trigger backward consolidation |
| Uninitialized read | Read heap memory without clearing | Leak 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)
```
© yaklang · MIT · yaklang/hack-skills