Leaking libc address with ROP
簡単な要約
オーバーフローのオフセットを見つける
POP_RDI
ガジェット、PUTS_PLT
およびMAIN
ガジェットを見つける前のガジェットを使用して、putsまたは他のlibc関数のメモリアドレスを漏洩させ、libcのバージョンを見つける(ダウンロードする)
ライブラリを使用して、ROPを計算し、エクスプロイトする
実践するための他のチュートリアルとバイナリ
このチュートリアルは、次のチュートリアルで提案されたコード/バイナリをエクスプロイトします:https://tasteofsecurity.com/security/ret2libc-unknown-libc/ 他の有用なチュートリアル:https://made0x78.com/bseries-ret2libc/、https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
コード
ファイル名:vuln.c
ROP - LIBCを漏洩させるテンプレート
エクスプロイトをダウンロードし、脆弱なバイナリと同じディレクトリに配置し、スクリプトに必要なデータを提供します:
Leaking libc - template1- オフセットの特定
テンプレートは、エクスプロイトを続行する前にオフセットが必要です。提供された場合は、必要なコードを実行してそれを見つけます(デフォルトでは OFFSET = ""
):
実行 python template.py
すると、クラッシュしたプログラムとともに GDB コンソールが開きます。その GDB コンソール 内で x/wx $rsp
を実行して、RIP を上書きしようとしていた バイト を取得します。最後に、python コンソールを使用して オフセット を取得します:
オフセット(この場合は40)を見つけたら、その値を使ってテンプレート内のOFFSET変数を変更します。
OFFSET = "A" * 40
別の方法としては、pattern create 1000
-- retまで実行 -- pattern seach $rsp
をGEFから使用することです。
2- ガジェットの発見
次に、バイナリ内のROPガジェットを見つける必要があります。このROPガジェットは、libcを見つけるためにputs
を呼び出すのに役立ち、後で最終的なエクスプロイトを実行するために使用されます。
PUTS_PLT
は関数putsを呼び出すために必要です。
MAIN_PLT
はオーバーフローを再度****悪用するために、1回のインタラクションの後にメイン関数を再度呼び出すために必要です(無限の悪用のラウンド)。各ROPの最後でプログラムを再度呼び出すために使用されます。
POP_RDIは呼び出された関数にパラメータを渡すために必要です。
このステップでは、実行中にpwntoolsによってすべてが見つかるため、何も実行する必要はありません。
3- libcライブラリの特定
今はどのバージョンのlibcライブラリが使用されているかを見つける時です。そうするために、関数puts
のメモリ内のアドレスを漏洩し、そのアドレスにあるputsのバージョンがどのライブラリバージョンにあるかを検索します。
これを行うために、実行されたコードの最も重要な行は次のとおりです:
これは、RIPを上書きすることが可能になるまでいくつかのバイトを送信します: OFFSET
。
次に、ガジェットPOP_RDI
のアドレスを設定し、次のアドレス(FUNC_GOT
)がRDIレジスタに保存されるようにします。これは、PUTS_GOT
のアドレスを渡してputsを呼び出すためです。puts関数のメモリ内のアドレスはPUTS_GOT
が指すアドレスに保存されています。
その後、PUTS_PLT
が呼び出され(RDI内にPUTS_GOT
がある状態で)、putsはPUTS_GOT
内の内容を読み取ります(メモリ内のputs関数のアドレス)そしてそれを出力します。
最後に、main関数が再び呼び出され、再度オーバーフローを利用できるようになります。
この方法で、puts関数を騙して、メモリ内のputs関数のアドレス(libcライブラリ内)を出力させました。そのアドレスがわかったので、どのlibcバージョンが使用されているかを検索できます。
ローカルバイナリを利用しているため、どのバージョンのlibcが使用されているかを特定する必要はありません(ただ/lib/x86_64-linux-gnu/libc.so.6
でライブラリを見つければよいです)。
しかし、リモートエクスプロイトの場合、ここでどのように見つけるかを説明します:
3.1- libcバージョンの検索 (1)
ウェブページでどのライブラリが使用されているかを検索できます: https://libc.blukat.me/ 発見されたlibcのバージョンをダウンロードすることもできます。
3.2- libcバージョンの検索 (2)
次のようにすることもできます:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
これには少し時間がかかりますので、辛抱してください。 これが機能するためには、次が必要です:
Libcシンボル名:
puts
漏洩したlibcアドレス:
0x7ff629878690
これにより、最も可能性の高いlibcを特定できます。
私たちは2つのマッチを得ます(最初のものが機能しない場合は2番目のものを試してください)。最初のものをダウンロードしてください:
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
から libc を作業ディレクトリにコピーします。
3.3- リークする他の関数
4- libcアドレスの発見と悪用
この時点で使用されているlibcライブラリを知っている必要があります。ローカルバイナリを悪用しているので、私は次のようにします:/lib/x86_64-linux-gnu/libc.so.6
したがって、template.py
の最初でlibc変数を次のように変更します: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #ライブラリパスを知っているときに設定
libcライブラリへのパスを指定することで、残りのエクスプロイトは自動的に計算されます。
get_addr
関数内でlibcのベースアドレスが計算されます:
注意してください 最終的なlibcベースアドレスは00で終わる必要があります。そうでない場合は、間違ったライブラリを漏洩した可能性があります。
次に、関数 system
へのアドレスと文字列 "/bin/sh" への アドレス は libcのベースアドレス から 計算 され、libcライブラリ が与えられます。
最終的に、/bin/sh 実行エクスプロイトが準備されます。
最後のROPについて説明しましょう。
最後のROP(rop1
)は再びmain関数を呼び出し、次にoverflowを再利用することができます(だからOFFSET
がここに再びあります)。次に、POP_RDI
を呼び出し、"/bin/sh"のアドレス(BINSH
)を指し示し、system関数(SYSTEM
)を呼び出したいです。なぜなら、"/bin/sh"のアドレスがパラメータとして渡されるからです。
最後に、exit関数のアドレスが呼び出され、プロセスが正常に終了し、アラートが生成されません。
この方法で、エクスプロイトは_/bin/sh_**シェルを実行します。**
4(2)- ONE_GADGETの使用
systemと**"/bin/sh"を使用する代わりに、ONE_GADGETを使用してシェルを取得することもできます。ONE_GADGETはlibcライブラリ内で、1つのROPアドレス**を使用してシェルを取得する方法を見つけます。
ただし、通常はいくつかの制約があり、最も一般的で回避しやすいものは[rsp+0x30] == NULL
のようなものです。RSP内の値を制御しているので、制約を回避するためにもう少しNULL値を送信するだけです。
EXPLOIT FILE
この脆弱性を利用するためのテンプレートはここにあります:
Leaking libc - templateCommon problems
MAIN_PLT = elf.symbols['main'] が見つかりません
"main" シンボルが存在しない場合、メインコードの場所を見つけることができます:
アドレスを手動で設定します:
Putsが見つかりません
バイナリがPutsを使用していない場合は、次のことを確認してください。
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found
すべてのエクスプロイトを作成した後にこのエラーが見つかった場合: sh: 1: %s%s%s%s%s%s%s%s: not found
"/bin/sh"のアドレスから64バイトを引いてみてください:
Last updated