SROP - Sigreturn-Oriented Programming
基本情報
Sigreturn
は、主にシグナルハンドラの実行が完了した後のクリーンアップに使用される特別な syscall です。シグナルは、オペレーティングシステムによってプログラムに送信される中断で、通常は何らかの例外的な状況が発生したことを示します。プログラムがシグナルを受け取ると、シグナルを処理するために シグナルハンドラ という特別な関数を使用して、現在の作業を一時的に中断します。
シグナルハンドラが終了した後、プログラムは何も起こらなかったかのように 以前の状態に戻る 必要があります。ここで sigreturn
が登場します。これは、プログラムが シグナルハンドラから戻る のを助け、シグナルハンドラによって使用されたスタックフレーム(関数呼び出しやローカル変数を格納するメモリのセクション)をクリーンアップすることでプログラムの状態を復元します。
興味深いのは、sigreturn
がプログラムの状態をどのように復元するかです:それは すべてのCPUのレジスタ値をスタックに保存することによって 行います。シグナルがもはやブロックされていないとき、sigreturn
はこれらの値をスタックからポップし、実質的にCPUのレジスタをシグナルが処理される前の状態にリセットします。これには、スタックの現在のトップを指すスタックポインタレジスタ(RSP)が含まれます。
ROPチェーンから sigreturn
システムコールを呼び出し、スタックに読み込むレジスタ値を追加する ことで、すべてのレジスタ値を 制御 できるため、例えば /bin/sh
で execve
システムコールを 呼び出す ことが可能です。
これは、他のRet2syscallを呼び出すためのパラメータを制御するのがはるかに簡単になる Ret2syscallの一種 であることに注意してください:
Ret2syscall興味がある方のために、これは後で値を回復するためにスタックに保存される sigcontext構造体 です(図は こちら から):
より良い説明のために、こちらも確認してください:
例
ここに例があります では、ROPを介してsigneturnへの呼び出しが構築されています(rxaに値0xf
を入れる)、ただし、これはそこからの最終的なエクスプロイトです:
Check also the exploit from here where the binary was already calling sigreturn
and therefore it's not needed to build that with a ROP:
その他の例と参考文献
スタックに書き込みを行い、その後**
sigreturn
システムコールを呼び出すアセンブリバイナリ。スタックにret2syscallをsigreturn**構造体を介して書き込み、バイナリのメモリ内にあるフラグを読み取ることが可能です。スタックに書き込みを行い、その後**
sigreturn
システムコールを呼び出すアセンブリバイナリ。スタックにret2syscallをsigreturn**構造体を介して書き込むことが可能です(バイナリには/bin/sh
という文字列があります)。64ビット、relroなし、canaryなし、nx、pieなし。
gets
関数のバッファオーバーフローを利用し、ret2syscallを実行するためのガジェットが不足しています。ROPチェーンはgets
を再度呼び出すことで/bin/sh
を.bss
に書き込み、**alarm
**関数を利用してeaxを0xf
に設定し、SROPを呼び出してシェルを実行します。64ビットアセンブリプログラム、relroなし、canaryなし、nx、pieなし。フローはスタックに書き込み、複数のレジスタを制御し、システムコールを呼び出し、その後
exit
を呼び出します。選択されたシステムコールはsigreturn
で、レジスタを設定し、eip
を以前のシステムコール命令を呼び出すように移動させ、memprotect
を実行してバイナリ空間をrwx
に設定し、バイナリ空間内のESPを設定します。フローに従って、プログラムは再度ESPに読み込みを呼び出しますが、この場合ESPは次の命令を指しているため、シェルコードを渡すことで次の命令として書き込み、実行します。SROPは、シェルコードが配置された場所に実行権限(memprotect)を与えるために使用されます。
Last updated