Life in a shell

bash$ tiagosh

Hijacking kernel functions

When I was developing RNAT I needed to change one kernel function (ip_options_compile), but I didn’t want the users to recompile their kernels. So then I discovered here that it was possible to hijack a kernel function by using a kernel module, and it solved my problem for that moment.

To exemplify the hijacking process, the code below shows how to hijack sys_mkdir() system call, preventing any user from creating a directory.

Don’t forget to change the old_sys_mkdir pointer to your real sys_mkdir() function.

——————- newmkdir.c —————-

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>

MODULE_LICENSE(“GPL”);

static spinlock_t kern_lock = SPIN_LOCK_UNLOCKED;
unsigned long slock_flags;

#define LOCK_KERN spin_lock_irqsave(&kern_lock, slock_flags)
#define UNLOCK_KERN spin_unlock_irqrestore(&kern_lock, slock_flags)

static unsigned char pr_jump[7]=”\xbf\x00\x00\x00\x00″ /* mov $0,%edi */
“\xff\xe7”; /* jmp *%edi */
static unsigned char pr_save[7];

unsigned char * old_sys_mkdir = (unsigned char *) 0xc01c79d0; /* grep sys_mkdir$ /proc/kallsyms */

/* function prototype from /usr/include/linux/syscalls.h */
asmlinkage long new_sys_mkdir(const char __user *pathname, int mode)
{
printk(“Tried to create: %s, mode: %d\n”, pathname, mode);
/* return Access Denied */
return -EACCES;
}

static int __init new_sys_mkdir_init(void)
{
/* fill pr_jump zero’s with the pointer to our new_sys_mkdir() */
*(long *)&pr_jump[1] = (long)new_sys_mkdir;
LOCK_KERN;

/* replace the inital 7 bytes from the original sys_mkdir() with our jump to  new_sys_mkdir() */
memcpy(pr_save, old_sys_mkdir, 7);
memcpy(old_sys_mkdir, pr_jump, 7);

UNLOCK_KERN;
return 0;
}

static void __exit new_sys_mkdir_exit(void)
{
LOCK_KERN;
/* copy the old initial 7 bytes back */
memcpy(old_sys_mkdir, pr_save, 7);
UNLOCK_KERN;
}

module_init(new_sys_mkdir_init);
module_exit(new_sys_mkdir_exit);

——————– Makefile —————-

obj-m := newmkdir.o

KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Advertisements

October 7, 2007 Posted by | general information, RNAT, xnx | 3 Comments