Linux:内核模块实现替换系统调用的简单例子

来源:互联网 发布:排八字软件 编辑:程序博客网 时间:2024/04/30 11:04

原文链接:http://blog.csdn.net/ddk3001/article/details/51485135

编写Linux内核模块,可以实现替换系统调用功能。
本文提供一个替换open系统调用的样例代码,功能和说明见代码。

参考代码:https://github.com/ricardoteixas/hook
在 https://github.com 中搜索 hook、kernel等,可以搜到很多可参考的代码。

/***************************************************************************文件 : hook_open.c功能 : 这是一个简单的内核模块,功能是替换了系统调用oepn,实现自定义open功能。关键函数 :my_sys_open         // 自定义的open系统调用处理函数syscall_init        // 内核模块初始化函数syscall_release     // 内核模块退出函数源代码参考 :  https://github.com/ricardoteixas/hook***************************************************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/syscalls.h>#include <linux/delay.h> #include <linux/sched.h>#include <linux/version.h>/**************************************************************************////**************************************************************************/// Write Protect Bit (CR0:16)#define CR0_WP 0x00010000 MODULE_LICENSE("GPL");void **syscall_table;unsigned long **find_sys_call_table(void);// !!!!!asmlinkage long  (*orig_sys_open)(const char __user *filename, int flags, umode_t mode);/*************************************************************************** * /boot/System.map-3.13.0-43-generic: * * ffffffff811bb230 T sys_close * ffffffff81801400 R sys_call_table * ffffffff81c15020 D loops_per_jiffy * **************************************************************************/unsigned long **find_sys_call_table(){    unsigned long ptr;    unsigned long *p;    for (ptr = (unsigned long) sys_close; ptr < (unsigned long) &loops_per_jiffy; ptr += sizeof(void *))    {        p = (unsigned long *) ptr;        if (p[__NR_close] == (unsigned long) sys_close)        {            return (unsigned long **) p;        }    }    return NULL;}/**************************************************************************///// 自定的open系统调用函数: 如果要打开的是 /home/test1.txt,则改为打开 /home/test2.txt//// 关键函数: strncpy_from_user 、 set_fs 、set_fs///**************************************************************************/asmlinkage long my_sys_open( const char __user  *filename, int flags, umode_t mode ){    char temp[256] = { 0 };    char *test2 = "/home/test2.txt";    // 需要把用户空间的数据拷贝到内核空间,才能使用    (void)strncpy_from_user( temp, filename, PATH_MAX );        if ( !strcmp( temp, "/home/test1.txt" ) )    {        mm_segment_t fs_save;        long ret;        // get_fs 和 set_fs 是为了使系统调用函数能够访问内核空间数据(本来参数应该是用户空间数据)        // 关于 get_fs 和 set_fs,参考: http://blog.chinaunix.net/uid-27717694-id-4076498.html        fs_save = get_fs();        set_fs( get_ds() );        ret = orig_sys_open( (const char __user *)test2, flags, mode );        set_fs( fs_save );        return ret;    }    return orig_sys_open(filename, flags, mode);}/**************************************************************************///// 内核模块初始化函数///**************************************************************************/static int __init syscall_init(void){    unsigned long cr0;    printk(KERN_DEBUG "Let's do some magic!\n");    syscall_table = (void **) find_sys_call_table();    if (! syscall_table) {        printk(KERN_DEBUG "ERROR: Cannot find the system call table address.\n");         return -1;    }    printk(KERN_DEBUG "Found the sys_call_table at %16lx.\n", (unsigned long) syscall_table);    cr0 = read_cr0();    write_cr0(cr0 & ~CR0_WP);    printk(KERN_DEBUG "Houston! We have full write access to all pages. Proceeding...\n");    orig_sys_open = syscall_table[__NR_open];    syscall_table[__NR_open] = my_sys_open;    write_cr0(cr0);    return 0;}/**************************************************************************///// 内核模块退出函数///**************************************************************************/static void __exit syscall_release(void){    unsigned long cr0;    printk(KERN_DEBUG "I hate you!\n");    cr0 = read_cr0();    write_cr0(cr0 & ~CR0_WP);    syscall_table[__NR_open] = orig_sys_open;    //syscall_table[__NR_access] = orig_sys_access;    write_cr0(cr0);}/**************************************************************************////**************************************************************************/module_init(syscall_init);module_exit(syscall_release);


下面是Makefile文件内容:

# Makefileobj-m:=hook_open.o  KERNELBUILD:=/lib/modules/$(shell uname -r)/build default:    make -C $(KERNELBUILD) M=$(shell pwd) modulesclean:    rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions


编译模块 : make
编译清除:make clean

安装模块 : sudo insmod hook_open.ko
卸载模块 : sudo rmmod hook_open
查看模块 : lsmod | grep hook_open

0 0
原创粉丝点击