ACTION REQUIRED(読んだらすぐ実行)
NOW:../field-journal/precedent-reverse.mdを読む — 本スキルの操作が許可された通常操作であることを確認NOW: 現在のタスクが本スキルの適用範囲に該当するか確認NEXT:../tool-index.mdを読み、ツールの可用性と実際のパスを検証NEXT: ツールがない場合はbootstrapを呼び出し、パスを推測しないACT: 「ワークフロー」の最初のステップに進み実行、確認状態で停止しない
脆弱性箇所から動作するエクスプロイトへ (Pwn Chain)
適用範囲
以下のシナリオで本スキルを使用します:
- バイナリ + 既知の脆弱性箇所 — 静的解析/監査/fuzzでオーバーフロー/UAF/ダブルフリーが見つかり、トリガーからシェル取得までが必要
- CTF問題がローカルでは通るがリモートでは通らない — リモート環境の差異でスクリプトが動作せず、安定化が必要
- 実ターゲットのバイナリエクスプロイト — SRC/レッドチームのシナリオでメモリ破壊の脆弱性が特定済み、RCEの構築が必要
- Linuxカーネルドライバのioctlバグ — ユーザーランドからトリガーし、ルート権限奪取が目標
前提: 「どこが壊れるか」は既に分かっていること。本スキルは脆弱性の発見(ファジング/監査)は担当せず、「脆弱性箇所からエクスプロイトを書く」ことのみを担当します。
他のスキルとの役割分担
| シナリオ | 使用スキル |
|---|---|
| カスタムVM / アンチデバッグ / 複雑な難読化の特定 | reverse-engineering/ |
| ゼロからバイナリの静的解析 | ida-reverse/ または radare2/ |
| 脆弱性箇所があり、エクスプロイトを書いてリモートを通す | 本スキル |
| pwnで取得したシェルを完全な攻撃チェーンに統合 | attack-chain/(下流) |
reverse-engineering/ は「プログラムが何をしているか」の理解(パターン認識、プロトコル復元、CTF問題の奇妙な仕組みの解読)に焦点を当てます。本スキルは「既に理解した脆弱性を実行可能な攻撃にする」ことに焦点を当てます。両者はしばしば併用されますが、役割は明確に分かれています。
コアワークフロー
Step 1: 脆弱性タイプ + 保護機構の確認
├─ checksec ./vuln(NX / Canary / PIE / RELRO / Fortify)
├─ file ./vuln + readelf -d ./vuln
├─ 脆弱性分類:スタックオーバーフロー / フォーマット文字列 / ヒープ (UAF/DF/OF) / 整数 / 競合 / カーネル
└─ → どの references/ を使うか決定
Step 2: エクスプロイト戦略の選択
├─ NX オフ + ASLR 無効 → 直接 shellcode
├─ NX オン + libc あり → ret2libc / one_gadget
├─ NX オン + libc 無し → leak 後 libc-database で逆引き
├─ ヒープ → glibc バージョンに応じた技術 (tcache/fastbin/unsorted/large)
└─ カーネル → commit_creds / modprobe_path / core_pattern
Step 3: libc + gadget の準備
├─ libc-database:./find puts 0x6f0
├─ ROPgadget --binary ./libc.so.6 --only "pop|ret"
├─ one_gadget ./libc.so.6
└─ base の計算:leak_addr - libc.sym['puts']
Step 4: pwntools テンプレートを書く(ローカル process)
├─ context.binary = ELF('./vuln')
├─ p = process('./vuln') / p = gdb.debug('./vuln','b *main+xx')
├─ payload = cyclic(N) + p64(ret) + ...
└─ p.interactive()
Step 5: ローカルを通す
├─ 繰り返し attach + レジスタ確認 + オフセット調整
├─ pwndbg/GEF の vmmap / heap / bins / telescope を使用
└─ 通ったら remote() に切り替え
Step 6: リモート安定化
├─ libc オフセット:leak から libc-database で逆引き、当てずっぽう禁止
├─ スタックアライメント:16バイト未アライン → movaps クラッシュ → ret gadget を1つ追加
├─ リモートネットワーク遅延 → recvuntil で文字列を正確にアンカー、曖昧な sleep は禁止
├─ リモートバッファ:sendlineafter の方が sendline より安定
├─ ヒープスプレー成功率:スプレー量を増やす + マージ防止用の padding chunk を残す
└─ 複数回実行:while True で成功率 95% 以上を確認
典型的なシナリオ
シナリオ 1:リモート 64ビットバイナリ (NX+PIE+canary, libcあり)
既存:./vuln(64-bit ELF, NX, PIE, canary)+ ./libc.so.6 + nc host port
脆弱性:read(buf, 0x200) だが buf は 0x40 バイト → スタックオーバーフロー
保護機構:canary が邪魔、PIE で .text がランダム化
戦略:
1. まず canary をリーク(スタック/フォーマット文字列/部分読み取り)
2. 次に libc 関数のアドレスをリーク(puts@got)
3. libc.address = leaked - libc.sym['puts'] で libc base を計算
4. one_gadget ./libc.so.6 で制約を満たせるマジック gadget を選択
5. payload = padding + canary + saved_rbp + (pop_rdi + bin_sh + system) または one_gadget 直接
6. ret gadget を1つ追加してスタックアライメントを修正(重要!)
完全なテンプレートは references/stack-pwn.md を参照。
シナリオ 2:Linuxカーネルドライバ ioctl 境界外書き込み → ルート奪取
既存:vmlinux + bzImage + initramfs.cpio.gz + カスタム vuln.ko
脆弱性:ioctl(0x1337, ptr) 内で copy_from_user の長さが制御可能 → kernel heap overflow (kmalloc-64 slab)
保護機構:SMEP, SMAP, KASLR, KPTI
戦略:
1. init スクリプトを編集して root シェルを取得(CTF)またはまず KASLR base をリークしてから続行(実ターゲット)
2. /proc/kallsyms(権限制限あり)または未初期化ヒープスプレーでカーネルベースアドレスをリーク
3. kmalloc-64 slab に tty_struct / msg_msg / pipe_buffer をスプレー
4. vtable ポインタをユーザーランドに向けて上書き → 不可(SMEP)、代わりに stack pivot + カーネルROP
5. ROP チェーン:prepare_kernel_cred(0) → commit_creds → swapgs+iretq → ユーザーランド execve("/bin/sh")
6. またはより簡単:modprobe_path を "/tmp/x" に上書き、/tmp/x を作成し、modprobe をトリガー
完全なテンプレートは references/kernel-pwn.md を参照。
オンデマンドブートストラップ (On-Demand Bootstrap)
ツール依存関係
| ツール | 用途 | インストール方法 |
|---|---|---|
| pwntools | エクスプロイト作成フレームワーク | pip install pwntools |
| GEF | gdb 拡張(カーネル + ユーザーランド推奨) | git clone https://github.com/bata24/gef (fork は活発にメンテナンス中) |
| pwndbg | gdb 拡張(ヒープデバッグの体験が最良) | git clone https://github.com/pwndbg/pwndbg && ./setup.sh |
| ROPgadget | gadget 検索 | pip install ropgadget |
| Ropper | gadget 検索(代替、対応アーキテクチャ多数) | pip install ropper |
| one_gadget | libc マジック gadget 検索 | gem install one_gadget(ruby が必要) |
| libc-database | libc フィンガープリント逆引き | git clone https://github.com/niklasb/libc-database && ./get |
| qemu-system-x86_64 | カーネル問題のデバッグ | apt install qemu-system-x86 |
| binwalk / cpio | initramfs の展開 | apt install binwalk cpio |
| patchelf | libc バージョンの切り替え | apt install patchelf |
Bootstrap 確認スクリプト
# 一発でコアツールを確認 + インストール
for t in pwntools ropgadget ropper; do
pip show $t >/dev/null 2>&1 || pip install $t
done
command -v one_gadget >/dev/null || gem install one_gadget
[ -d ~/tools/libc-database ] || git clone https://github.com/niklasb/libc-database ~/tools/libc-database
[ -d ~/tools/libc-database/db ] || (cd ~/tools/libc-database && ./get ubuntu debian)
[ -d ~/tools/pwndbg ] || (git clone https://github.com/pwndbg/pwndbg ~/tools/pwndbg && cd ~/tools/pwndbg && ./setup.sh)
同一ツールの自動インストールが2回連続で失敗した場合
リトライを停止し、構造化された手動インストール手順(pip ソース / gem ソース / git 国内ミラー / apt ソース)を出力してユーザーに確認を求めます。
ルーティングコンテキスト
上流エントリ: skills/SKILL.md(全体制御)、routing.md
トリガー条件: バイナリがあり、脆弱性箇所が特定され、エクスプロイトの作成が必要
上流スキル(先にそれらを使用してから本スキルに戻る):
- バイナリが何をしているかまだ理解できていない →
reverse-engineering/ - 詳細な静的解析が必要 →
ida-reverse/ - アーキテクチャ/保護機構の迅速な偵察 →
radare2/
下流スキル(シェル取得後):
- 完全な攻撃チェーンへの統合(横移動、権限昇格、永続化) →
attack-chain/
サブモジュールナビゲーション:
- スタック系エクスプロイト(ret2libc / ret2csu / one_gadget / スタックアライメント) →
references/stack-pwn.md - ヒープ系エクスプロイト(tcache / fastbin / unsorted / large bin / FILE struct) →
references/heap-pwn.md - カーネル pwn(kROP / SMEP-SMAP バイパス / KASLR leak / modprobe_path) →
references/kernel-pwn.md
注意事項
- ローカルで通ったからといって完了しないこと — ローカルの libc / ASLR / ネットワーク環境はリモートと異なる。remote モードで20回以上連続実行して安定性を確認すること
- libc バージョンは必ず確認すること — leak + libc-database で逆引きし、Ubuntu 22.04 デフォルトの libc と決めつけない
- スタックアライメントは64ビットのよくある落とし穴 —
movaps xmm0, [rsp]が rsp 16バイト未アライン時にセグフォを起こす。空のretgadget を1つ追加して解決 - ヒープエクスプロイトは glibc バージョンに極めて敏感 — tcache は 2.27 で導入、safe-linking は 2.32 で導入、2.34 で hooks 削除。バージョンごとに利用経路が異なる
- カーネル pwn ではまず cpu フラグを確認すること — qemu 起動パラメータに +smep +smap +pku があるかどうかで ROP チェーンの書き方が直接決まる
- KASLR リークは1回で十分 — 1つのカーネルアドレスを取得すれば、全アドレスをオフセットで計算可能。繰り返しリークする必要なし
タスク完了自己チェック(完了を宣言する前に MUST で通過)
- ワークフローの各ステップを実行したか(単に読んだだけではない)?
-
tool-indexに基づいて実際のツールパスを使用したか? - 再現可能な証拠(コマンド/スクリプト/スクリーンショット/レポート)を生成したか?
- RULES で要求される Checklist 項目を完了し、書き戻したか?