Ret2lib
基本情報
Ret2Libcの本質は、脆弱なプログラムの実行フローを、スタック上の攻撃者提供のシェルコードを実行する代わりに、共有ライブラリ(たとえばsystem、execve、strcpy)内の関数にリダイレクトすることです。攻撃者は、ペイロードを作成し、スタック上の戻りアドレスを望ましいライブラリ関数を指すように変更し、同時に呼び出し規約に従って必要な引数を適切に設定するように配置します。
手順の例(簡略化)
呼び出す関数(たとえばsystem)のアドレスと呼び出すコマンド(たとえば/bin/sh)を取得する
最初の引数をコマンド文字列を指すようにし、実行フローを関数に渡すためのROPチェーンを生成する
アドレスの検索
現在のマシンで使用されている
libc
がどこにメモリにロードされるかは、次のコマンドで確認できます:
ASLRがlibcのアドレスを変更しているかどうかを確認したい場合は、次のようにします:
使用されているlibcを知っていると、
system
関数へのオフセットを見つけることも可能です:
使用されているlibcを知っている場合、文字列
/bin/sh
関数へのオフセットを見つけることも可能です:
gdb-peda / GEFを使用する
使用しているlibcを知っている場合、PedaまたはGEFを使用して、system関数、exit関数、および文字列**/bin/sh
**のアドレスを取得することも可能です:
/proc/<PID>/mapsを使用する
プロセスが子プロセスを作成している場合(ネットワークサーバーの場合)、そのファイルを読み取ろうとしてみてください(おそらくroot権限が必要になるかもしれません)。
ここで、プロセス内でlibcがロードされている正確な場所と、プロセスの各子プロセスにロードされる場所がわかります。
この場合、0xb75dc000にロードされています(これがlibcのベースアドレスになります)
未知のlibc
バイナリがロードしているlibcがわからない可能性があります(アクセス権がないサーバーにあるかもしれません)。その場合、脆弱性を悪用していくつかのアドレスを漏洩させ、どのlibcライブラリが使用されているかを見つけることができます:
また、これに対するpwntoolsのテンプレートを以下で見つけることができます:
2つのオフセットでlibcを知る
ページhttps://libc.blukat.me/をチェックし、libc内の関数のいくつかのアドレスを使用して使用されているバージョンを特定します。
32ビットでASLRをバイパスする
これらのブルートフォース攻撃は32ビットシステムにのみ有用です。
攻撃がローカルの場合、libcのベースアドレスをブルートフォースすることができます(32ビットシステムに有用):
リモートサーバーを攻撃する場合、
libc
関数usleep
のアドレスを10(例)として試行することができます。サーバーが10秒追加で応答するようになったら、この関数のアドレスを見つけました。
ワンガジェット
libc
内の特定のアドレスにジャンプしてシェルを実行します:
x86 Ret2libコード例
この例では、ASLRブルートフォースがコードに統合されており、脆弱性のあるバイナリがリモートサーバーに配置されています:
x64 Ret2lib コード例
以下の例を確認してください:
ARM64 Ret2lib 例
ARM64の場合、ret 命令は x30 レジスタが指す場所にジャンプし、スタックレジスタが指す場所にはジャンプしません。そのため、少し複雑です。
また、ARM64では命令がそのままの動作をします(命令の途中でジャンプして新しい命令に変換することはできません)。
以下の例を確認してください:
Ret-into-printf (またはputs)
これにより、printf
/puts
を呼び出して特定のデータを引数として渡すことで、プロセスから情報を漏洩させることができます。たとえば、GOT 内の puts
のアドレスを puts
の実行に置くことで、メモリ内の puts
のアドレスを漏洩させることができます。
Ret2printf
これは、ret2lib
を使用して printf
フォーマット文字列の脆弱性に変換するRet2libの悪用を意味します。ret2lib
を使用して、それを悪用するための値を持って printf
を呼び出します(無駄に聞こえるかもしれませんが、可能です):
その他の例と参照
Ret2lib、libc 内の関数のアドレスを漏洩させることができる場合、one gadget を使用
64 ビット、ASLR 有効、PIE なし、最初のステップは、canary のバイト 0x00 までオーバーフローを埋め、その後 puts を呼び出して漏洩させる。canary を使用して、GOT 内の puts のアドレスを漏洩させ、
system('/bin/sh')
を呼び出すための ROP ガジェットを作成64 ビット、ASLR 有効、canary なし、メイン関数内のスタックオーバーフロー。puts を呼び出して、GOT 内の puts のアドレスを漏洩させ、その後 one gadget を呼び出す
64 ビット、PIE なし、canary なし、relro なし、nx。write 関数を使用して、write(libc)のアドレスを漏洩させ、one gadget を呼び出す
スタックから canary を漏洩させるためにフォーマット文字列を使用し、システムにアドレス
/bin/sh
を持つ GOT に呼び出すためのバッファオーバーフローを使用32 ビット、relro なし、canary なし、nx、pie。スタックから libc とヒープのアドレスを漏洩させるために悪いインデックスを悪用。バッファオーバーフローを悪用して、
system('/bin/sh')
を呼び出す ret2lib を行う(ヒープアドレスはチェックをバイパスするために必要)。
Last updated