-
Notifications
You must be signed in to change notification settings - Fork 577
Add system call "stealing" sample using kprobe handler #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,14 @@ | |
|
||
#if defined(CONFIG_KPROBES) | ||
#define HAVE_KPROBES 1 | ||
#if defined(CONFIG_X86_64) | ||
/* If you have tried to use the syscall table to intercept syscalls and it | ||
* doesn't work, you can try to use Kprobes to intercept syscalls. | ||
* Set USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL to 1 to register a pre-handler | ||
* before the syscall. | ||
*/ | ||
#define USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL 0 | ||
#endif | ||
#include <linux/kprobes.h> | ||
#else | ||
#define HAVE_PARAM 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, we need to add the other condition, the system is v5.9+ and x86 arch without kprobe support. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe defining USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL to 0 by default is enough because users may turn on this macro if they get stuck when hacking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the module will be broken if we have such a scenario. |
||
|
@@ -58,12 +66,37 @@ module_param(sym, ulong, 0644); | |
|
||
#endif /* Version < v5.7 */ | ||
|
||
static unsigned long **sys_call_table_stolen; | ||
|
||
/* UID we want to spy on - will be filled from the command line. */ | ||
static uid_t uid = -1; | ||
module_param(uid, int, 0644); | ||
|
||
#if USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL | ||
|
||
/* syscall_sym is the symbol name of the syscall to spy on. The default is | ||
* "__x64_sys_openat", which can be changed by the module parameter. You can | ||
* look up the symbol name of a syscall in /proc/kallsyms. | ||
*/ | ||
static char *syscall_sym = "__x64_sys_openat"; | ||
module_param(syscall_sym, charp, 0644); | ||
|
||
static int sys_call_kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs) | ||
{ | ||
if (__kuid_val(current_uid()) != uid) { | ||
return 0; | ||
} | ||
|
||
pr_info("%s called by %d\n", syscall_sym, uid); | ||
return 0; | ||
} | ||
|
||
static struct kprobe syscall_kprobe = { | ||
.symbol_name = "__x64_sys_openat", | ||
.pre_handler = sys_call_kprobe_pre_handler, | ||
}; | ||
#else | ||
|
||
static unsigned long **sys_call_table_stolen; | ||
|
||
/* A pointer to the original system call. The reason we keep this, rather | ||
* than call the original function (sys_openat), is because somebody else | ||
* might have replaced the system call before us. Note that this is not | ||
|
@@ -202,9 +235,23 @@ static void disable_write_protection(void) | |
clear_bit(16, &cr0); | ||
__write_cr0(cr0); | ||
} | ||
#endif | ||
|
||
static int __init syscall_steal_start(void) | ||
{ | ||
#if USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL | ||
|
||
int err; | ||
/* use symbol name from the module parameter */ | ||
syscall_kprobe.symbol_name = syscall_sym; | ||
err = register_kprobe(&syscall_kprobe); | ||
if (err) { | ||
pr_err("register_kprobe() on %s failed: %d\n", syscall_sym, err); | ||
pr_err("Please check the symbol name from 'syscall_sym' parameter.\n"); | ||
return err; | ||
} | ||
|
||
#else | ||
if (!(sys_call_table_stolen = acquire_sys_call_table())) | ||
return -1; | ||
|
||
|
@@ -218,13 +265,17 @@ static int __init syscall_steal_start(void) | |
|
||
enable_write_protection(); | ||
|
||
pr_info("Spying on UID:%d\n", uid); | ||
#endif | ||
|
||
pr_info("Spying on UID:%d\n", uid); | ||
return 0; | ||
} | ||
|
||
static void __exit syscall_steal_end(void) | ||
{ | ||
#if USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL | ||
unregister_kprobe(&syscall_kprobe); | ||
#else | ||
if (!sys_call_table_stolen) | ||
return; | ||
|
||
|
@@ -239,6 +290,7 @@ static void __exit syscall_steal_end(void) | |
disable_write_protection(); | ||
sys_call_table_stolen[__NR_openat] = (unsigned long *)original_call; | ||
enable_write_protection(); | ||
#endif | ||
|
||
msleep(2000); | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.