linux内核模块替换系统调用

安装内核模块,使自己的代码进入内核空间运行,可以替换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.o
VERSIONID = /lib/modules/$(shell uname -r)/build/
all:
	make -C $(VERSIONID) M=$(PWD) modules
clean:
	make -C $(VERSIONID) M=$(PWD) clean

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

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

sun@sun-desktop:~/program/sun_c/kernel$ make
make -C /lib/modules/4.2.0-25-generic/build/ M=/home/sun/program/sun_c/kernel modules
make[1]: Entering directory '/usr/src/linux-headers-4.2.0-25-generic'
skm===================================
@make -f ./scripts/Makefile.build obj=/home/sun/program/sun_c/kernel
skm==================================
  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.ko
make[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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值