mcpField
H
heap-exploitation

heap-exploitation

github.com/yaklangセキュリティ2.6k3.7k 回インストール6 週間前に更新
リポジトリ

heap-exploitation について

セキュリティ研究者や CTF 参加者向けのヒープエクスプロイト資料です。glibc のバージョンごとにアロケーターの挙動と脆弱性の原語を攻撃手法に結び付け、safe-linking やアドレスリークも扱います。

主な機能

  1. 01ptmalloc2 の chunk・bin リファレンス
  2. 02ヒープ・libc のリーク手法
  3. 03glibc バージョン別の攻撃整理
  4. 04safe-linking のエンコードとデコード
  5. 05一般的なヒープ脆弱性パターン
  6. 06pwndbg のヒープ検査コマンド

活用シーン

  1. 01ヒープ脆弱性の手法選択
  2. 02glibc に応じた tcache poisoning の調整
  3. 03ヒープまたは libc のアドレスリーク調査
  4. 04pwndbg によるアロケーター状態の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yaklang/hack-skills --skill heap-exploitation

インストール後、Claude Code で/heap-exploitationを入力して読み込まれたか確認します。

同梱ファイルHOUSE_OF_TECHNIQUES.mdIO_FILE_EXPLOITATION.md

詳細

スキル:ヒープエクスプロイト — エキスパート向け攻撃プレイブック

AI LOAD INSTRUCTION:glibc ヒープエクスプロイトのエキスパート向けテクニックです。ptmalloc2 の内部構造、ビンの構造、tcache の仕組み、libc/ヒープのリーク方法、glibc のバージョンに応じた攻撃の選択を扱います。ctf-wiki のヒープ関連セクション、how2heap、実際のエクスプロイト事例をもとに要点をまとめています。ベースモデルは glibc のバージョンによる制約を混同しがちで、2.32 で導入された safe-linking(PROTECT_PTR)を見落とすことがよくあります。

0. 関連するルーティング

高度なリファレンス
  • HOUSE_OF_TECHNIQUES.md — House of Force/Spirit/Orange/Einherjar/Roman/Pig/Banana/Cat/Apple と tcache 攻撃
  • IO_FILE_EXPLOITATION.md — _IO_FILE vtable の乗っ取り、FSOP、stdout/stdin の悪用、終了フローのエクスプロイト

1. PTMALLOC2 の構造クイックリファレンス

malloc_chunk のレイアウト(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)│
         └──────────────────────────┘
ビンの種類
ビンサイズ範囲(64-bit)構造LIFO/FIFO
tcache(スレッドごと)≤ 0x410(サイズごとに 7 エントリー)単方向リンク(next ポインター)LIFO
fastbin≤ 0x80(デフォルト)単方向リンク(fd)LIFO
unsortedbin任意の解放済みサイズ双方向循環リストFIFO
smallbin< 0x400双方向循環リストFIFO
largebin≥ 0x400双方向リンク+サイズ順ソート順
主なグローバル構造体
構造体場所目的
main_arenalibc の .data セグメントビンの先頭、top chunk、system_mem を保持
mp_libc の .datamalloc のパラメーター(tcache の設定、mmap のしきい値)
tcache_perthread_structヒープ(最初の割り当て時)スレッドごとの tcache ビンとカウント

2. リーク方法

Libc ベースアドレスのリーク
方法前提条件テクニック
Unsortedbin の fd/bktcache の範囲より大きいチャンクを解放する(または tcache を埋める)fd/bk → main_arena + 0x60(バージョンによっては +0x70)→ libc ベースアドレス
Smallbin の fd/bkチャンクが unsortedbin から smallbin に移動しているunsortedbin のリークと同じ
stdout FILE のリーク_IO_2_1_stdout_ に書き込む_IO_write_base を破壊して libc データをリークする(IO_FILE を参照)
ヒープベースアドレスのリーク
方法前提条件テクニック
Tcache の fd ポインターtcache のチャンクを 2 つ解放し、先のチャンクの fd を読み取るfd → ヒープアドレス(≥ 2.32 では XOR 化)
Fastbin の fdfastbin のチャンクを 2 つ解放するfd → ヒープアドレス
UAF 読み取り解放済みチャンクに対する Use-After-Freefd/bk を直接読み取る
Safe-Linking のデコード(glibc ≥ 2.32)
# 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. glibc のバージョン別攻撃カテゴリ

glibc < 2.26(tcache なし)
攻撃必要なプリミティブ結果
Fastbin dup二重解放任意の割り当て
Unsortedbin attackunsortedbin の bk を破壊ターゲットに main_arena のアドレスを書き込む(__malloc_hook 付近の上書きに使用)
Unlink attackヒープオーバーフローで prev_size と fd/bk に到達任意書き込み(ヒープポインターが既知の場合)
House of Forcetop chunk のサイズを上書き任意の割り当て
House of Spirit偽のチャンクヘッダーを書き込む偽チャンク上で fastbin 割り当て
Off-by-one null次のチャンクのサイズへのヌルバイトオーバーフローチャンクの重複
glibc 2.26–2.28(tcache あり、キーなし)
攻撃備考
Tcache poisoningtcache の fd を上書き → 任意の割り当て。サイズチェックなし
Tcache duptcache への二重解放(まだ二重解放の検出なし)
以前のすべての攻撃引き続き有効。ただし、チャンクはまず tcache に入ります
glibc 2.29–2.31(tcache key の導入)
攻撃tcache key の回避方法
Tcache dup2 回目の free の前に key フィールド(chunk+0x18)を破損させる
House of BotcakeDouble free:unsortedbin に 1 つ、tcache に 1 つ → 重なり合うチャンク
Tcache stashing unlinksmallbin→tcache の補充を悪用して任意のチャンクを取得する
glibc 2.32–2.33(safe-linking / PROTECT_PTR)
攻撃対応方法
Tcache poisoning(chunk_addr >> 12) ^ target でターゲットをエンコードする
ヒープリークが必須safe-linked ポインターのデコード/エンコードにはヒープアドレスが必要です
Fastbin dup同じエンコードが必要です
glibc ≥ 2.34(フックの削除)
変更影響
__malloc_hook が削除one_gadget のためにフックを上書きできません
__free_hook が削除フックを上書きできません
__realloc_hook が削除one_gadget の制約に realloc トリックを使用できません

2.34 以降のターゲット:_IO_FILE、exit_funcs、TLS_dtor_list、_dl_fini については、arbitrary-write-to-rce を参照してください。


4. よくある脆弱性パターン

脆弱性説明悪用方法
UAF(Use-After-Free)free 後にチャンクへアクセスする読み取り:fd/bk をリークする。書き込み:fd を破損させて tcache poisoning を行う
Double Free同じチャンクを 2 回 free() するTcache dup(key を回避)または fastbin dup
ヒープオーバーフローチャンクの境界を越えて書き込む次のチャンクのメタデータ(size、fd、bk)を破損させる
Off-by-one1 バイトのオーバーフローヌルバイト → 次のチャンクのサイズを縮小 → チャンクを重ね合わせる
Off-by-null特定の \x00 オーバーフローPREV_INUSE をクリア → 後方統合を発生させる
未初期化読み取りクリアせずにヒープメモリを読み取る再利用されたチャンクから fd/bk をリークする

5. ツール

# 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. 決定木

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)

コメント