我正在尝试使用Jprobes在Linux内核上执行一个'do_execve()‘函数的钩子,但是我在某些系统上遇到了问题。我尝试在Ubuntu 12,64位(Kernel版本3.11)上使用我在网上找到的代码:
Hook.c:
/* Trace do_execv. Taken basically from Documentation/kprobes.txt */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
/*
* Pre-entry point for do_execve.
*/
static int my_do_execve(char * filename,
char __user *__user *argv,
char __user *__user *envp,
struct pt_regs * regs)
{
printk("do_execve for %s from %s\n", filename, current->comm);
/* Always end with a call to jprobe_return(). */
jprobe_return();
/*NOTREACHED*/
return 0;
}
static struct jprobe my_jprobe = {
.entry = (kprobe_opcode_t *) my_do_execve
};
int init_module(void)
{
int ret;
my_jprobe.kp.addr =
(kprobe_opcode_t *) kallsyms_lookup_name("do_execve");
if (!my_jprobe.kp.addr) {
printk("Couldn't find %s to plant jprobe\n", "do_execve");
return -1;
}
if ((ret = register_jprobe(&my_jprobe)) <0) {
printk("register_jprobe failed, returned %d\n", ret);
return -1;
}
printk("Planted jprobe at %p, handler addr %p\n",
my_jprobe.kp.addr, my_jprobe.entry);
return 0;
}
void cleanup_module(void)
{
unregister_jprobe(&my_jprobe);
printk("jprobe unregistered\n");
}
MODULE_LICENSE("GPL");Makefile:
# This is taken straight from Documentation/kprobes.txt
obj-m := trace-exec.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.mod.c *.ko *.o该模块的工作与预期一致。它首先在系统上正确编译,然后使用函数'insmod‘(具有ROOT权限)插入。运行dmesg会显示正确的输出:
Planted Jprobes at [ADDRESS HERE], handler addr [ADDRESS HERE]
do_execve for /bin/sh from wcstatusd [PRINTED FOR ANY EXECUTED PROCESS]当我在Ubuntu 14,64位(内核版本3.13)系统上尝试相同的代码时,出现了这个问题。我在系统上重新编译并插入了它,就像我在以前的系统上所做的那样,但是这一次它没有工作。我没有得到任何错误,并且输出了成功消息("Planted at ADDRESS WAS,handler ADDRESS HERE"),但是没有打印'do_execve‘行。我浏览了一下谷歌,但找不到一个解释或解决方案。有什么想法吗?
注意:我也试过在Ubuntu14上挂接'do_fork()‘,它起作用了!这只是'do_execve()‘的一些东西,我不知道是什么!
发布于 2015-04-16 01:30:22
do_execve()的定义在exec.c http://lxr.free-electrons.com/source/fs/exec.c?v=3.11#L1584中
下面是do_execve()的代码。只需在后面添加一行
int do_execve(struct filename *filename,const char __user *const __user *__argv,const char __user *const __user *__envp)
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct user_arg_ptr envp = { .ptr.native = __envp };
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
EXPORT_SYMBOL(do_execve); // Add this line.该文件将位于linux/fs/exec.c中。在fuction.And之后添加EXPORT_SYMBOL()行,然后执行make、make install和reboot。这几乎就像钩子一样,因为我们必须重新构建和安装内核。假设您没有在运行时通过修改系统调用地址来拦截调用。
https://stackoverflow.com/questions/29210260
复制相似问题