C 拦截系统调用
我一直试图在内核级别拦截系统调用。我从中得到了基本的想法。我试图拦截的系统调用是fork()。因此,我从System.map中找到了sys_fork()的地址,结果是0xc1010e0cC 拦截系统调用,c,linux,linux-kernel,kernel-module,kernel,C,Linux,Linux Kernel,Kernel Module,Kernel,我一直试图在内核级别拦截系统调用。我从中得到了基本的想法。我试图拦截的系统调用是fork()。因此,我从System.map中找到了sys_fork()的地址,结果是0xc1010e0c #include<linux/kernel.h> #include<linux/module.h> #include<linux/unistd.h> #include<linux/semaphore.h> #include<asm/cacheflush.h&
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/unistd.h>
#include<linux/semaphore.h>
#include<asm/cacheflush.h>
MODULE_LICENSE("GPL");
void **sys_call_table;
asmlinkage int (*original_call)(struct pt_regs);
asmlinkage int our_call(struct pt_regs regs)
{
printk("Intercepted sys_fork");
return original_call(regs);
}
static int __init p_entry(void)
{
printk(KERN_ALERT "Module Intercept inserted");
sys_call_table=(void *)0xc1010e0c;
original_call=sys_call_table[__NR_open];
set_memory_rw((long unsigned int)sys_call_table,1);
sys_call_table[__NR_open]=our_call;
return 0;
}
static void __exit p_exit(void)
{
sys_call_table[__NR_open]=original_call;
set_memory_ro((long unsigned int)sys_call_table,1);
printk(KERN_ALERT "Module Intercept removed");
}
module_init(p_entry);
module_exit(p_exit);
#包括
#包括
#包括
#包括
#包括
模块许可证(“GPL”);
作废**系统调用表;
ASMINT(*原始调用)(结构参数寄存器);
ASMINT our_调用(struct pt_regs regs)
{
printk(“截获的系统分叉”);
返回原始通话(regs);
}
静态int\u初始p\u条目(void)
{
printk(插入模块拦截的内核警报);
系统调用表=(void*)0xc1010e0c;
原始调用=系统调用表[\uuuu NR\u open];
set_memory_rw((长无符号整数)sys_call_table,1);
系统调用表[\uuuu NR\u open]=我们的调用;
返回0;
}
静态无效uu退出p_退出(无效)
{
系统调用表[\uuuuu NR\u open]=原始调用;
设置内存表((长无符号整数)系统调用表,1);
printk(内核警报“模块拦截已删除”);
}
模块初始化(p_条目);
模块_出口(p_出口);
然而,在编译模块之后,当我试图将其插入内核时,我从dmesg输出中得到了以下信息。
当然不是拦截系统调用。你能帮我解决问题吗?我使用的是3.2.0-4-686版本的Linux内核
original_call=sys_call_table[__NR_open];
....
sys_call_table[__NR_open]=our_call;
如果您正在拦截fork
,则open
的条目不是您想要更改的内容。
您应该使用sys\u call\u table
的地址,而不是System.map中sys\u fork()的地址
因此,警告是因为sys\u call\u table
变量未对齐页面
应该说,内核维护人员官方不鼓励修补系统调用表,他们故意给您设置了一些障碍——您可能已经注意到,您无法访问真正的
sys\u call\u table
符号,写保护也是故意的。如果你能找到另一种方法去做你想做的事,那么你应该这样做。根据您更大的目标,您可能可以使用而不使用任何内核模块来完成它。trace\u sched\u process\u fork
钩子也可能有用。不清楚您是否解决了问题,但取决于您测试模块的方式,glib不再使用sys\u fork,而是使用sys\u clone。是的。但是(刚刚编辑了答案)您应该使用sys_call_table的地址来初始化sys_call_table指针,而不是sys_fork的原始地址。当然,我犯了一个错误,使用了u NR_open而不是u NR_fork。但问题似乎并没有就此结束。现在我不确定将set_memeory_rw()应用于sys_call_表的有效性。这需要进一步调查。有什么意见吗?
if (*addr & ~PAGE_MASK) {
*addr &= PAGE_MASK;
/*
* People should not be passing in unaligned addresses:
*/
WARN_ON_ONCE(1);
}