我想拦截open()
系统调用,以便在用户每次打开文件时进行测试,应该在dmesg
中显示消息“ OPEN IS!”。
已显示dmesg
中的系统调用表和公开呼叫地址,但看不到消息“ OPEN IS!”。内核v.4.18
我想知道问题是什么。代码:
unsigned long cr0;
static unsigned long *__sys_call_table;
typedef asmlinkage int (*orig_open_t)(const char *, int, int);
orig_open_t orig_open;
unsigned long *
get_syscall_table_bf(void)
{
unsigned long *syscall_table;
unsigned long int i;
for (i = (unsigned long int)ksys_close; i < ULONG_MAX;
i += sizeof(void *)) {
syscall_table = (unsigned long *)i;
if (syscall_table[__NR_close] == (unsigned long)ksys_close) {
printk(KERN_INFO "syscall: %08lx\n", syscall_table);
return syscall_table;
}
}
return NULL;
}
asmlinkage int
hacked_open(const char *filename, int flags, int mode)
{
printk(KERN_INFO "OPEN IS!\n");
return 0;
}
static inline void
protect_memory(void)
{
write_cr0(cr0);
}
static inline void
unprotect_memory(void)
{
write_cr0(cr0 & ~0x00010000);
}
static int __init
diamorphine_init(void)
{
__sys_call_table = get_syscall_table_bf();
if (!__sys_call_table)
return -1;
cr0 = read_cr0();
orig_open = (orig_open_t)__sys_call_table[__NR_open];
unprotect_memory();
__sys_call_table[__NR_open] = (unsigned long)hacked_open;
printk(KERN_INFO "WE DO IT!\n");
printk(KERN_INFO "hacked is: %08lx\n", hacked_open);
protect_memory();
return 0;
}
static void __exit
diamorphine_cleanup(void)
{
unprotect_memory();
__sys_call_table[__NR_open] = (unsigned long)orig_open;
protect_memory();
}
module_init(diamorphine_init);
module_exit(diamorphine_cleanup);
MODULE_LICENSE("GPL");
答案 0 :(得分:1)
我猜想您的上钩方式有误。您要么挂错了syscall表的偏移量,要么就完全退出了。我不明白为什么您明确地开始使用ksys_close()进行搜索,尤其是当它是内联函数时。您应该尝试像这样查找syscall表符号:
typedef void (*_syscall_ptr_t)(void);
_syscall_ptr_t *_syscall_table = NULL;
_syscall_table=(_syscall_ptr_t *)kallsyms_lookup_name("sys_call_table");
我看到的一个不同的(巨大)问题是重置CR0,它允许系统中的任何内容在写入时写入只读存储器,而不是遍历页面并在特定位置设置W位您要编辑的页面。
另外一个小建议:您应该完成钩子才能重定向到原始的打开syscall。否则,您将导致整个系统从STDIN中读取每个新打开的文件描述符(最终将杀死您的系统)