Ret2win
基本情報
Ret2win チャレンジは、特にバイナリエクスプロイテーションを含むCapture The Flag (CTF) コンペティションで人気のあるカテゴリです。目標は、与えられたバイナリ内の脆弱性を悪用して、通常win
、flag
などと名付けられた特定の未呼び出し関数を実行することです。通常、この関数を実行すると、フラグや成功メッセージが表示されます。チャレンジは、通常、スタック上の戻りアドレスを上書きして、実行フローを目的の関数に誘導することを含みます。以下は、例を交えた詳細な説明です:
Cの例
脆弱性を持つ単純なCプログラムと、呼び出したいwin
関数があるとします:
このプログラムをスタック保護を無効にして、ASLRを無効にしてコンパイルするには、次のコマンドを使用できます:
-m32
: プログラムを32ビットバイナリとしてコンパイルする(これはオプションですが、CTFチャレンジで一般的です)。-fno-stack-protector
: スタックオーバーフローに対する保護を無効にする。-z execstack
: スタック上でのコードの実行を許可する。-no-pie
: 位置独立実行可能ファイルを無効にして、win
関数のアドレスが変わらないようにする。-o vulnerable
: 出力ファイルの名前をvulnerable
にする。
Pwntoolsを使用したPythonエクスプロイト
エクスプロイトでは、エクスプロイトスクリプトがバッファをオーバーフローさせ、リターンアドレスを win
関数のアドレスで上書きするペイロードを作成します。
win
関数のアドレスを見つけるためには、gdb、objdump、またはバイナリファイルを調査することができる他のツールを使用できます。たとえば、objdump
を使用して次のようにします:
このコマンドは、win
関数のアセンブリを表示し、その開始アドレスを含めます。
Pythonスクリプトは、vulnerable_function
によって処理されるときに、注意深く作成されたメッセージを送信し、バッファをオーバーフローさせ、スタック上の戻りアドレスを win
のアドレスで上書きします。vulnerable_function
が返るとき、main
に戻るか終了する代わりに、win
にジャンプし、メッセージが表示されます。
保護
PIE は無効にする必要があります。そうしないと、アドレスが実行ごとに信頼性のあるものにならず、関数が格納されるアドレスが常に同じでないため、win 関数がどこにロードされるかを特定するためには何らかのリークが必要になります。オーバーフローを引き起こす関数が
read
などの場合、1または2バイトの部分的な上書きを行うことで、戻りアドレスを win 関数に変更することができます。ASLRの動作により、最後の3つの16進数のニブルはランダム化されないため、正しい戻りアドレスを取得する確率は1/16(1ニブル)です。Stack Canaries も無効にするか、侵害された EIP 戻りアドレスは決して追跡されません。
他の例と参考文献
32ビット、ASLRなし
ASLR付きの64ビット、バイナリアドレスのリークあり
64ビット、ASLRなし
32ビット、ASLRなし、ダブルスモールオーバーフロー、最初はスタックをオーバーフローさせ、次のオーバーフローのサイズを拡大する
32ビット、relro、canaryなし、nx、pieなし、アドレス
fflush
を win 関数(ret2win)で上書きするためのフォーマット文字列32ビット、nx、その他何もなし、EIP(1バイト)の部分的な上書きで win 関数を呼び出す
32ビット、nx、その他何もなし、EIP(1バイト)の部分的な上書きで win 関数を呼び出す
プログラムは数値の最後のバイトのみを検証して入力サイズを確認しており、したがって、最後のバイトが許可される範囲内であれば任意のサイズを追加することが可能です。その後、入力は ret2win で悪用されるバッファオーバーフローを作成します。
64ビット、relro、canaryなし、nx、pie。 win 関数(ret2win)を呼び出すための部分的な上書き
arm64、PIE、win 関数のPIEリーク、実際には2つの関数を呼び出すROPガジェット
ARM64、オフバイワンで win 関数を呼び出す例
ARM64の例
pageRet2win - arm64Last updated