Stack Pivoting - EBP2Ret - EBP chaining
基本情報
このテクニックは、**ベースポインタ(EBP)**を操作して、EBPレジスタと leave; ret
命令シーケンスを注意深く使用して複数の関数の実行をチェーンする能力を悪用します。
再確認ですが、leave
は基本的に次の意味です:
EBP2Ret
このテクニックは、EBPレジスタを変更できますが、EIPレジスタを直接変更する方法がない場合に特に有用です。関数が実行を終了する際の挙動を活用します。
fvuln
の実行中に、スタックに偽のEBPを挿入し、そのEBPがESPが指すメモリ領域を指すようにすることに成功すれば(pop
操作を考慮してシェルコードのアドレスが格納されているメモリ領域のアドレスに4バイトを加算)、間接的にEIPを制御できます。fvuln
がリターンすると、ESPはこの作成された位置に設定され、その後のpop
操作によりESPが4減少し、実質的に攻撃者によってそこに格納されたアドレスを指すようになります。
ここで注意すべきは、2つのアドレスを知る必要があることです:ESPが移動する場所と、ESPが指すアドレスを書き込む必要がある場所です。
攻撃構築
まず、任意のデータ/アドレスを書き込むことができるアドレスを知る必要があります。ESPはここを指し、最初のret
を実行します。
次に、任意のコードを実行するret
によって使用されるアドレスを知る必要があります。次のものを使用できます:
有効なONE_GADGETアドレス。
system()
のアドレスに続く4つのジャンクバイトと"/bin/sh"
のアドレス(x86ビット)。jump esp;
ガジェットのアドレス(ret2esp)と実行するシェルコード。いくつかのROPチェーン
制御されたメモリのこのアドレスの前には、leave
命令の**pop
部分のために4
バイトが必要です。これらの4バイトを悪用して2番目の偽のEBP**を設定し、実行を継続することが可能です。
Off-By-One Exploit
このテクニックの特定のバリアントを「Off-By-One Exploit」として知られています。これは、EBPの最も重要なバイトのみを変更できる場合に使用されます。その場合、**ret
**でジャンプするアドレスを格納するメモリ位置は、最初の3バイトをEBPと共有する必要があり、より制約のある条件で同様の操作が可能になります。
通常、できるだけ遠くにジャンプするためにバイト0x00を変更します。
また、スタックにRETスレッドを使用し、実際のROPチェーンを最後に配置して、新しいESPがRET SLED内部を指し、最終的なROPチェーンが実行される可能性を高めることが一般的です。
EBP Chaining
したがって、スタックのEBP
エントリに制御されたアドレスを配置し、EIP
にleave; ret
のアドレスを配置すると、ESP
をスタックから制御されたEBP
アドレスに移動することができます。
今、**ESP
**は望ましいアドレスを指し、次に実行される命令はRET
です。これを悪用するために、制御されたESPの場所に次のものを配置できます:
&(次の偽のEBP)
->leave
命令のpop ebp
によって新しいEBPをロードしますsystem()
->ret
によって呼び出されます&(leave;ret)
-> systemが終了した後に呼び出され、ESPを偽のEBPに移動させて再開します&("/bin/sh")
->system
のパラメータ
基本的に、プログラムのフローを制御するために複数の偽のEBPをチェーンすることが可能です。
これはret2libのようなものですが、明らかな利点はなく、いくつかのエッジケースで興味深いかもしれません。
さらに、ここにはこのテクニックを使用したスタックリークを行い、勝利関数を呼び出すチャレンジの例があります。これはページからの最終ペイロードです:
EBP might not be used
この投稿で説明されているように, バイナリがいくつかの最適化でコンパイルされている場合、EBPはESPを制御することができないため、EBPを制御することによって機能するエクスプロイトは基本的に失敗します。 これは、バイナリが最適化されている場合、プロローグとエピローグが変更されるためです。
最適化されていない場合:
最適化された:
RSPを制御する他の方法
pop rsp
ガジェット
pop rsp
ガジェットこのページ には、このテクニックを使用した例があります。このチャレンジでは、2つの特定の引数を持つ関数を呼び出す必要があり、pop rsp
ガジェットが存在し、スタックからのリークがありました。
xchg <reg>, rsp ガジェット
jmp esp
ここでret2espテクニックを確認してください:
pageRet2esp / Ret2reg参考文献と他の例
64ビット、ret sledで始まるropチェーンを使用したオフバイワン攻撃
64ビット、relro、canary、nx、およびpieなし。プログラムはスタックまたはpieのリークとqwordのWWWを提供します。まずスタックのリークを取得し、WWWを使用してpieのリークを取得します。その後、WWWを使用して
.fini_array
エントリを乱用し、__libc_csu_fini
を呼び出すことで永続ループを作成します(詳細はこちら)。この「永遠の」書き込みを乱用して、.bssにROPチェーンを書き込み、それを呼び出してRBPでピボットします。
ARM64
ARM64では、関数のプロローグとエピローグはSPレジスタを保存および復元しません。さらに、**RET
命令はSPが指すアドレスに戻るのではなく、x30
**内のアドレスに戻ります。
したがって、デフォルトでは、エピローグを乱用しても、スタック内のデータを上書きしてSPレジスタを制御することはできません。そして、SPを制御できたとしても、**x30
**レジスタを制御する方法が必要です。
プロローグ
エピローグ
ARM64でスタックピボットに類似した操作を行う方法は、SP
を制御できるようになること(SP
に渡されるレジスタの値を制御するか、何らかの理由でSP
がスタックからアドレスを取得し、オーバーフローがある場合)であり、その後、エピローグを乱用して**制御されたSP
からx30
レジスタをロードし、RET
**します。
また、次のページでARM64でのRet2espの相当物を見ることができます:
pageRet2esp / Ret2regLast updated