Linuxカーネル。システムコールフッキングの例
質問
システムコールテーブルをフックするデモとして、簡単なテストコードを書こうとしています。
2.6 では "sys_call_table" はもはやエクスポートされないので、私は System.map ファイルからアドレスを取得しており、それが正しいことがわかります (私が見つけたアドレスのメモリを見ると、システムコールへのポインタが見えます)。
しかし、このテーブルを変更しようとすると、カーネルは "Oops" で "unable to handle kernel paging request at virtual address c061e4f4" を表示し、マシンはリブートされます。
これは、CentOS 5.4 で 2.6.18-164.10.1.el5 を実行しています。何らかの保護があるのでしょうか、それとも単にバグがあるのでしょうか。SELinux が付属していることは知っていますし、寛容モードにしてみましたが、違いはありません。
以下は私のコードです。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
void **sys_call_table;
asmlinkage int (*original_call) (const char*, int, int);
asmlinkage int our_sys_open(const char* file, int flags, int mode)
{
printk("A file was opened\n");
return original_call(file, flags, mode);
}
int init_module()
{
// sys_call_table address in System.map
sys_call_table = (void*)0xc061e4e0;
original_call = sys_call_table[__NR_open];
// Hook: Crashes here
sys_call_table[__NR_open] = our_sys_open;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[__NR_open] = original_call;
}
どのように解決するのですか?
やっと自分で答えを見つけました。
http://www.linuxforums.org/forum/linux-kernel/133982-cannot-modify-sys_call_table.html
カーネルはある時点で変更され、システムコール表は読み取り専用となりました。
cypherpunk
<ブロッククオート遅ればせながら、解決策を は他の人も興味を持つかもしれません。この entry.S ファイルにあります。コードです。
.section .rodata,"a"
#include "syscall_table_32.S"
sys_call_table -> ReadOnly カーネルを新規にコンパイルする必要があります。 カーネルを新規にコンパイルする必要があります。 sys_call_tableをハックするには、カーネルを新規にコンパイルする必要があります。
リンク先には、書き込み可能なメモリに変更する例もあります。
nasekomoe:
<ブロッククオートこんにちは、みなさん。返信をありがとうございます。I メモリページのアクセス方法を変更することで、かなり前に問題を解決しました。 メモリページへのアクセスを変更することで解決しました。I を行う2つの関数を実装しました。 私の上位のコードに実装しました。
#include <asm/cacheflush.h>
#ifdef KERN_2_6_24
#include <asm/semaphore.h>
int set_page_rw(long unsigned int _addr)
{
struct page *pg;
pgprot_t prot;
pg = virt_to_page(_addr);
prot.pgprot = VM_READ | VM_WRITE;
return change_page_attr(pg, 1, prot);
}
int set_page_ro(long unsigned int _addr)
{
struct page *pg;
pgprot_t prot;
pg = virt_to_page(_addr);
prot.pgprot = VM_READ;
return change_page_attr(pg, 1, prot);
}
#else
#include <linux/semaphore.h>
int set_page_rw(long unsigned int _addr)
{
return set_memory_rw(_addr, 1);
}
int set_page_ro(long unsigned int _addr)
{
return set_memory_ro(_addr, 1);
}
#endif // KERN_2_6_24
以下は、私のために動作するオリジナルのコードの修正版です。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
void **sys_call_table;
asmlinkage int (*original_call) (const char*, int, int);
asmlinkage int our_sys_open(const char* file, int flags, int mode)
{
printk("A file was opened\n");
return original_call(file, flags, mode);
}
int set_page_rw(long unsigned int _addr)
{
struct page *pg;
pgprot_t prot;
pg = virt_to_page(_addr);
prot.pgprot = VM_READ | VM_WRITE;
return change_page_attr(pg, 1, prot);
}
int init_module()
{
// sys_call_table address in System.map
sys_call_table = (void*)0xc061e4e0;
original_call = sys_call_table[__NR_open];
set_page_rw(sys_call_table);
sys_call_table[__NR_open] = our_sys_open;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[__NR_open] = original_call;
}
関連
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
エラー: 宣言されていない識別子 'bool' の使用と C コンパイラでの問題点
-
[解決済み] Valgrind が初期化されていないバイトについて警告する
-
[解決済み] MIPSのネストされたForループと配列の使用
-
[解決済み] C言語で関数型プログラミングを行うためのツールにはどのようなものがありますか?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] while ( !feof (file) ) 」は、なぜいつも間違っているのですか?
-
[解決済み] プログラム終了前にmallocの後にfreeをしないと本当に何が起こるのか?
-
[解決済み] longをフォーマットするprintfの引数は何ですか?
-
[解決済み] 講師が書いたC言語のファイルは、なぜ最初の行に#が一つ付いているのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
赤線の位置は必ずしも間違っていない:式は変更可能なlvalueでなければならないエラーは、この文とは別の場所に存在する可能性があります。
-
関数 'malloc' の暗黙の宣言に対する解決策
-
コンパイルエラー:可変長オブジェクトが初期化されていない可能性があります。
-
[解決済み] C 言語で const char* を char* に変換するには?
-
[解決済み] C言語の**はどういう意味ですか?
-
[解決済み] Cコードの単体テスト【終了しました
-
[解決済み] なぜC言語では構造体を頻繁にtypedefする必要があるのですか?
-
[解決済み] FortranはC言語よりも重い計算を最適化しやすいですか?
-
[解決済み] C言語でファイルサイズを取得するには?[重複]する