3

巨大なカーネルインターセプトを再実装しようとしています(このPhrackの問題で説明されています)。

32ビット関数呼び出しを置き換えるコードは次のようになります。

#define SYSMAPADDR 0x12345678
#define CODESIZE 7
static char acct_code[7] = "\xb8\x00\x00\x00\x00"/*movl $0, %eax*/
"\xff\xe0";/*jmp *%eax*/
*(long*)&acct_code[1] = (long)my_hijacking_function;
// here, use either set_pages_rw or trick CR0 to do this:
memcpy(SYSMAPADDR, acct_code, CODESIZE);

ただし、元の関数の64ビットアドレスは0xffffffff12345678です(カーネルは低メモリにあります)。

では、(長い)新しい関数ポインターはmovl命令の4 \ x00バイトにちょうど収まりますか?

ところで、これをリンクしてくださいLinuxカーネル関数をモジュールに置き換えることはできますか?Linuxカーネルのモジュールで機能をオーバーライドすると、上記のハッキーな方法はより柔軟になります(外部以外の関数をインターセプトできます=>カーネルを再コンパイルする必要はありません)。

4

3 に答える 3

4

x86 (32 ビットまたは 64 ビット) では、ディスプレースメントが 2GB を超えるアドレスに無条件で直接ジャンプする方法はありません。

少し前に迂回ライブラリを作成したとき、プログラム フローをリダイレクトするために思いついた最良のオプション (x86-64 の場合) は、ターゲット関数のプロローグをMバイト単位でバックアップし、ターゲット関数のプロローグを 2 つの命令で上書きすることでした。

アキュムレータの代わりに%r11レジスタを使用します。AMD64 ABI Draft 0.99.5によると、%r11は関数呼び出し間で保持されない一時レジスタです。

最初の命令 はmovq $addr, %r11、指定されたアドレスをレジスタにロードします。2 番目の命令 は、 %r11jmp *%r11に格納されているアドレスへの無条件の間接ジャンプを強制します。

バックアップされた命令の最後に、上書きされた命令の直後のアドレスに、元のターゲットの関数に戻る別の無条件の間接ジャンプを追加する必要があります。次に、オリジナルを呼び出したい場合は、バックアップされた関数プロローグのアドレスを呼び出すことができ、プログラム フローは通常どおり続行されます。

バックアップするバイト数 はM、ストア/ジャンプ命令のサイズと上書きされた命令の残りのサイズの合計でなければならないことに注意してください。このブードゥーを行った後、部分的な指示を残したくありません。

于 2011-04-19T03:21:17.450 に答える
2

注: これは x86_64 用であると想定しています。

関数ポインタは 64 ビットで、movl命令は 64 ビット レジスタにゼロ拡張されるため、マシン コードを書き直す必要があります。必要な命令はおそらく48 B8 (imm64)(つまりmovq ..., %rax) であり、ジャンプ命令はそのままにしておくことができると思いますが、これについてはよくわかりません。おそらく、質問に「x86-64」および「assembly」タグを追加する必要があります。

于 2011-04-16T19:01:07.683 に答える
1

(0xE9) 操作を使用JMP rel32して、現在のアドレスから 32 ビットの相対ジャンプを実行できます。これにより、5 バイトでソース アドレスの 2GB 以内の任意の場所にジャンプできます。また、%eax を壊さないという利点もあります (これは、あなたのケースでは重要かもしれませんし、そうでないかもしれません)。

とはいえ、代わりにkprobes APIを調べることをお勧めします。これにより、実行時のパッチ適用のすべてのハードワークが処理されます。また、同じ機能に適用される複数のマーカーやその他の厄介なことにも対処し、複数のプラットフォームに移植できます。特に、モンキー パッチ アプローチが使用されていた場合、コンパイルされた場合にマーカー API と競合し、クラッシュが発生する可能性がありました。また、動的にパッチを適用できるコードが関数の最初の数バイト (LOCK プレフィックスなど) にある場合にも、クラッシュが発生します。

また、 ftraceがどのように機能するかを調べることもできます。カーネルの構成によっては、代わりに ftrace にフックする方が多少速い場合があります。

于 2011-03-07T18:19:14.353 に答える