From b61bf36c555c7d51a854fe7986a8c192c3a624ba Mon Sep 17 00:00:00 2001 From: Andriy Petrov Date: Thu, 25 Apr 2024 21:51:18 +0200 Subject: [PATCH] source --- Makefile | 9 +++ README.md | 35 +++++++++- sumo.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ whoami.sh | 6 ++ 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 Makefile create mode 100644 sumo.c create mode 100755 whoami.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..761ad7b --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +# FIX: module verification failed: signature and/or required key missing - tainting kernel +CONFIG_MODULE_SIG=n + +obj-m += sumo.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/README.md b/README.md index c84a8c8..97cb70d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ -# sumo +Sumo is a Linux Kernel module that grants root access credentials to any user-space process by PID. -Sumo is a Linux Kernel module that grants root access credentials to any user-space process by PID. \ No newline at end of file +# TL;DR + +*.bashrc* +```bash +make # build +sudo insmod sumo.ko # install +./whoami # test +``` + +# How it works + +In it's `init()` function, *sumo* kernel module creates `/proc/sumo` file and waits for PID to be written. Afterwards, it fetches instance of a `task_struct` [kernel structure](https://medium.com/@boutnaru/linux-kernel-task-struct-829f51d97275) associated with the given PID and modifies its values accordingly. + +```text +sumo __ SUdo + ,;.'--'. MOdule + /"/=,=( + \( __/ + ___/ (____ + .' - - '. + / v \ + __/ , | \ '-/'_ +{z, ,__/__,__/\__,_ )__( z} + \>' ( \_ `--c/ + _.-'\_ , / \_ + ( `.______.' '. + \ , \ ( __ ) + \ )-'-\__/-' | / + | | / .' + / ,) ( \_ + oooO' '--Ooo +``` diff --git a/sumo.c b/sumo.c new file mode 100644 index 0000000..e75a29a --- /dev/null +++ b/sumo.c @@ -0,0 +1,194 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#define SUMO \ +R"(sumo: __ SUdo )""\n"\ +R"( ,;.'--'. MOdule )""\n"\ +R"( /'/=,=( )""\n"\ +R"( \( __/ )""\n"\ +R"( ___/ (____ )""\n"\ +R"( .' - - '. )""\n"\ +R"( / v \ )""\n"\ +R"( __/ , | \ '-/'_ )""\n"\ +R"( {z, ,__/__,__/\__,_ )__( z} )""\n"\ +R"( \>' ( \_ `--c/ )""\n"\ +R"( _.-'\_ , / \_ )""\n"\ +R"( ( `.______.' '. )""\n"\ +R"( \ , \ ( __ ) )""\n"\ +R"( \ )-'-\__/-' | / )""\n"\ +R"( | | / .' )""\n"\ +R"( / ,) ( \_ )""\n"\ +R"( oooO' '--Ooo )""\n" + +#define MTAG "sumo: " + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("djmil"); +MODULE_DESCRIPTION("Grant root access right to the process by PID"); +//MODULE_INFO(intree, "Y"); + +/////////////////////////////////////////////////////////////////////////////// + +void set_task_uids_gids_to_zero(struct task_struct *task) +{ + struct cred *_cred; + //struct real_cred *_real_cred; + + // Safely access cred and real_cred using rcu_dereference + _cred = (struct cred *)rcu_dereference(task->cred); + //_real_cred = (struct cred *)rcu_dereference(task->real_cred); + if (_cred == NULL) { + pr_err(MTAG "Task creds are null %d\n", task->pid); + return; + } + + // Update UIDs to zero + _cred->uid.val = 0; + _cred->euid.val = 0; + _cred->fsuid.val = 0; + + // Update GIDs to zero + _cred->gid.val = 0; + _cred->egid.val = 0; + _cred->fsgid.val = 0; + + pr_debug(MTAG "PID %d: all UIDs and GIDs set to zero\n", task->pid); +} + +void change_process_capabilities(struct task_struct *task) +{ + struct cred *_cred; + + // Acquire a new set of credentials + _cred = (struct cred *)rcu_dereference(task->cred); + + // Add ptrace+other capabilities + _cred->cap_inheritable.cap[0] = 0xffffffff; + _cred->cap_inheritable.cap[1] = 0xffffffff; + + _cred->cap_permitted.cap[0] = 0xffffffff; + _cred->cap_permitted.cap[1] = 0xffffffff; + + _cred->cap_effective.cap[0] = 0xffffffff; + _cred->cap_effective.cap[1] = 0xffffffff; + + _cred->cap_bset.cap[0] = 0xffffffff; + _cred->cap_bset.cap[1] = 0xffffffff; + + _cred->cap_ambient.cap[0] = 0xffffffff; + _cred->cap_ambient.cap[1] = 0xffffffff; + + pr_debug(MTAG "PID %d: capabilities changed\n", task->pid); +} + +ssize_t proc_pid_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + unsigned long long pid; + struct pid *pid_struct = 0; + struct task_struct *task; + int ret = 0; + + // Read the target PID from the user buffer + if (count < 0) { + pr_err(MTAG "read failed. size %lu\n", count); + return -1; + } + + *ppos = count; + + ret = kstrtoull_from_user(buffer, count, 10, &pid); + if (ret) { + pr_err(MTAG "read PID failed %d\n", ret); + return count; + } + + pr_info(MTAG "Got PID %llu\n", pid); + *ppos = count; + + pid_struct = find_get_pid(pid); + if (pid_struct == NULL) { + pr_err(MTAG "find_get_pid() failed\n"); + return count; + } + + // Find the task_struct corresponding to the given PID + task = pid_task(pid_struct, PIDTYPE_PID); + + if (task == NULL) { + pr_err(MTAG "Could not find process with PID %llu\n", pid); + return count; + } + + if (task->cred == NULL /*|| task->real_cred*/) { + pr_err(MTAG "task->cred == NULL\n"); + return count; + } + + { + rcu_read_lock(); + + set_task_uids_gids_to_zero(task); + change_process_capabilities(task); + + rcu_read_unlock(); + } + + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + + static struct proc_ops proc_fops = { + //.proc_read = porc_pid_read, + .proc_write = proc_pid_write, + }; + +#else + + static struct file_operations proc_fops = { + .owner = THIS_MODULE, + //.read = proc_pid_read, + .write = proc_pid_write, + }; + +#endif + +static struct proc_dir_entry *ent = NULL; + + +int sumo_init(void) +{ + pr_info(SUMO); + + // Create `/proc/sumo` file + ent = proc_create("sumo", 0666, NULL, &proc_fops); + if (ent) + pr_info(MTAG "Created /proc/sumo\n"); + else + pr_err(MTAG "Unable to created /proc/sumo\n"); + + return 0; +} + +void sumo_exit(void) +{ + if (ent) + proc_remove(ent); +} + + +module_init(sumo_init); +module_exit(sumo_exit); diff --git a/whoami.sh b/whoami.sh new file mode 100755 index 0000000..23c1109 --- /dev/null +++ b/whoami.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euxo pipefail + +echo $$ > /proc/sumo # $$ shows PID of the (self) process +whoami +