Stack Pivoting - EBP2Ret - EBP chaining
Last updated
Last updated
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
この技術は、**ベースポインタ(EBP)を操作する能力を利用して、EBPレジスタとleave; ret
**命令シーケンスを慎重に使用することで、複数の関数の実行をチェーンするものです。
念のため、**leave
**は基本的に次のことを意味します:
And as the EBP is in the stack before the EIP it's possible to control it controlling the stack.
この技術は、EBPレジスタを変更できるが、EIPレジスタを直接変更する方法がない場合に特に有用です。これは、関数が実行を終了する際の動作を利用します。
もし、fvuln
の実行中に、シェルコードのアドレスがあるメモリの領域を指す偽のEBPをスタックに注入することができれば(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チェーン。
制御されたメモリの部分の前には、4
バイトが必要です。これは**pop
部分のleave
命令のためです。これらの4バイトを悪用して2つ目の偽EBP**を設定し、実行を制御し続けることが可能です。
この技術には「Off-By-One Exploit」として知られる特定のバリアントがあります。これは、EBPの最下位バイトのみを変更できる場合に使用されます。この場合、**ret
**でジャンプするアドレスを格納するメモリ位置はEBPの最初の3バイトを共有する必要があり、より制約のある条件で類似の操作が可能になります。
通常、0x00のバイトを変更してできるだけ遠くにジャンプします。
また、スタックにRETスレッドを使用し、実際のROPチェーンを最後に配置して、新しいESPがRETスレッド内を指し、最終的なROPチェーンが実行される可能性を高めることが一般的です。
したがって、スタックのEBP
エントリに制御されたアドレスを配置し、EIP
にleave; ret
のアドレスを配置することで、スタックから制御されたEBP
アドレスにESP
を移動させることが可能です。
今、**ESP
**は制御され、望ましいアドレスを指しており、次に実行される命令はRET
です。これを悪用するために、制御されたESPの場所に次のものを配置することができます:
&(次の偽EBP)
-> leave
命令からのpop ebp
により新しいEBPをロード
system()
-> ret
によって呼び出される
&(leave;ret)
-> systemが終了した後に呼び出され、ESPを偽EBPに移動させ、再び開始
&("/bin/sh")
-> system
のパラメータ
基本的に、この方法で複数の偽EBPを連鎖させてプログラムのフローを制御することが可能です。
これはret2libのようなものですが、明らかな利点はなく、特定のエッジケースで興味深いかもしれません。
さらに、ここにチャレンジの例があり、この技術を使用してスタックリークを利用して勝利関数を呼び出します。これはページからの最終的なペイロードです:
この投稿で説明されているように、バイナリがいくつかの最適化でコンパイルされている場合、EBPはESPを制御することができません。したがって、EBPを制御することによって機能するエクスプロイトは基本的に失敗します。なぜなら、それには実際の効果がないからです。 これは、プロローグとエピローグがバイナリが最適化されると変更されるためです。
最適化されていない:
最適化された:
pop rsp
ガジェットこのページでは、この技術を使用した例を見つけることができます。このチャレンジでは、2つの特定の引数を持つ関数を呼び出す必要があり、pop rsp
ガジェットがあり、スタックからのリークがあります:
ret2espテクニックについては、こちらを確認してください:
64ビット、retスレッドで始まるropチェーンを使用したオフバイワンのエクスプロイト
64ビット、relro、canary、nx、pieなし。プログラムはスタックまたはpieのリークとqwordのWWWを提供します。最初にスタックリークを取得し、WWWを使用して戻り、pieリークを取得します。その後、WWWを使用して.fini_array
エントリを悪用して永続ループを作成し、__libc_csu_fini
を呼び出します(詳細はこちら)。この「永続的」な書き込みを悪用して、.bssにROPチェーンを書き込み、RBPでピボットを呼び出します。
ARM64では、関数のプロローグとエピローグはスタック内のSPレジスタを保存および取得しません。さらに、**RET
命令はSPが指すアドレスに戻るのではなく、x30
**内のアドレスに戻ります。
したがって、デフォルトでは、エピローグを悪用するだけではSPレジスタを制御することはできません。データをスタック内で上書きしても、SPを制御できたとしても、x30
レジスタを制御する方法が必要です。
プロローグ
エピローグ
ARM64でスタックピボティングに似たことを行う方法は、**SP
を制御できること(SP
に渡される値を持つレジスタを制御するか、何らかの理由でSP
がスタックからアドレスを取得しており、オーバーフローがある場合)であり、その後、エピローグを悪用して制御されたSP
からx30
**レジスタをロードし、**それにRET
**することです。
次のページでは、ARM64におけるRet2espの同等物を見ることができます:
AWSハッキングを学び、練習する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、練習する:HackTricks Training GCP Red Team Expert (GRTE)