BF Addresses in the Stack
キャナリとPIE(Position Independent Executable)で保護されたバイナリに直面している場合、それらをバイパスする方法を見つける必要があるかもしれません。
checksec
は、バイナリが静的にコンパイルされており、関数を識別することができない場合、バイナリがキャナリで保護されていることを見つけることができないかもしれません。
ただし、関数呼び出しの開始時にスタックに値が保存され、この値が終了前にチェックされる場合、これを手動で気付くことができます。
アドレスのブルートフォース
PIEをバイパスするためには、いくつかのアドレスをリークする必要があります。バイナリがアドレスをリークしていない場合、脆弱な関数内のスタックに保存されたRBPとRIPをブルートフォースするのが最善です。 たとえば、バイナリがキャナリとPIEの両方を使用して保護されている場合、まずキャナリをブルートフォースし、次の8バイト(x64)が保存されたRBPであり、次の8バイトが保存されたRIPになります。
スタック内のリターンアドレスがメインバイナリコードに属していると仮定されており、脆弱性がバイナリコードにある場合は通常そのようなケースになります。
バイナリからRBPとRIPをブルートフォースするには、プログラムが何かを出力するかクラッシュしない場合、有効な推測されたバイトが正しいことがわかります。キャナリをブルートフォースするために提供された関数と同じ関数を使用して、RBPとRIPをブルートフォースすることができます。
最後に、PIEを打破するために必要なのは、漏洩したアドレスから有用なアドレスを計算することです:RBPとRIP。
RBPからは、スタック内にシェルを書き込んでいる場所を計算することができます。これは、スタック内に文字列_"/bin/sh\x00"_を書き込む場所を知るのに非常に役立ちます。漏洩したRBPとあなたのシェルコードの間の距離を計算するには、漏洩したRBPの後にブレークポイントを設定して、シェルコードがどこにあるかを確認し、その後、シェルコードとRBPの間の距離を計算できます:
RIPからは、PIEバイナリのベースアドレスを計算できます。これは、有効なROPチェーンを作成するために必要になります。
ベースアドレスを計算するには、単にobjdump -d vunbinary
を実行し、最新のアドレスを逐次進行してください:
この例では、すべてのコードを特定するのに1バイトと半分だけが必要であることがわかります。したがって、この状況では、ベースアドレスは**"000"で終わるリークしたRIP**になります。たとえば、0x562002970ecf
がリークした場合、ベースアドレスは0x562002970000
になります。
改善
この投稿からのいくつかの観察 によると、RBP と RIP の値を漏洩させる際、サーバーは正しい値でないいくつかの値でクラッシュせず、BF スクリプトは正しい値を取得したと思うかもしれません。これは、正確な値でなくても、いくつかのアドレスがそれを壊すことが可能だからです。
そのブログ投稿によると、サーバーへのリクエスト間に短い遅延を導入することが推奨されています。
Last updated