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アドレス漏洩テンプレート
エクスプロイトをダウンロードし、脆弱性のあるバイナリと同じディレクトリに配置し、スクリプトに必要なデータを提供します:
pageLeaking libc - template1- オフセットの検索
テンプレートは、エクスプロイトを続行する前にオフセットが必要です。提供されている場合、必要なコードを実行してそれを見つけます(デフォルトでは OFFSET = ""
)。
実行 python template.py
とすると、プログラムがクラッシュした状態で GDBコンソール が開かれます。その GDBコンソール 内で x/wx $rsp
を実行して、RIP を上書きするバイト列を取得します。最後に、pythonコンソールを使用して オフセット を取得します:
オフセット(この場合は40)を見つけた後は、その値を使ってテンプレート内のOFFSET変数を変更します。
OFFSET = "A" * 40
別の方法は、GEFから pattern create 1000
-- execute until ret -- pattern seach $rsp
を使用することです。
2- ガジェットの検索
次に、バイナリ内のROPガジェットを見つける必要があります。これらのROPガジェットは、使用されているlibcを見つけるためにputsを呼び出し、後で 最終的なエクスプロイトを起動するのに役立ちます。
PUTS_PLT
を呼び出すためには、puts関数を呼び出す必要があります。
MAIN_PLT
は、オーバーフローを再度利用するために、1回のインタラクション後にmain関数を再度呼び出すために必要です(無限の利用ラウンド)。 各ROPの最後にプログラムを再度呼び出すために使用されます。
POP_RDIは、呼び出される関数にパラメータを渡すために必要です。
このステップでは、実行する必要はありません。すべては実行中にpwntoolsによって見つけられます。
3- libcライブラリの検索
今は、使用されているlibcライブラリのバージョンを見つける時です。そのために、puts関数のメモリ内のアドレスをリークし、その後そのアドレスにあるputsバージョンがどのライブラリバージョンにあるかを検索します。
それを行うために、実行されるコードの中で最も重要な行は次のとおりです:
これにより、RIP を上書きするまでのいくつかのバイトが送信されます: OFFSET
。
次に、ガジェット POP_RDI
のアドレスが設定され、次のアドレス (FUNC_GOT
) がRDI レジスタに保存されます。これは、PUTS_GOT
のアドレスをメモリ内の puts 関数のアドレスが PUTS_GOT
によって指し示されるアドレスとして渡して puts を呼び出したいためです。
その後、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)
Web ページ 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番目のものを試してください)。最初のものをダウンロードしてください:
3.3- リークするための他の関数
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
から libc を作業ディレクトリにコピーします。
4- libcアドレスの特定と悪用
この時点で、使用されているlibcライブラリを知っている必要があります。ローカルバイナリを悪用しているので、単に次のようにします:/lib/x86_64-linux-gnu/libc.so.6
したがって、template.py
の冒頭で、libc変数を次のように変更します:libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
libcライブラリへのパスを指定すると、残りの悪用が自動的に計算されます。
get_addr
関数の中で、libcのベースアドレスが計算されます:
最終的なlibcベースアドレスは00で終わる必要があることに注意してください。そうでない場合、間違ったライブラリが漏洩している可能性があります。
次に、system
関数へのアドレスと文字列_"/bin/sh"_へのアドレスは、libcのベースアドレスから計算され、与えられたlibcライブラリになります。
最後に、/bin/sh実行エクスプロイトが準備され送信される予定です:
最終のROPを説明しましょう。\
最後のROP (rop1
) は再びmain関数を呼び出して終了しましたので、オーバーフローを再度利用できます(そのためにOFFSET
が再度ここにあります)。その後、POP_RDI
を呼び出して "/bin/sh" のアドレス (BINSH
) を指し、system 関数 (SYSTEM
) を呼び出します。なぜなら "/bin/sh" のアドレスがパラメータとして渡されるからです。
最後に、exit関数のアドレスが呼び出されるので、プロセスがきちんと終了し、アラートが生成されません。
この方法で、エクスプロイトは _/bin/sh_** シェルを実行します。**
4(2)- ONE_GADGETの使用
ONE_GADGET を使用して、system と "/bin/sh" を使用する代わりにシェルを取得することもできます。ONE_GADGET は、libcライブラリ内で1つの ROPアドレスだけを使用してシェルを取得する方法を見つけます。
ただし、通常、いくつかの制約があります。最も一般的で回避しやすいものは、[rsp+0x30] == NULL
のようなものです。RSP内の値を制御できるため、さらにいくつかのNULL値を送信して制約を回避すればよいです。
EXPLOIT FILE
この脆弱性を悪用するためのテンプレートはこちらにあります:
pageLeaking libc - templateCommon problems
MAIN_PLT = elf.symbols['main'] が見つかりません
"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