一般情况有四个部分
pre_probe, post_probe, kprobe_ init, kprobe_exit.
probe addr 两种方式获得,一种直接调用kallsyms_lookup_name(“you_function”),
另外一种是直接给地址 0xabcd. 可用的函数和地址都是通过cat /proc/kallsyms 找到。
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#INCLUDE <linux/kprobes.h>
#include <linux/kallsyms.h>
#include "asm/ptrace.h"
#include "asm/current.h"
#include "linux/utsname.h"
/* global probe object */
struct kprobe probe;
/*
* enter the probe pointer
*/
static int pre_probe(struct kprobe *probe, struct pt_regs *regs)
{
printk("Hit it\n");
return 0;
}
/*
* exit the probe pointer
*/
static void post_probe(struct kprobe *probe, struct pt_regs *regs, unsigned long flags)
{}
static int __init kprobe_ init(void)
{
probe.pre_handler = pre_probe;
probe.post_handler = post_probe;
//probe.addr = (kprobe_opcode_t *) 0xaddress;
probe.addr = (kprobe_opcode_t *) kallsyms_lookup_name("you_function");
if (probe.addr == NULL) {
return 1;
}
register_kprobe(&probe);
printk("register probe driver.\n");
return 0;
}
static void __exit kprobe_exit(void)
{
unregister_kprobe(&probe);
printk("unregister probe driver.\n");
return;
}
module_init(kprobe_ init);
module_exit(kprobe_ exit);
MODULE_LICENSE("GPL");
|
如果想拿到函数中的参数,在X86_64平台上, 对于Linux-2.6.23版本,Linux的参数传递
通过如下9个寄存器完成,分别为:RDI,RSI,RDX,RCX,RAX,R8,R9,R10,R11。
对于Linux-3.2版本之后,名字改变为 di, si, dx… 这样获得参数的值就为
1
2
3
4
5
| static int pre_probe(struct kprobe *probe, struct pt_regs *regs)
{
printk("first param is %d.\n", regs->di);
return 0;
}
|
Reference:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
#ifdef __i386__
struct pt_regs {
unsigned long bx;
unsigned long cx;
unsigned long dx;
unsigned long si;
unsigned long di;
unsigned long bp;
unsigned long ax;
unsigned long ds;
unsigned long es;
unsigned long fs;
unsigned long gs;
unsigned long orig_ax;
unsigned long ip;
unsigned long cs;
unsigned long flags;
unsigned long sp;
unsigned long ss;
};
#else /* __i386__ */
struct pt_regs {
/*
* C ABI says these regs are callee-preserved. They aren't saved on kernel entry
* unless syscall needs a complete, fully filled "struct pt_regs".
*/
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long bp;
unsigned long bx;
/* These regs are callee-clobbered. Always saved on kernel entry. */
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long ax;
unsigned long cx;
unsigned long dx;
unsigned long si;
unsigned long di;
/*
* On syscall entry, this is syscall#. On CPU exception, this is error code.
* On hw interrupt, it's IRQ number:
*/
unsigned long orig_ax;
/* Return frame for iretq */
unsigned long ip;
unsigned long cs;
unsigned long flags;
unsigned long sp;
unsigned long ss;
/* top of stack page */
};
#endif /* !__i386__ */
|
Author
Hangbin Liu
LastMod
2018-12-13
(1672b97)