linux下系统调用劫持ioctl

实验环境:linux 2.6.32   64位系统


采用lkm(动态加载内核模块)方式劫持ioctl系统调用,系统调用过程如图所示(以open为例子)


实验代码:(头文件有不需要的,但是懒得改了,在系统开发时依赖 kernel-devel开发工具)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/fs_struct.h>
#include <linux/fdtable.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/syscalls.h>
#include <linux/list.h>
#include <linux/jiffies.h>
#include <linux/cdev.h>
#include <linux/path.h>
#include <linux/time.h>
#include <linux/stat.h>
#include <net/sock.h>
#include <net/inet_sock.h>
#include <linux/cdrom.h>
#include <linux/types.h>
#include <linux/security.h>
#include <linux/export.h>
#include <linux/uaccess.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h>
#include <linux/falloc.h>
#include <asm/cpufeature.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
#include <linux/compiler.h>
#include <linux/posix_types.h>
#include <linux/syscalls.h>
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/mmzone.h>
#include <linux/time.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/workqueue.h>


#include <linux/syscalls.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/capability.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h>
#include <linux/falloc.h>
#include <linux/ioctl.h>
#include <asm/ioctls.h>

//通过内核符号表查找到的sys_call_table的地址
//  grep sys_call_table /boot/System.map-`uname -r` 
unsigned long **sys_call_table = (unsigned long **)0xffffffff81600520;
//unsigned long *orig_mkdir = NULL;  
//unsigned long *orig_ioctl = NULL;
asmlinkage long (*orig_ioctl)(unsigned int fd, unsigned int cmd,
unsigned long arg);
//为了可以对sys_call_table所在内存页,进行读写,需要重新设置页的属性。
/* make the page writable */
int make_rw(unsigned long address)
{
        unsigned int level;
        pte_t *pte = lookup_address(address, &level);//查找地址所在的内存页面
        if (pte->pte & ~_PAGE_RW) //设置读写属性
                pte->pte |=  _PAGE_RW;
        return 0;
}
/* make the page write protected */
int make_ro(unsigned long address)
{
        unsigned int level;
        pte_t *pte = lookup_address(address, &level);
        pte->pte &= ~_PAGE_RW; //设置只读属性
        return 0;
}
//mkdir的函数原型,这个函数的原型要和系统的一致
/*asmlinkage long hacked_mkdir(const char __user *pathname, int mode)
{
        printk("mkdir pathname: %s ", pathname);
        printk(KERN_ALERT "mkdir do nothing! ");
        return 0; //everything is ok, but he new systemcall does nothing*/
//}
// you should change inside code according your kernel version
asmlinkage long hacked_ioctl(unsigned int fd, unsigned int cmd,
unsigned long arg){
printk("hacking ");
if(cmd == CDROMEJECT){
printk("HiveMe Hack! ");
return 0;
}

return orig_ioctl(fd,cmd,arg);
}


//也是内核初始化函数
static int syscall_init_module(void)
{
        printk(KERN_ALERT "sys_call_table: 0x%p ", sys_call_table);
      //  orig_mkdir = (unsigned long *)(sys_call_table[__NR_mkdir]); //获取原来的系统调用地址
        orig_ioctl = (unsigned long *)(sys_call_table[__NR_ioctl]);
     //   printk(KERN_ALERT "orig_mkdir: 0x%p ", orig_mkdir);
printk(KERN_ALERT "orig_ioctl: 0x%p ", orig_ioctl);
        make_rw((unsigned long)sys_call_table); //修改页属性
    //    sys_call_table[__NR_mkdir] = (unsigned long *)hacked_mkdir; //设置新的系统调用地址
    //    printk("mkdir ");
      sys_call_table[__NR_ioctl] = (unsigned long *)hacked_ioctl;
printk("ioctl ");
       // make_ro((unsigned long)sys_call_table);
        return 0;
}

//内核注销函数
static void syscall_cleanup_module(void)
{
        printk(KERN_ALERT "Module syscall unloaded. ");


        make_rw((unsigned long)sys_call_table);
      //  sys_call_table[__NR_mkdir] = (unsigned long *)orig_mkdir;
sys_call_table[__NR_ioctl] = (unsigned long *)orig_ioctl;
        /*set mkdir syscall to the origal one*/
        make_ro((unsigned long)sys_call_table);
}
module_init(syscall_init_module);
module_exit(syscall_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("hack syscall");
代码源自其他网友,进行了部分修改,如原作者需要特殊标注请与我联系



原文地址:https://www.cnblogs.com/hiveme/p/8194834.html