/* * syscall.c * * System call "stealing" sample. * * Disables page protection at a processor level by * changing the 16th bit in the cr0 register (could be Intel specific) * * Based on example by Peter Jay Salzman and * https://bbs.archlinux.org/viewtopic.php?id=139406 */ #include #include #include #include /* which will have params */ #include #include /* The list of system calls */ /* * For the current (process) structure, we need * this to know who the current user is. */ #include #include unsigned long **sys_call_table; unsigned long original_cr0; /* * UID we want to spy on - will be filled from the * command line */ static int uid; module_param(uid, int, 0644); /* * A pointer to the original system call. The reason * we keep this, rather than call the original function * (sys_open), is because somebody else might have * replaced the system call before us. Note that this * is not 100% safe, because if another module * replaced sys_open before us, then when we're inserted * we'll call the function in that module - and it * might be removed before we are. * * Another reason for this is that we can't get sys_open. * It's a static variable, so it is not exported. */ asmlinkage int (*original_call)(const char *, int, int); /* * The function we'll replace sys_open (the function * called when you call the open system call) with. To * find the exact prototype, with the number and type * of arguments, we find the original function first * (it's at fs/open.c). * * In theory, this means that we're tied to the * current version of the kernel. In practice, the * system calls almost never change (it would wreck havoc * and require programs to be recompiled, since the system * calls are the interface between the kernel and the * processes). */ asmlinkage int our_sys_open(const char *filename, int flags, int mode) { int i = 0; char ch; /* * Report the file, if relevant */ pr_info("Opened file by %d: ", uid); do { get_user(ch, filename + i); i++; pr_info("%c", ch); } while (ch != 0); pr_info("\n"); /* * Call the original sys_open - otherwise, we lose * the ability to open files */ return original_call(filename, flags, mode); } static unsigned long **aquire_sys_call_table(void) { unsigned long int offset = PAGE_OFFSET; unsigned long **sct; while (offset < ULLONG_MAX) { sct = (unsigned long **) offset; if (sct[__NR_close] == (unsigned long *) ksys_close) return sct; offset += sizeof(void *); } return NULL; } static int __init syscall_start(void) { if (!(sys_call_table = aquire_sys_call_table())) return -1; original_cr0 = read_cr0(); write_cr0(original_cr0 & ~0x00010000); /* keep track of the original open function */ original_call = (void *) sys_call_table[__NR_open]; /* use our open function instead */ sys_call_table[__NR_open] = (unsigned long *) our_sys_open; write_cr0(original_cr0); pr_info("Spying on UID:%d\n", uid); return 0; } static void __exit syscall_end(void) { if (!sys_call_table) { return; } /* * Return the system call back to normal */ if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) { pr_alert("Somebody else also played with the "); pr_alert("open system call\n"); pr_alert("The system may be left in "); pr_alert("an unstable state.\n"); } write_cr0(original_cr0 & ~0x00010000); sys_call_table[__NR_open] = (unsigned long *) original_call; write_cr0(original_cr0); msleep(2000); } module_init(syscall_start); module_exit(syscall_end); MODULE_LICENSE("GPL");