需要编写一个内核模块,带有一个exec的钩子.我找到了sys_calls_table
和lsm
的方法.据我所知,sys_calls_table
更像是一个黑客而不是一个正确的解决方案,我没有找到lsm
的正常例子.
如何在现代内核版本中正确拦截系统调用?我很乐意举一些例子.
需要编写一个内核模块,带有一个exec的钩子.我找到了sys_calls_table
和lsm
的方法.据我所知,sys_calls_table
更像是一个黑客而不是一个正确的解决方案,我没有找到lsm
的正常例子.
如何在现代内核版本中正确拦截系统调用?我很乐意举一些例子.
没有正确的方法可以做到这一点.
LSM(Linux安全模块)不支持系统调用拦截,
据我所知,有两种截获系统调用的替代方法:
钩住可以获得的sys_call_table
,并用新函数覆盖指针:
unsigned long *sys_call_table_ptr = kallsyms_lookup_name("sys_call_table");
unsigned long cr0 = read_cr0();
write_cr0(cr0 & ~x86_CR0_WP);
sys_call_table_ptr[__NR_getpid] = new_getpid;
write_cr0(cr0);
使用kprobe:Syscall函数,函数名以前缀__do_sys_
展开(请参见__SYSCALL_DEFINEx).
static struct kprobe kp = {
.symbol_name = "__do_sys_finit_module",
};
static int handler_pre(struct kprobe *p, struct pt_regs *regs) {
// do your logic
// obtain function arguments using register (calling convetion)
}
static int __init kprobe_init(void)
{
kp.pre_handler = handler_pre;
ret = register_kprobe(&kp);
if (ret < 0) {
printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
return ret;
}
printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
return 0;
}
static void __exit kprobe_exit(void)
{
unregister_kprobe(&kp);
printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
}