Created
February 14, 2018 09:50
-
-
Save AVGP/ef65a5c8db0d36124e701cb9ed954f8a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/init.h> | |
#include <linux/kernel.h> | |
#include <linux/unistd.h> | |
#include <linux/utsname.h> | |
#define MEM_READONLY 0x10000 // bit 16 in cr0 specifies if "readonly" memory is protected | |
// we define a type for the original uname syscall handler function | |
typedef asmlinkage long (*orig_uname_t)(struct new_utsname *); | |
// TODO: Find this dynamically, either via IDT or via /boot/System.map | |
// we keep a pointer to the beginning of the sys_call_table | |
unsigned long *sys_call_tbl = (unsigned long *)0xffffffff81801300; // WAIT, these seem to be stable for the same kernel version across hosts :O | |
// here we'll store the address of the original "uname" handler | |
orig_uname_t orig_uname = NULL; | |
// | |
asmlinkage long my_uname(struct new_utsname *name) { | |
orig_uname(name); // we call the original function to get the structure filled out by the real syscall | |
strncpy(name->sysname, "YOLO", 5); // now we overwrite the "sysname" field (the first part of what "uname" outputs). 5 bytes because of the trailing \0. | |
return 0; | |
} | |
int init(void) { | |
printk("Yolo Swaggings loaded.\n"); | |
// the following two lines hide the module from /proc/modules (and thus from lsmod, modinfo, rmmod, etc.) and /sys/module/ | |
//list_del_init(&__this_module.list); | |
//kobject_del(&THIS_MODULE->mkobj.kobj); | |
// disable write protection in the memory via the cr0 register on the CPU by removing the "read-only" bit | |
write_cr0(read_cr0() & (~ MEM_READONLY)); | |
// look at the position of the "uname" syscall in our table and save the address it points to (i.e. the original uname handler) | |
orig_uname = (orig_uname_t)sys_call_tbl[__NR_uname]; | |
// now we put the address of our own handler (my_uname) into the table | |
sys_call_tbl[__NR_uname] = &my_uname; | |
printk("Original uname at %08x -- new one at %08x\n", orig_uname, &my_uname); | |
// enable write protection by putting the "read-only" bit back | |
write_cr0(read_cr0() | MEM_READONLY); | |
return 0; | |
} | |
void unload(void) { | |
// disable write protection | |
write_cr0(read_cr0() & (~MEM_READONLY)); | |
// put the original handler back | |
sys_call_tbl[__NR_uname] = orig_uname; | |
// enable write protection | |
write_cr0(read_cr0() | MEM_READONLY); | |
printk("Yolo Swaggings has left the building.\n"); | |
} | |
// Declare this as a module, licensed under GPL, run "init" when loaded, run "unload" when removed | |
MODULE_LICENSE("GPL"); | |
module_init(init); | |
module_exit(unload); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment