web-dev-qa-db-ja.com

完全なASLRおよびNXで、syscallガジェットまたは情報リークのないバイナリを利用する方法は?

そのため、パッチを当てたUbuntu 16.04でリモートで動的に実行されているlibcにリンクされたLinux x86-64バイナリがあります。

実行可能ファイルはlibcを1回呼び出して終了し、ROPへの単純なスタックオーバーフローを許可します。これがバイナリにコンパイルされる唯一のコードです。

-----------------------
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
-----------------------

完全なASLRが有効になっています。

既知のアドレスでsyscallガジェットにアクセスできず、vsyscallが機能する可能性があると聞いた後、vsyscallが新しいカーネルバージョンでエミュレートされており、syscallガジェットに使用できないことがわかりました。

私は、int 0x80、syscall、およびsysenterを手動で検索しましたが、既知の実行可能セクションでそれらが見つからないことを期待しています。

「読み取り」以外の既知のアドレスなしでこのバイナリを悪用する方法を誰かが知っていますか?

私が想像できる唯一の方法は、GOTからlibcアドレスを読み取り、そのアドレスを新しいオフセットで新しい関数に逆参照することです...しかし、逆参照できるガジェットすら見つけられません。

X86-64はエントロピーが多すぎるため、部分的なアドレス上書きブルートフォーシングを使用できません。

知らないテクニックはありますか?

これで壁に頭をぶつけた!

2
Gbps

結局のところ、ソリューションが部分的なアドレス上書きを使用していたことになります。

アドレスを使用してGOTで読み取り、2バイトの部分的なアドレスの上書きを実行して、libcへの読み取りから8192バイトの保証内でジャンプすることができます。 ASLRのバイトエントロピー)。

2バイトの上書き内には、読み取りのアドレスから0x6109バイト離れた、2バイトの距離内にある魔法のガジェットがあります。

one_gadget から、read nearマジックガジェットが見つかります。

0xf0567 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

このバージョンのlibc(2.6.32)では、readの呼び出しは次の場所にあります。

0xF6670 read            proc near

読み取り呼び出しを使用して、読み取りのGOTエントリを上書きし、メインに戻り、マジックガジェットを呼び出すことができます。

また、ROPへの同じ部分的なアドレスの上書きを実行してsyscallをセットアップし、次にreadの最後のバイトを上書きして0x0Eバイトを前方にジャンプし、read内で見つかった自然なsyscallガジェットをヒットすることによって、別の解決策が見つかりました。このようにして、ASLRをブルートフォースして安定したエクスプロイトを実行する必要はありません!

5
Gbps