BROP - Blind Return Oriented Programming

Reading time: 11 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

この攻撃の目的は、脆弱なバイナリに関する情報がなくてもバッファオーバーフローを介してROPを悪用できるようにすることです。
この攻撃は以下のシナリオに基づいています:

  • スタックの脆弱性とそれをトリガーする方法の知識。
  • クラッシュ後に再起動するサーバーアプリケーション。

攻撃

1. 脆弱なオフセットを見つける サーバーの異常が検出されるまで1文字追加で送信する

2. カナリアをブルートフォース して漏洩させる

3. スタック内の保存されたRBPとRIP アドレスをブルートフォースして漏洩させる

これらのプロセスに関する詳細情報は、こちら (BF Forked & Threaded Stack Canaries)こちら (BF Addresses in the Stack)で見つけることができます。

4. 停止ガジェットを見つける

このガジェットは基本的に、ROPガジェットによって何か興味深いことが実行されたことを確認するためのもので、実行がクラッシュしなかったことを示します。通常、このガジェットは実行を停止するもので、特定のROPガジェットが実行されたことを確認するためにROPチェーンの最後に配置されます。

5. BROPガジェットを見つける

この技術はret2csuガジェットを使用します。これは、いくつかの命令の途中でこのガジェットにアクセスすると、**rsirdi**を制御するガジェットが得られるためです:

https://www.scs.stanford.edu/brop/bittau-brop.pdf

これらがガジェットです:

  • pop rsi; pop r15; ret
  • pop rdi; ret

これらのガジェットを使用すると、関数を呼び出すための2つの引数を制御することが可能であることに注意してください。

また、ret2csuガジェットは非常にユニークなシグネチャを持っているため、スタックから6つのレジスタをポップすることになります。したがって、次のようなチェーンを送信します:

'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP

STOPが実行される場合、これは基本的にスタックから6つのレジスタをポップするアドレスが使用されたことを意味します。または、使用されたアドレスもSTOPアドレスであったことを意味します。

この最後のオプションを排除するために、次のような新しいチェーンが実行され、前のものが6つのレジスタをポップしたことを確認するためにSTOPガジェットを実行してはなりません:

'A' * offset + canary + rbp + ADDR

ret2csuガジェットのアドレスを知っていると、rsirdiを制御するガジェットのアドレスを推測することが可能です。

6. PLTを見つける

PLTテーブルは0x400000から、またはスタックからの漏洩したRIPアドレスから検索できます(PIEが使用されている場合)。テーブルのエントリ16B(0x10B)で区切られており、1つの関数が呼び出されると、引数が正しくなくてもサーバーはクラッシュしません。また、PLTのエントリのアドレス + 6Bもクラッシュしません。これは最初に実行されるコードです。

したがって、次の動作を確認することでPLTテーブルを見つけることができます:

  • 'A' * offset + canary + rbp + ADDR + STOP -> クラッシュしない
  • 'A' * offset + canary + rbp + (ADDR + 0x6) + STOP -> クラッシュしない
  • 'A' * offset + canary + rbp + (ADDR + 0x10) + STOP -> クラッシュしない

7. strcmpを見つける

strcmp関数は、比較される文字列の長さをレジスタrdxに設定します。rdx3番目の引数であり、後でプログラムを漏洩させるために0より大きくする必要があります

次のように、関数の最初の2つの引数を制御できる事実を利用して、PLT内の**strcmp**の位置を見つけることができます:

  • strcmp(<非読み取りアドレス>, <非読み取りアドレス>) -> クラッシュ
  • strcmp(<非読み取りアドレス>, <読み取りアドレス>) -> クラッシュ
  • strcmp(<読み取りアドレス>, <非読み取りアドレス>) -> クラッシュ
  • strcmp(<読み取りアドレス>, <読み取りアドレス>) -> クラッシュしない

これは、PLTテーブルの各エントリを呼び出すか、PLTスローパスを使用して確認できます。これは基本的にPLTテーブルのエントリを呼び出し + 0xbdlresolveを呼び出す)し、スタックに調査したいエントリ番号(ゼロから始まる)を続けて、最初のエントリからすべてのPLTエントリをスキャンします:

  • strcmp(<非読み取りアドレス>, <読み取りアドレス>) -> クラッシュ
  • b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP -> クラッシュする
  • strcmp(<読み取りアドレス>, <非読み取りアドレス>) -> クラッシュ
  • b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
  • strcmp(<読み取りアドレス>, <読み取りアドレス>) -> クラッシュしない
  • b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP

覚えておいてください:

  • BROP + 0x7は**pop RSI; pop R15; ret;**を指します
  • BROP + 0x9は**pop RDI; ret;**を指します
  • PLT + 0xbはdl_resolveへの呼び出しを指します。

strcmpを見つけることで、**rdx**を0より大きい値に設定することが可能です。

tip

通常、rdxにはすでに0より大きい値が格納されているため、このステップは必要ないかもしれません。

8. Writeまたは同等のものを見つける

最後に、バイナリを漏洩させるためにデータを外部に送信するガジェットが必要です。そして、この時点で2つの引数を制御し、rdxを0より大きく設定することが可能です。

これに悪用できる一般的な関数は3つあります:

  • puts(data)
  • dprintf(fd, data)
  • write(fd, data, len(data))

ただし、元の論文では**write**のみが言及されているため、これについて話しましょう:

現在の問題は、PLT内のwrite関数がどこにあるかがわからず、データをソケットに送信するためのfd番号がわからないことです。

しかし、PLTテーブルの位置はわかっており、その動作に基づいてwriteを見つけることが可能です。また、サーバーとの複数の接続を作成し、高いFDを使用して、いくつかの接続と一致することを期待できます。

これらの関数を見つけるための動作シグネチャ:

  • 'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP -> データが印刷される場合、putsが見つかりました
  • 'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP -> データが印刷される場合、dprintfが見つかりました
  • 'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP -> データが印刷される場合、writeが見つかりました

自動エクスプロイト

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする