Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a17514c

Browse files
Create Ftrace syscall hooking example
1 parent 9c25e59 commit a17514c

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

‎examples/Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ obj-m += kbleds.o
1717
obj-m += sched.o
1818
obj-m += chardev2.o
1919
obj-m += syscall.o
20+
obj-m += syscall-ftrace.o
2021
obj-m += intrpt.o
2122
obj-m += cryptosha256.o
2223
obj-m += cryptosk.o

‎examples/syscall-ftrace.c‎

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* syscall-ftrace.c
3+
*
4+
* System call "stealing" with Ftrace
5+
*/
6+
7+
#include <linux/kernel.h>
8+
#include <linux/init.h>
9+
#include <linux/module.h>
10+
#include <linux/moduleparam.h>
11+
#include <linux/version.h>
12+
#include <linux/unistd.h>
13+
#include <linux/kprobes.h>
14+
#include <linux/sched.h>
15+
#include <linux/uaccess.h>
16+
#include <linux/slab.h>
17+
/** This is what we're using here. */
18+
#include <linux/ftrace.h>
19+
20+
MODULE_LICENSE("GPL");
21+
22+
#define MAX_FILENAME_SIZE 200
23+
24+
/* UID we want to spy on - will be filled from the command line. */
25+
static int uid;
26+
module_param(uid, int, 0644);
27+
28+
/**
29+
* This is a helper structure that housekeeps all information
30+
* needed for hooking. Usage with `PREPARE_HOOK` is recommended.
31+
*
32+
* Example:
33+
* static ftrace_hook_t sys_clone_hook = PREPARE_HOOK(__NR_openat, my_sys_clone, &orig_sys_clone)
34+
*/
35+
typedef struct ftrace_hook {
36+
unsigned long nr; // syscall name
37+
void* new; // hook function
38+
void* orig; // original function
39+
40+
unsigned long address; // address to the original function
41+
struct ftrace_ops ops; // ftrace structure
42+
} ftrace_hook_t;
43+
44+
#define PREPARE_HOOK(_nr, _hook, _orig) { \
45+
.nr = (_nr), \
46+
.new = (_hook), \
47+
.orig = (_orig) \
48+
}
49+
50+
unsigned long **sys_call_table;
51+
52+
/**
53+
* For the sake of simplicity, only the kprobe method is included.
54+
* If you want to know more about different methods to get
55+
* kallsyms_lookup_name, see syscall.c.
56+
*/
57+
static int resolve_address(ftrace_hook_t *hook)
58+
{
59+
static struct kprobe kp = {
60+
.symbol_name = "kallsyms_lookup_name"
61+
};
62+
unsigned long (*kallsyms_lookup_name)(const char *name);
63+
register_kprobe(&kp);
64+
kallsyms_lookup_name = (unsigned long (*)(const char *))kp.addr;
65+
unregister_kprobe(&kp);
66+
67+
if (kallsyms_lookup_name) pr_info("[syscall-ftrace] kallsyms_lookup_name is found at 0x%lx\n", (unsigned long)kallsyms_lookup_name);
68+
else {
69+
pr_err("[syscall-ftrace] kallsyms_lookup_name is not found!\n");
70+
return -1;
71+
}
72+
73+
sys_call_table = (unsigned long **)kallsyms_lookup_name("sys_call_table");
74+
if (sys_call_table) pr_info("[syscall-ftrace] sys_call_table is found at 0x%lx\n", (unsigned long)sys_call_table);
75+
else {
76+
pr_err("[syscall-ftrace] sys_call_table is not found!\n");
77+
return -1;
78+
}
79+
80+
hook->address = (unsigned long)sys_call_table[hook->nr];
81+
*((unsigned long*) hook->orig) = hook->address;
82+
return 0;
83+
}
84+
85+
/**
86+
* This is where the magic happens.
87+
*
88+
*/
89+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
90+
static void notrace ftrace_thunk(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct ftrace_regs *fregs)
91+
{
92+
ftrace_hook_t *hook = container_of(ops, ftrace_hook_t, ops);
93+
if (!within_module(parent_ip, THIS_MODULE)) fregs->regs.ip = (unsigned long) hook->new;
94+
}
95+
96+
#else
97+
static void notrace ftrace_thunk(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct pt_regs *regs)
98+
{
99+
ftrace_hook_t *hook = container_of(ops, ftrace_hook_t, ops);
100+
if (!within_module(parent_ip, THIS_MODULE)) regs->ip = (unsigned long) hook->new;
101+
}
102+
103+
#endif /** Version >= v5.11 */
104+
105+
int install_hook(ftrace_hook_t *hook)
106+
{
107+
int err;
108+
err = resolve_address(hook);
109+
if (err) return err;
110+
111+
hook->ops.func = ftrace_thunk;
112+
hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY;
113+
err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0);
114+
if (err) {
115+
pr_err("[syscall-ftrace] ftrace_set_filter_ip() failed: %d\n", err);
116+
return err;
117+
}
118+
119+
err = register_ftrace_function(&hook->ops);
120+
if (err) {
121+
pr_err("[syscall-ftrace] register_ftrace_function() failed: %d\n", err);
122+
return err;
123+
}
124+
125+
return 0;
126+
}
127+
128+
void remove_hook(ftrace_hook_t *hook)
129+
{
130+
int err;
131+
err = unregister_ftrace_function(&hook->ops);
132+
if (err) pr_err("[syscall-ftrace] unregister_ftrace_function() failed: %d\n", err);
133+
134+
err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
135+
if (err) pr_err("[syscall-ftrace] ftrace_set_filter_ip() failed: %d\n", err);
136+
}
137+
138+
/** For some reason the kernel segfaults when the arguments are expanded. */
139+
static asmlinkage long (*original_call)(struct pt_regs *regs);
140+
static asmlinkage long our_sys_openat(struct pt_regs *regs)
141+
{
142+
char *kfilename;
143+
kfilename = kmalloc(GFP_KERNEL, 200*sizeof(char));
144+
if (!kfilename) return original_call(regs);
145+
146+
if (copy_from_user(kfilename, (char __user *)regs->si, MAX_FILENAME_SIZE) < 0) {
147+
kfree(kfilename);
148+
return original_call(regs);
149+
}
150+
151+
pr_info("[syscall-ftrace] File opened by UID %d: %s\n", uid, kfilename);
152+
kfree(kfilename);
153+
154+
return original_call(regs);
155+
}
156+
157+
static ftrace_hook_t sys_openat_hook = PREPARE_HOOK(__NR_openat, our_sys_openat, &original_call);
158+
159+
static int __init syscall_ftrace_start(void) {
160+
int err;
161+
err = install_hook(&sys_openat_hook);
162+
if (err) return err;
163+
pr_info("[syscall-ftrace] hooked, spying on uid %d\n", uid);
164+
return 0;
165+
}
166+
167+
static void __exit syscall_ftrace_end(void) {
168+
remove_hook(&sys_openat_hook);
169+
pr_info("[syscall-ftrace] removed\n");
170+
}
171+
172+
module_init(syscall_ftrace_start);
173+
module_exit(syscall_ftrace_end);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /