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

【Pwn入門編】x86/x64アセンブリと関数呼び出し規約をスッキリ整理|CTF思考フレームワーク #58

【Pwn入門編】x86/x64アセンブリと関数呼び出し規約をスッキリ整理|CTF思考フレームワーク #58 アイキャッチ画像
安全に生きたい編集部

広告・PRを含みます。この記事にはアフィリエイトリンクが含まれます。掲載内容は編集方針に基づいて作成していますが、価格・在庫・キャンペーン内容はリンク先で最新情報を確認してください。

Pwn って何?アセンブリも出てくるけど…めっちゃ難しそう😰

Pwnはバイナリ脆弱性を突く競技。x86/x64のアセンブリと、関数呼び出し規約(calling convention)を理解しないと始まりません。でも基礎を押さえれば、低レイヤーの世界が一気に見えてきます。

Pwn は CTF の花形カテゴリ。バッファオーバーフロー、ROP、ヒープエクスプロイトなど、CやC++で書かれたバイナリの脆弱性を突きます。x86/x64 アセンブリ、レジスタの役割、スタックの構造、calling convention(cdecl/stdcall/System V AMD64 ABI)の理解が必須。

アセンブリ、見るだけでクラクラする…でも基礎押さえれば見えるんだね。

この記事は、CTF思考フレームワーク第58回。Pwn入門としてx86/x64アセンブリと関数呼び出し規約を整理。レジスタ・スタック・呼び出し規約の基本、GDB/peda/pwntools の使い方、最初の一歩を解説します。

📖 この記事はシリーズの一部です
CTF思考フレームワーク#58 / 全86記事 → シリーズ一覧を見る →

🛠️ Pwnの第一歩は「アセンブリと関数呼び出し規約をスッキリ理解する」こと。レジスタ・スタック・ヒープの物理的なお約束を握れば、バッファオーバーフローも「ROPに必要な部品集め」も怖くなくなります。

x86とx64で呼び出し規約が違う、Linux ABIとWindows ABIで違う。Pwnの問題で詰まる多くは「なぜここに値が入るのか」を物理レイアウトで掴めていないとき。スタック図を描く癖が最重要。

難易度:★★☆(中級)

x86/x64アセンブリと関数呼び出し規約をスッキリ整理します🐧

Pwnの第一歩はアセンブリと呼び出し規約を理解すること。これがないと何も始まらない🐧

この記事で出てくる言葉

先に意味を押さえておくと読みやすい用語です。

  • CTF: セキュリティの練習問題を解く競技。必ず許可された環境だけで試します。
  • Pwn: バイナリの不備を突いてプログラムの制御を奪うCTF分野です。
  • ヒープ: プログラムが実行中に動的に使うメモリ領域です。
  • スタック: 関数呼び出しや一時データを積み上げて管理するメモリ領域です。

👀 観察フェーズ:まず何を見る?

まずfilechecksecでアーキ・ビット・保護機構を観察🔍

バイナリを渡されたら、アーキテクチャ・呼び出し規約・保護機構を確認。x86/x64、Linux ELF、保護フラグはchecksecで一発。

  • file でアーキテクチャ判定
  • checksec でNX/PIE/Canary/RELRO
  • 呼び出し規約:x86=cdecl/stdcall(スタック)、x64=System V(rdi,rsi,rdx,rcx,r8,r9)
  • スタックフレーム:rbp(ベース)、rsp(トップ)
  • callerが戻り番地をpush、calleeが ret で pop
  • 関数プロローグ:push rbp; mov rbp,rsp; sub rsp,N

基本ツール: objdump / readelf / pwndbg / pwntools / Ghidra。まずはobjdump -dで全関数を眺めます👀

x86_64の引数はrdi, rsi, rdx, rcx, r8, r9の順、x86は全部スタックなんだね💡

🤔 仮説フェーズ:攻撃者は何を考える?

Pwn入門の重要4要素。

🕶️ 攻撃者は「ret命令で読まれるスタック上の戻り番地」をどう書き換えるかを考えます。x86なら引数も全部スタック、x64ならまずrdi等のレジスタ、それを越えてからスタック。「制御の窃取」と「データの仕込み」をスタック図で同時に設計するのがPwnの基本動作。

🧱 仮説①:レジスタとスタック

rsp/rbpがスタックポインタ、ripが次命令。関数呼び出し時のスタックフレームが肝。

📞 仮説②:呼び出し規約

x86_64 System Vはrdi, rsi, rdx, rcx, r8, r9。Windows x64はrcx, rdx, r8, r9。混同事故が多い。

🚪 仮説③:プロローグとエピローグ

push rbp / mov rbp, rsp / sub rsp, Xで関数開始、leave / retで終了。retがpop ripに等しいのが攻略点。

🔧 仮説④:保護機構の有無

checksecNX/PIE/Canary/RELROを確認。組み合わせが攻略難易度を決める。

Pwnは「メモリレイアウトの想像力」がすべての始まり💡

🔬 検証フェーズ:どうやって確かめる?

pwntoolsのprocess()gdb.attach()でデバッグ→cyclicでオフセット特定が王道🧪

練習はpicoCTF・OverTheWire・pwnable.kr等のプログレッシブな環境で。gdb-pwndbg / gef / gdb peda を入れて checksec vmmap tele を駆使。

# checksec
checksec --file=./chall
# RELRO / Canary / NX / PIE / RPATH / RUNPATH / Symbols / FORTIFY

# gdb で関数の disassemble
gdb ./chall
pwndbg> disassemble main
pwndbg> b *vuln+42
pwndbg> r
pwndbg> tele $rsp 30

pwndbgのvmmap / telescopeはメモリ調査の最強ツールだね💡

⚔️ 攻撃フェーズ:実際の手口

入門で身につける3つ。

基本動作:①引数がレジスタ/スタックのどちらに来るか、②戻り番地の場所、③ret時に何が読まれるか、を正確に描いてからexploitを設計。

# x64 System V呼び出し規約
# 第1引数: rdi
# 第2引数: rsi
# 第3引数: rdx
# 第4引数: rcx
# 第5引数: r8
# 第6引数: r9
# それ以降: スタック

# 例:system("/bin/sh") をx64で呼ぶ
# 1. rdi に "/bin/sh" のアドレスを置く
# 2. system のアドレスへジャンプ

Pwnを始めると「電卓みたいに16進アドレスが脳内で扱える」ようになります🤓 最初は紙に書きながらでOK、慣れます

① cyclicパターンでオフセット特定

cyclic 200を入力→クラッシュ時のRIPの値からオフセットを逆引き。BoFの基本動作。

② 関数呼出変数の改ざん

スタック上のローカル変数を書き換えて、if (admin == 1)を突破する練習問題が頻出。

③ ret2win

プログラム中に存在するwin()関数のアドレスにretでジャンプするシンプルなPwn。

🛡️ 防御フェーズ:どう守る?

入門段階での守り意識3点。

守備側は「呼び出し規約を悪用させない仕組み」(CFI、shadow stack等)を理解。コンパイラオプションとOSの保護機構を全部入りにするのが最低ライン。

  • -fstack-protector-strong(Stack Canary)
  • -D_FORTIFY_SOURCE=2(バッファ関数強化)
  • NX / DEP(実行不可スタック)
  • PIE / ASLR(アドレス空間ランダム化)
  • CET / Shadow Stack(Intel CET)
  • コンパイラの-fcf-protection
🚫 strcpy / gets / sprintf を使わない

C言語の境界チェックのない関数がPwnの源泉。modern C++/Rustやsafe wrapperを選ぶ。

🛡️ コンパイラ保護機構を全有効化

-fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro,-z,now標準的攻撃を激減

🦀 Rust / Goで書き直し

新規コードはメモリ安全な言語へ。7割のCVEがメモリ安全性に起因。

Pwnは「攻撃を理解しないと守れない」典型例だね💪

🧪 pwn検証用のLinuxラボ

Pwnやエクスプロイトの練習は、必ず自分の検証環境で。💻 ConoHa VPSならLinuxをワンクリックで立てて、gdb-pedaやpwntoolsを仕込んでそのままトレーニングできます。

PR / 広告

ConoHa VPS

※ 上記は他社サービスへのリンクです。購入は各自でご判断ください。

⚠️ よくある落とし穴

  1. 32bitと64bitで引数渡しが違うのを忘れる
  2. スタックの伸び方向(高→低)を逆に図示
  3. ret命令で読むのは「rspが指す8バイト」のみ
  4. cannary(カナリア)の有無確認を怠り謎の落ち方をする
  5. PIEのため絶対アドレスが毎回変わる事実を無視
  6. Linux/Windowsの呼び出し規約差を意識しない

🧰 ツール早見表

ツール用途備考
gdb + pwndbg / gefデバッグ環境の決定版tele/vmmap/checksec
pwntoolsPythonのexploit骨格process/p64/u64/asm
Ghidra / IDA Free逆コンパイル関数構造の把握
ROPgadget / roppergadget抽出ROP用
one_gadget1命令でshellを取れるアドレスlibc解析向け

🎓 本気で学びたい人へ

ローレベルやOSレベルの許可を、仕事として深く学びたい方へ。🎓 ササエルはインフラとセキュリティの両方を学べるスクールです。

PR / 広告

ササエル

📚 もっと深く学びたい人へ

実際に手を動かして攻撃手法を体で覚えたいなら『7日間でハッキングをはじめる本 TryHackMe』がおすすめ📚

📚 次に読みたい

✍️ 学んだことを発信する

検証ノートをブログで公開したい方は、高速で安価なConoHa WINGが使いやすいです。

PR / 広告

ConoHa WING

⚖️ 大事なお約束

必ず守ってね

この記事の手法は、必ず自分の環境か、許可されたCTF・脆弱性報奨金プログラム(HackerOne、Bugcrowd等)で試してください。他人のサービスに無断で攻撃を仕掛けるのは不正アクセス禁止法違反、立派な犯罪です。学んだ知識は守る側で活かしましょう🤝

この記事は合法な学習・防御目的での解説です。許可のないシステムへの攻撃は犯罪になります(不正アクセス禁止法ほか)。検証は必ず自分が管理する環境・CTF・公式ハンズオンで行ってください🙏

記事URLをコピーしました