linux内核模块替换系统调用

来源:互联网 发布:sql server distinct 编辑:程序博客网 时间:2024/05/21 06:44

安装内核模块,使自己的代码进入内核空间运行,可以替换linux原有的系统调用。

更改mkdir的系统调用的内核模块代码如下:(ubuntu1510 X86_64)

#include <linux/module.h>#include <linux/kernel.h>// 更改83号mkdir中断处理#define callnumber 83// grep sys_call_table /boot/System.map-`uname -r`unsigned long* sys_call_table = (unsigned long*) 0xffffffff818001c0;unsigned long bak_syscall = 0;asmlinkage long mysyscall(void){    printk(KERN_INFO "this is skm syscall");    return 0;}void change_call(unsigned long address){    unsigned long callnumbe = callnumber;    unsigned long syscalltb = (unsigned long)sys_call_table;    __asm__ __volatile__          (           ".intel_syntax noprefix\n"           "mov rax,cr0\n"         "push rax\n"              "and rax,0xfffffffffffeffff\n"           "mov cr0,rax\n"         "mov rax,%1\n"         "mov rbx,%2\n"         "lea rax,[rax+rbx*8]\n"         "mov rbx,[rax]\n"         "mov %0,rbx\n"         "mov rbx,%3\n"         "mov [rax],rbx\n"         "pop rax\n"         "mov cr0,rax\n"              :"=m"(bak_syscall)           :"m"(syscalltb),"m"(callnumbe),"m"(address)           :"rax","rbx"           );      printk(KERN_INFO "src syscall method address is 0x%lx\n",bak_syscall);    printk(KERN_INFO "our syscall method address is 0x%lx\n",address);}void recover_call(unsigned long address){        printk(KERN_INFO "will recover syscall address is 0x%lx\n",address);    unsigned long callnumbe = callnumber;    unsigned long syscalltb = (unsigned long)sys_call_table;    unsigned long result = 0;    __asm__ __volatile__          (           ".intel_syntax noprefix\n"           "mov rax,cr0\n"         "push rax\n"              "and rax,0xfffffffffffeffff\n"           "mov cr0,rax\n"         "mov rax,%1\n"         "mov rbx,%2\n"         "lea rax,[rax+rbx*8]\n"         "mov %0,rax\n"         "mov rbx,%3\n"         "mov [rax],rbx\n"         "pop rax\n"         "mov cr0,rax\n"              :"=m"(result)         :"m"(syscalltb),"m"(callnumbe),"m"(address)           :"rax","rbx"           );      printk(KERN_INFO "recover syscall table  address is 0x%lx\n",result);    printk(KERN_INFO "recover syscall method address is 0x%lx\n",address);}int insmod_init(void){    unsigned long para = (unsigned long)(&mysyscall);    change_call(para);    return 0;}void rmmod_exit(void){    recover_call(bak_syscall);}module_init(insmod_init);module_exit(rmmod_exit);

使用下面语句建立Makefile文件

obj-m += test.oVERSIONID = /lib/modules/$(shell uname -r)/build/all:make -C $(VERSIONID) M=$(PWD) modulesclean:make -C $(VERSIONID) M=$(PWD) clean

由于代码中使用了intel汇编,编译时Makefile会报错

需要修改Makefile的对应的代码源码文件编译位置添加 -masm=intel语句

sun@sun-desktop:~/program/sun_c/kernel$ makemake -C /lib/modules/4.2.0-25-generic/build/ M=/home/sun/program/sun_c/kernel modulesmake[1]: Entering directory '/usr/src/linux-headers-4.2.0-25-generic'skm===================================@make -f ./scripts/Makefile.build obj=/home/sun/program/sun_c/kernelskm==================================  CC [M]  /home/sun/program/sun_c/kernel/test.o/home/sun/program/sun_c/kernel/test.c: In function ‘insmod_init’:/home/sun/program/sun_c/kernel/test.c:79:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]  unsigned long para = (unsigned long)(&mysyscall);  ^  Building modules, stage 2.  MODPOST 1 modules  CC      /home/sun/program/sun_c/kernel/test.mod.o  LD [M]  /home/sun/program/sun_c/kernel/test.komake[1]: Leaving directory '/usr/src/linux-headers-4.2.0-25-generic'

编译成功使用 sudo insmod test.ko 安装编译好的内核模块

然后使用命令dmesg查看内核日志会显示:

[17795.236888] skm change syscall mkdir[17795.236893] CR0 value is 0x80050033

然后直接在终端执行命令新建目录 mkdir 123

内核日志会记录我们内核模块的相应日志,表示系统调用被我们截断了

[17795.236888] skm change syscall mkdir[17795.236893] CR0 value is 0x80050033[17869.650698] this is skm syscall[17871.123488] this is skm syscall


1 0
原创粉丝点击