GNU/Linux >> Linux の 問題 >  >> Linux

Linux カーネル ROP - カーネル コンテキストからユーザーランドに戻る?

私はシェルコードを別の方法で書くことになりました。戻る方法がわからなかったので、ユーザーランドに戻る際に、カーネルに面倒な作業を任せました。アイデアは、特権エスカレーション ビットを実行し、レジスタとスタックを修正して、脆弱な関数が戻るはずだった場所に戻ることでした。

カーネルが脆弱な関数から戻った直後 (オーバーフローしていないとき)、 gdb 経由で何かに気づきました . (アドレスは想像上のものですが、とにかく概念を説明しています。)

(gdb) x/i $eip
0xadd1: ret
(gdb) x/xw $esp
0xadd1: 0xadd2
(gdb) x/6i 0xadd2
0xadd2: add esp,0x40
0xadd3: pop ...
0xadd4: pop ...
0xadd5: pop ...
0xadd6: pop ...
0xadd7: ret

したがって、リターンの直後、スタックの 0x40 バイトは使用されていません add esp で単純に消えます 命令。したがって、この事実を利用して、24 バイトの長さの ROP チェーンを構築しました (この質問を書いている間に既に構築していました。その仕事は、SMEP を無効にして、ユーザーランドのシェルコードにジャンプすることでした)。リターン時に 4 バイトが EIP を上書きし、残りの 20 (0x14 ) は、未使用のスタックに続きます。これで 0x2c が残ります まだ未使用のスタックのバイト。

しかし、もし 0xadd2 に戻ったら 、さらに 0x14 を失うリスクがあります スタックから数バイトの貴重なレジスタ情報を取得し、無効なデータでレジスタをいっぱいにします。 add 0x2cできました esp まで ユーザーランドのシェルコードで、直接 0xadd3 にジャンプします 、実際の add をスキップします

また、デバッグセッションから、eax を除くすべてに注意してください と ebx 正常に復元されていました。私のオーバーフローはそれらの両方を破壊したので、関数がクリーンなリターンを行った場合と同様の値でそれらを復元する必要がありました. (これを行うのは簡単でした:0xadd2 にブレークポイントを設定しました 、および info reg から値を抽出しました )

したがって、私の最終的なユーザーランド シェルコードは次のとおりです。

Execute privesc payload -> add esp,0x2c -> register fixup -> jump to 0xadd3

これを行うと、コード パスは完全にクリーンに戻り、カーネルはユーザー モードに戻るタスクを実行しました。


Linux
  1. Linuxカーネルでの2038年問題の解決

  2. Linux –異なるLinux / UNIXカーネルは交換可能ですか?

  3. CコードからLinuxカーネルモジュールをロードする方法は?

  1. 私のLinuxストーリー:8ビット愛好家からUnixシステム管理者まで

  2. root ユーザーから Linux カーネルを保護するのはなぜですか?

  3. Linux カーネルからメモリのブロックを予約するにはどうすればよいですか?

  1. MacからLinuxに切り替えた理由

  2. Linuxシステム管理者になる:販売からシステム管理者まで

  3. Linuxでの仕事の仕方:初心者からプロまで