关于劫持系统调用时的sys_call_table地址,在上篇文章中提到了手动获取系统调用表地址的方法,本文采用 kallsyms_lookup_name() 来获得sys_call_table的符号地址。
文章指路:https://blog.csdn.net/ShirokoYae/article/details/119036040
主要参考文章:https://blog.csdn.net/zzzpany/article/details/94308431
次要参考文章:https://blog.csdn.net/bin_linux96/article/details/104031561
问题说明:
(1)insmod 时出现 killed 问题,大概率是系统调用表地址错误造成的。
(2)在主要参考文章中,将sys_call_table定义成了全局变量,在函数中赋值获取地址,这样做可能会获取到错误的地址。于是定义了局部变量,在初始化和退出的时候各获取一次即可。
头文件可能有多余,只作为参考。自动获取地址只需要编译一次即可,每次开机只需要将 .ko 文件动态载入内核模块,即可自动获取其地址。使用方法同上篇文章,只是修改了源程序。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/syscalls.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/dcache.h>
#include <linux/path.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
int (*orig_mkdir)(void);
unsigned int clear_and_return_cr0(void);
void setback_cr0(unsigned int val);
unsigned int orig_cr0;
int my_mkdir(void)
{
int pid = current->pid;
int ppid = current->real_parent->real_parent->pid;
const char *ppwd = (current->fs->root).dentry->d_name.name;
struct path pwd;
get_fs_pwd(current->fs,&pwd);
printk(KERN_WARNING "Warnning Someone(PID=%d,parent=%d) attempts to mkdir!\n",pid,ppid);
printk(KERN_WARNING "ROOT:%s!\n",ppwd);
printk(KERN_WARNING "PWD:%s!\n",pwd.dentry->d_name.name);
return 0;
}
unsigned int clear_and_return_cr0(void)
{
unsigned int cr0 = 0;
unsigned int ret;
asm volatile ("movq %%cr0, %%rax":"=a"(cr0));
ret = cr0;
cr0 &= 0xfffeffff;
asm volatile ("movq %%rax, %%cr0"::"a"(cr0));
return ret;
}
void setback_cr0(unsigned int val)
{
asm volatile ("movq %%rax, %%cr0"::"a"(val));
}
int hello_init(void)
{
unsigned long* sys_call_table = (unsigned long*)kallsyms_lookup_name("sys_call_table");
printk(KERN_INFO "Hello kernel!\n");
orig_cr0 = clear_and_return_cr0();
orig_mkdir=(int (*)(void))sys_call_table[__NR_mkdir];
sys_call_table[__NR_mkdir] = (unsigned long)my_mkdir;
setback_cr0(orig_cr0);
return 0;
}
void hello_exit(void)
{
unsigned long* sys_call_table = (unsigned long*)kallsyms_lookup_name("sys_call_table");
printk("Bye, kernel!");
orig_cr0 = clear_and_return_cr0();
sys_call_table[__NR_mkdir] = (unsigned long)orig_mkdir;
setback_cr0(orig_cr0);
}
module_init(hello_init);
module_exit(hello_exit);