PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【Pwn総まとめ編】実戦シナリオとチートシートで完走する|CTF思考フレームワーク #66

かも次郎とアンペンが「Pwn総まとめ」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

今回はPwn章の最終回、実戦シナリオとチートシートでこれまでの全技術を統合します。#58のアセンブリ基礎から、#59 BoF、#60 ROP、#61 FSB/GOT、#62-#64 Heap三部作、#65 保護機構と続いた一連の知識を、『CTF本番で問題を開いた瞬間にどう動くか』の定型ルーチンに落とし込みます。

Pwn問題は『時間勝負』。バイナリの種類・保護状況・配布ファイル(libc.so.6の同梱有無)から、最初の3分で攻略方針が決まれば後は実装作業に集中できます。チートシートをそばに置けば、本番でも手が止まりません。

総まとめ回でいちばん伝えたいのは、『Pwnは才能ではなく“型”だ』ということです。問題を開いて固まってしまうのは、知識が足りないからではなく、“最初に何を見るか”の手順が決まっていないから。逆に、見る順番さえ体に入れば、初見の問題でも淡々と前に進めます。今日はその“型”を、チートシートとテンプレという形で持ち帰ってください。

Pwn問題を開いたら、まず何を見ればいい?

(1)checksec、(2)file/strings、(3)Ghidra/IDAでmain読み、(4)libcバージョン特定、(5)脆弱性候補リストアップ。この5ステップで作戦が決まる。あとは脆弱性タイプ別の決め技を当てはめるだけ。

まず結論

Pwn問題攻略の定型ルーチン5ステップ:(1)checksecで保護状況、(2)file/strings/Ghidraで全体把握、(3)libc-databaseでlibc特定、(4)脆弱性タイプ分類(BoF/UAF/FSB/Race/整数オーバーフロー等)、(5)タイプ別の決め技で突破口決定。脆弱性タイプ別『決め技マップ』を覚えれば、本番でも手が止まりません。pwntoolsテンプレを『リーク→計算→送信』の3段で用意しておけば、毎回ゼロから書かずに済みます。

この記事で分かること

  • Pwn問題攻略の定型5ステップ
  • 脆弱性タイプ別の決め技マップ(BoF/UAF/FSB/Race/整数)
  • pwntools テンプレートの3段構造
  • 本番で時間短縮のコツ
  • Pwn全章の振り返り(#58〜#66)
難易度:総まとめ 所要時間:12分 体験:テンプレで2問解く おすすめ:#65の後

📖 はじめてのWebセキュリティ #66|Pwn総まとめ編
実戦シナリオとチートシートで完走する。 シリーズ一覧を見る →

⚠️ 大事なお約束
本番システムへのexploitは違法。CTF・自作バイナリのみで確認してください。

Pwn問題の定型ルーチン5ステップ

  • ①checksec:4項目(Canary/NX/PIE/RELRO)の状態 → 必要なリーク経路と防御の壁が見える(#65参照)
  • ②file/strings/Ghidra:動的リンクか静的か、strippedか、main関数の所在、補助関数(win等)の存在、文字列リソースから機能推定
  • ③libc特定:配布されたlibc.so.6があればそれを直接使う。なければリーク値1〜2個からlibc-databaseで照合(./find puts 0xXXXXXX)
  • ④脆弱性分類:main関数を読みながらBoF/UAF/Double Free/FSB/Off-by-one/Race/整数オーバーフローのどれかを当てる。複数共存もある
  • ⑤突破口決定:分類に応じてリーク経路・計算式・ペイロード構造を決定。あとは実装するだけ

この5ステップは、料理でいう“下ごしらえ”のようなものです。いきなり炒め始める(exploitを書き始める)前に、まず食材を確認し(checksec)、レシピを読み(Ghidra)、調味料をそろえる(libc特定)。下ごしらえが済んでいれば、あとの調理は迷いません。逆にここを飛ばすと、途中で『あれが無い、これが違う』と手が止まる。急がば回れ、の典型ですね。

checksec・静的解析・libc特定・脆弱性分類・突破口決定の5ステップPwn攻略ルーチン図解
図1:Pwn問題は5ステップで攻略
⚔️ たとえるなら、対戦ゲームのキャラ別必殺技

対戦ゲームでは『相手キャラ(=脆弱性タイプ)』が決まれば、こちらが使う『必殺技(=攻撃手法)』はほぼ固定。BoFなら『ret2win or ret2libc』、UAFなら『vtable hijack』、FSBなら『%nでGOT書換 or libcリーク』、ヒープなら『tcache poisoning → __free_hook』。チートシートを手元に置いておけば、CTF本番でも手が止まらず、残り時間を実装と微調整に集中できます。

ここで覚える用語:pwntoolsテンプレート
pwntools(from pwn import *)を使う典型コード骨格。elf = ELF('./vuln')でバイナリ読込、libc = ELF('./libc.so.6')でlibc読込、p = process('./vuln') if args.LOCAL else remote(host, port)でローカル/リモート切替、p.recvuntil()/p.sendline()で対話、p.interactive()でシェル獲得後の手動操作。1回作って使い回せば、問題ごとにペイロード組立部分だけ書き換えれば済みます。

脆弱性タイプ別 決め技チートシート

  • BoF (canary off): ret2win(win関数あれば)→ret2libc(なければ)。x64はret-gadgetでmovaps対策
  • BoF (canary on): canary leak経路(FSB/部分書込/fork brute-force)を探す→canaryを再現してret書換
  • UAF / Double Free: 同サイズ malloc/free操作で再利用誘導→vtable hijack or tcache poisoning→__free_hook(glibc < 2.34) or _IO_FILE
  • FSB: %p列挙でstack位置特定→libc/canaryリーク→fmtstr_payload(off, {got: target})でGOT書換
  • Off-by-one: 上位/下位1バイト改竄→隣接チャンクのsize書換→overlapping chunksを作成→好きな場所にmalloc誘導
  • Race condition: マルチスレッド/シグナルで競合→TOCTOU(check-time-of-use-time)で前提を覆す
  • 整数オーバーフロー: 巨大なsize計算で結果が小さくなる→小さいbufに大量書込が成立→BoFやheap-bofに連鎖
  • Type confusion(C++/V8等): 型キャストエラーで構造体メンバが別解釈→任意R/Wプリミティブへ

このチートシートは、丸暗記するより“引ける状態”にしておくのが正解です。本番でやることは、①で見た保護状況と④で分けた脆弱性タイプを、この表に突き合わせるだけ。『canary無しBoF=ret2win/ret2libc』『UAF=vtable乗っ取り』と、対応が一目で引ければ、悩む時間がゼロになります。最初は表を見ながらでOK。何度も引くうちに、自然と手が覚えていきます。

対戦ゲームのキャラ別必殺技に例えた脆弱性タイプ別決め技のたとえイラスト
図2:タイプが決まれば必殺技も決まる

pwntoolsテンプレート(3段構造)

  • 初期化部: context.binary = elf = ELF('./vuln') / libc = ELF('./libc.so.6') / p = process(...) if args.LOCAL else remote(host, port)
  • リーク部: p.recvuntil(b'> ')p.sendline(payload_leak)leak = u64(p.recv(8))
  • 計算部: libc.address = leak - libc.symbols['puts']log.info(f'libc base: {hex(libc.address)}')
  • 送信部: 2回目のpayload送信 → p.interactive()

テンプレ運用のコツは、『毎回ゼロから書かない』こと。リーク→計算→送信の3段は、どの問題でもほぼ同じ骨格です。だから一度きれいに書いたものを template.py として保存し、問題ごとに“ペイロードを組む部分だけ”差し替える。これだけで、つまらないタイプミスや初期化忘れが激減し、頭を本質(脆弱性をどう突くか)に集中させられます。

リーク→計算→送信のpwntools標準テンプレートPythonコード図解
図3:pwntoolsテンプレ(リーク→計算→送信)

CTFでやってみよう:テンプレで2問連続攻略

やってみよう / 自分の環境・CTFのみ

異なる脆弱性タイプを連続で解いてテンプレを習熟する

目的は『1問目で時間使っても、2問目以降は型化されて早くなる』を体感することです。テンプレをtemplate.pyとして保存しておけば、毎回コピーから始められます。

  1. pwntoolsテンプレを template.py に貼り付け、ベース確保
  2. 1問目: 単純なBoFバイナリ(canary無し / PIE無し) → ret2libcで攻略。リーク→計算→送信の3段を実装
  3. 2問目: menu型UAF + tcache poisoning → vtable hijackで攻略
  4. 解いたら『解き方の流れ』を1行メモ(『libcリーク→ROP』『UAF→tcache→hook』等)
  5. 同じテンプレで別ジャンルもいくつか(FSBバイナリ、Off-by-one等)
  6. 気付いた小ネタ(x64アライメント、libc文字列の探し方等)をcheatsheet.mdに追記
  7. 余裕があれば pwn.college / picoCTF / overthewire / HackTheBox Starting Pointで実戦練習
  8. 定期的にCTF(CTFtime.orgでスケジュール確認)に参加し、本番で時間内に解く経験を積む
本番システムには絶対適用しないこと。CTF・自作バイナリ・許可済み環境のみ。

守る側:『すべてON+メモリ安全言語+監視』の総まとめ

Pwn対策の総まとめ(優先度順)
  • 新規プロジェクトはRust/Go等のメモリ安全言語を選ぶ ── これだけで多くの脆弱性が構造的に排除される
  • C/C++を続けるなら全保護機構ON(-fstack-protector-strong -fPIE -pie -Wl,-z,relro -Wl,-z,now -D_FORTIFY_SOURCE=2 -fcf-protection=full)
  • 境界チェックなし関数(gets/strcpy/sprintf/strcat)を禁止。コードレビューと静的解析(cppcheck/clang-tidy)で検出
  • 開発・CIにASan+UBSan+libFuzzer/AFL++を組込、未知バグを継続的に発見
  • CIでchecksecを成果物に対して回し、退化を即検出。1項目でも欠ければビルド失敗
  • 本番にはWAF/EDR+クラッシュ集約監視(同一プロセスの繰り返しクラッシュは自動exploitの兆候)
  • 定期的なレッドチーム演習で実戦的に弱点を洗う、脅威モデリングを年1回更新
  • サプライチェーン(依存ライブラリ)も常に最新化、CVEは即時パッチ適用

『定型ルーチン+チートシート』でPwnが楽しめるようになるね!

これでPwn章完結。次回からは新章OSINT編。公開情報だけで世界を読み解く思考を扱うよ。

まとめ:『定型5ステップ+チートシート+テンプレ』で完走

今回のポイント
  • 定型ルーチン:checksec→静的解析→libc特定→分類→決め技の5ステップ
  • 脆弱性タイプ別の決め技マップを頭に入れる
  • pwntoolsテンプレで『リーク→計算→送信』を高速化
  • 守りは全保護ON+メモリ安全言語+Fuzz+監視+レッドチームの多層
  • 本番経験はpicoCTF/pwn.college/HackTheBoxで継続的に

ここまで来たあなたは、もうアセンブリの読み方からヒープの最新攻撃、そして守りの全保護機構までを一周しました。#58から始まったPwnの旅は、これでひと区切りです。大切なのは“完璧に覚える”ことではなく、“型と地図を持って、迷わず手を動かせる”こと。あとは実戦で場数を踏むほど、この型は鋭くなっていきます。お疲れさまでした——Pwn章、完走です!

次回からはOSINT章。公開情報だけで世界を読み解く思考を扱います。Pwnとは違うベクトルですが、攻撃者の発想を理解するためには必須です。

次に読みたい記事

参考資料

次に読みたい記事

未経験からセキュリティ・インフラエンジニアを目指すロードマップ

CTFの先のキャリア。インフラ基礎固めから就職までの4ステップ。

記事URLをコピーしました