リバースエンジニアリングとPwnの基礎
リバースエンジニアリングとバイナリ exploitの入門を学びます。
「リバースエンジニアリングとPwnの基礎」はCoddyKit上の無料Cyber Security Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCyber Security Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Cyber Security Academyコースには全4レッスンが含まれています。
リバースとPwnの概要
コンパイル済みプログラムを扱う、密接に関連した2つのCTFカテゴリがあります。
- リバースエンジニアリング(rev) — バイナリを解析して動作を理解します。多くの場合、パスワードチェックやフラグを表示する隠れたロジックを復元することが目的です。
- Pwn(バイナリエクスプロイト) — 実行中のバイナリにあるメモリ安全性のバグを見つけ、それを悪用して実行を乗っ取ります。フラグを保持するリモートサービス上でシェルを起動することがよくあります。
Revは理解すること、pwnは壊すことが中心です。どちらにも低レベルの概念に慣れていることが求められます。
バイナリを最初に確認する
バイナリをいきなり逆アセンブラで開いてはいけません。まずはコマンドラインの簡単なツールでトリアージし、種類、アーキテクチャ、明らかな文字列の有無を確認します。
# Identify file type and architecture
file ./challenge
# Pull human-readable strings (flags are sometimes left in plaintext)
strings ./challenge
# Check which security mitigations are enabled
checksec --file=./challenge静的解析と動的解析
バイナリは、相互に補完し合う2つの方法で解析します。
- 静的解析 — Ghidraや逆アセンブラのビューなどの逆アセンブラまたはデコンパイラを使い、実行せずにコードを読みます。制御フロー全体を確認できますが、実行時の値は推測しなければなりません。
- 動的解析 — GDBなどのデバッガーでプログラムを実行し、レジスタやメモリの実際の値を観察します。何が起きるかを正確に確認できますが、実行した経路に限られます。
熟練したプレイヤーは両者を切り替えます。静的に読んで仮説を立て、ステップ実行して動的に確認します。
逆アセンブリを読む
リバースでは、アセンブリを読みます。流暢に書ける必要はありませんが、パターンを認識できなければなりません。
- cmp / testの後にジャンプ(
je、jne)がある場合は、比較と分岐を表します。多くの場合、これがパスワードチェックです。 - callは関数を呼び出します。引数はその直前にレジスタまたはスタックへ配置されています。
- movはレジスタ、メモリ、定数の間でデータを移動します。
自分の入力との比較を行うcmpを見つけ、その後に成功メッセージへ分岐していれば、チェックを発見したことになります。次は、期待されている値を復元するか、チェックを回避します。
デコンパイラで作業を高速化
最新のデコンパイラはアセンブリを近似的なCコードに戻すため、生の命令列よりもはるかに速く読めます。デコンパイルされたパスワードチェックは、次のようになります。
// Decompiler output (approximate)
if (strcmp(user_input, "s3cr3t_p4ss") == 0) {
puts("Correct! Here is your flag:");
print_flag();
} else {
puts("Wrong.");
}メモリ破壊の始まり
Pwnの課題では、長さを確認せずに固定長バッファへ入力を読み込むプログラムを悪用します。スタックにはローカル変数と、関数の終了時にCPUが移動する場所を示す保存済みのリターンアドレスが格納されます。
入力がローカルバッファからあふれると、保存済みのリターンアドレスを上書きできます。リターンアドレスを制御できる者が、次に実行される場所を制御できます。
// Vulnerable: no bound on how much is read into buf
void vuln() {
char buf[64];
gets(buf); // reads until newline, ignores buf size
}古典的なスタックバッファオーバーフロー
最も単純なpwnは、リターンアドレスを上書きし、プログラムが本来呼び出すはずのない関数へジャンプさせることです。例えば、フラグを表示する隠れたwin()を呼び出します。
手順は次のとおりです。
- バッファの先頭からリターンアドレスまでの正確なオフセットを見つけます(サイクリックパターンのツールを使うとすぐに求められます)。
- ターゲット関数のアドレスを見つけます。
- オフセットまでパディングを送り、その後にリターンアドレスをターゲットで上書きします。
# Build the input with a Python exploit library
from pwn import *
p = process('./challenge')
offset = 72 # bytes to reach the return address
win_addr = 0x401176 # address of the win() function
p.sendline(b'A' * offset + p64(win_addr))
p.interactive()現代の緩和策
実際のバイナリでは、単純なオーバーフローを阻止する防御機構が有効になっています。checksecで次の機構を確認しなければなりません。
- スタックカナリア — リターンアドレスの前に配置される秘密の値です。値が変化するとプログラムは異常終了します。まずカナリアをリークする必要があります。
- NX(No-eXecute) — スタックが実行不可になるため、そこに配置したシェルコードを実行できません。
- ASLR / PIE — 実行のたびにアドレスがランダム化されるため、狙いを定める前にアドレスリークが必要です。
- RELRO — Global Offset Tableへの上書きから保護します。
それぞれの緩和策によって、より高度なテクニックが必要になります。
Return-Oriented Programming(ROP)
NXによって自分のコードを実行できない場合、Return-Oriented Programmingではバイナリ内にすでに存在するコードを再利用します。
ガジェットと呼ばれる短い命令列をつなぎ合わせます。各ガジェットはretで終わり、レジスタへの値のロードや、シェルを起動するライブラリ関数の呼び出しなどの処理を少しずつ実行します。スタック上にチェーンを構築し、各retが次のガジェットへジャンプするようにします。
ROPは、初心者向けのオーバーフローから、攻撃者のコードを直接実行することがほとんどできない実際のエクスプロイトへの橋渡しとなります。
フォーマット文字列のバグ
もう1つの古典的なpwnの基本テクニックがフォーマット文字列脆弱性です。これは、ユーザー入力がprint関数のフォーマット引数に直接渡される場合に発生します。
// Vulnerable: user controls the format string
printf(user_input); // dangerous
// Safe: user input is data, not format
printf("%s", user_input); // correct防御側がこれを学ぶ理由
メモリバグを正確に悪用する方法を学ぶのは、それらを防止できるようになるためです。防御の要点は明確です。
getsやstrcpyのような、入力長を制限しない関数は決して使わず、長さをチェックする同等の関数を使います。- カナリア、NX、完全なASLR/PIE、完全なRELROをデフォルトで有効にし、緩和策を維持します。
- 脅威モデル上可能であれば、メモリ安全な言語を優先します。
- ユーザーが制御できる値がフォーマット文字列やバッファコピーに到達する場合は、コードレビューで重大な問題として扱います。
クイックチェック
リバースとpwnの基礎をどの程度理解できているか確認します。
まとめ
これで、リバースとpwnの全体像を把握できました。
- 詳細な解析の前に、すべてのバイナリを
file、strings、checksecでトリアージします。 - 静的解析(逆アセンブラ/デコンパイラ)と動的解析(デバッガー)を組み合わせて、ロジックを理解します。
- Pwnは、リターンアドレスを上書きするスタックバッファオーバーフローから始まります。緩和策(カナリア、NX、ASLR/PIE、RELRO)が難易度を引き上げます。
- ROPは既存のガジェットを再利用してNXを回避します。フォーマット文字列のバグは、信頼できないフォーマット引数から生じます。
- すべてのテクニックは、より安全なコードの作成とレビューにつながる防御の教訓にもなります。
次は、ツールキットを構築し、解答をWriteupにまとめる方法を学びます。
AI チューターと学ぶ Cyber Security Academy — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 76
- レッスン
- 303
よくある質問
「リバースエンジニアリングとPwnの基礎」レッスンは無料ですか?
はい。「リバースエンジニアリングとPwnの基礎」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Cyber Security Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Cyber Security Academyコースには全4レッスンが含まれています。
「リバースエンジニアリングとPwnの基礎」で何を学びますか?
リバースエンジニアリングとバイナリ exploitの入門を学びます。 ブラウザで直接実行するハンズオンコードでCyber Security Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Cyber Security Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのCyber Security Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「リバースエンジニアリングとPwnの基礎」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このCyber Security Academyレッスンでコードを書いて実行できますか?
はい。すべてのCyber Security Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- CTFのカテゴリと考え方
- Webと暗号のチャレンジ
- リバースエンジニアリングとPwnの基礎
- ツールとWriteup