Leaking libc address with ROP
Last updated
Last updated
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
オーバーフローのオフセットを見つける
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
エクスプロイトをダウンロードし、脆弱なバイナリと同じディレクトリに配置し、スクリプトに必要なデータを提供します:
テンプレートは、エクスプロイトを続行する前にオフセットが必要です。提供された場合は、必要なコードを実行してそれを見つけます(デフォルトでは OFFSET = ""
):
実行 python template.py
すると、プログラムがクラッシュした状態で GDB コンソールが開きます。その GDB コンソール 内で x/wx $rsp
を実行して、RIP を上書きしようとしている バイト を取得します。最後に、python コンソールを使用して オフセット を取得します:
オフセットを見つけたら(この場合は40)、その値を使ってテンプレート内のOFFSET変数を変更します。
OFFSET = "A" * 40
別の方法としては、pattern create 1000
-- retまで実行 -- pattern seach $rsp
をGEFから使用することです。
次に、バイナリ内のROPガジェットを見つける必要があります。このROPガジェットは、libcを見つけるためにputs
を呼び出すのに役立ち、後で最終的なエクスプロイトを実行するために使用されます。
PUTS_PLT
はfunction putsを呼び出すために必要です。
MAIN_PLT
はexploitのためにoverflowをagain実行するために、1回のインタラクションの後にmain functionを再度呼び出すために必要です(無限のexploitのラウンド)。各ROPの最後でプログラムを再度呼び出すために使用されます。
POP_RDIは呼び出された関数にparameterをpassするために必要です。
このステップでは、pwntoolsが実行中にすべてを見つけるため、何も実行する必要はありません。
今はどのバージョンのlibcライブラリが使用されているかを見つける時です。そうするために、function puts
のメモリ内のaddressをleakし、そのアドレスにあるputsのバージョンがどのlibrary versionにあるかをsearchします。
これを行うために、実行されたコードの最も重要な行は次のとおりです:
これは、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
でライブラリを見つければよいです)。
しかし、リモートエクスプロイトの場合、ここでそれを見つける方法を説明します:
ウェブページで使用されているライブラリを検索できます: https://libc.blukat.me/ これにより、発見されたlibcのバージョンをダウンロードすることもできます。
次のようにすることもできます:
$ 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 を作業ディレクトリにコピーします。
この時点で、使用されている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_**シェルを実行します。**
systemと**"/bin/sh"を使用する代わりに、ONE_GADGETを使用してシェルを取得することもできます。ONE_GADGETはlibcライブラリ内で、1つのROPアドレス**を使用してシェルを取得する方法を見つけます。
ただし、通常はいくつかの制約があり、最も一般的で回避しやすいものは[rsp+0x30] == NULL
のようなものです。RSP内の値を制御しているので、制約を回避するためにいくつかのNULL値を送信するだけです。
この脆弱性を悪用するためのテンプレートはここにあります:
"main" シンボルが存在しない場合、メインコードの場所を見つけることができます:
そしてアドレスを手動で設定します:
バイナリが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
"/bin/sh"のアドレスから64バイトを引いてみてください:
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)