http://kerneltrap.org/node/17083

http://www.l0t3k.org/biblio/kernel/english/kernel-hijack.txt

hijacking of network subsystem function

April 19, 2009 - 5:00am
Submitted by nagliyvred on April 19, 2009 - 5:00am.
Linux

Hi all, guys!
I'm now writing my thesis to degree at the university. My work is about the covert (or
subliminal) channels in network protocols. The practice part of my
work is to implement such channels and suggest the security mechanism.
I'm a Linux fan and developing it under 2.6.27 kernel.
The problem occured when I tried to use the mechanism of function
hijacking suggested by SilvioCesare
http://www.l0t3k.org/biblio/kernel/english/kernel-hijack.txt
to inject the covert function in the kernel.
I'm trying to hijack the kernel function called
ip_finish_output(struct sk_buff*). It is hijacked ok, but when I
trying to call the original one something strange happens: system is
falling with Oops after calling the original function. I tried to
avoid calling this function and place it's code in the interceptor,
but is it falling too. This is stumping me - as I can see this
mechanism is quite simple and efficient, but when I hijack the needed function it does not work. Can this be because of using
struct sk_buff? Or maybe passing it as a parameter ? Or this hijacking mechanism broke passing the sk_buff as a parameter? Or this is because of some tricky config option in the kernel?

In the attach you can find the sample code, that is not working for me
(be careful - it is making a panic if you'll send some packets, ping
f.e),

Attachment Size
call_stack.png 49.16 KB
hijack_test.c.txt 2.78 KB
Makefile.txt 440 bytes


#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef LINUX
#define LINUX
#endif
#ifndef KERNEL
#define KERNEL
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/types.h>
#include <linux/smp_lock.h>
#include <net/ip_fib.h>
#include <linux/inetdevice.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <net/ip.h>

#define CODESIZE 10 
static char original_code[CODESIZE];
static char jump_code[CODESIZE] =
       "\xb8\x00\x00\x00\x00"      /*      movl   $0,%eax  */
       "\x40"			   /*	   inc	  %eax	   */
       "\x90"			   /*	   nop	           */
       "\x48"			   /*	   dec	  %eax	   */
       "\xff\xe0"                  /*      jmp    *%eax    */
	       	;

//  spinlock
static spinlock_t hijack_lock = SPIN_LOCK_UNLOCKED;

#define HIJACK_LOCK 	spin_lock_irqsave(&hijack_lock, sl_flags)
#define HIJACK_UNLOCK	spin_unlock_irqrestore(&hijack_lock, sl_flags)

// function to intercept 
static int (*addr) (struct sk_buff * skb);

// interceptor function
static int interceptor(struct sk_buff *skb);


void *_memcpy(void *dest, const void *src, int size)
{
	const char *p = src;
	char *q = dest;
	int i;
        for (i = 0; i < size; i++) 
		*q++ = *p++;

	return dest;
}


//
//  set interceptor
//
unsigned int mk_interceptor(void)
{
	int sl_flags;
	printk("setting interceptors...");
	printk(KERN_INFO" page offset (%08x), addr=(%08x)\n", (unsigned int) PAGE_OFFSET, (unsigned int)addr);
    if ((unsigned int) addr == 0 || (unsigned int) addr < PAGE_OFFSET)
    {
	    printk("address for function is not valid (%08x)\n", (unsigned int)addr);
		return -EINVAL;
	}
	

	*(long *)&jump_code[1] = (long)interceptor;
	
    HIJACK_LOCK;
	_memcpy(original_code, addr, CODESIZE);
	_memcpy(addr, jump_code, CODESIZE);
	HIJACK_UNLOCK;

    return 0;
}

//
//  remove interceptor
//
void rm_interceptor(void)
{
	printk("removing interceptors...");
	
    lock_kernel();

	_memcpy(addr, original_code, CODESIZE);

	unlock_kernel();
	printk("OK\n");
}

//
//  entry point
//
int __init startup_module(void)
{
	int ret = 0;
	printk("loading  module...");	
	
    ret = mk_interceptor();
    if (ret) goto init_error;

	printk("OK\n");
	return 0;

 init_error:

	printk("FAILED, ret= %d\n", ret);
    return ret;
}

void exit_module(void)
{
	printk("unloading cc_sender module...");
	rm_interceptor();
	printk("OK\n");
}

int interceptor(struct sk_buff * skb)
{
	int ret = 0;
	int sl_flags;
	printk("interceptor\n");

   	HIJACK_LOCK;
	_memcpy(addr, original_code, CODESIZE);
        
    ret = addr(skb);
    _memcpy(addr, jump_code, CODESIZE);
	HIJACK_UNLOCK;
	return ret;
}



module_init(startup_module);
module_exit(exit_module);
module_param(addr, long, 0);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eugeny Dudin");



MODULE_DESCRIPTION("covert channel sender");

	obj-m:=hijack_test.o

FUNC_ADDRESS=0x$(word 1,$(shell grep ' ip_finish_output' /proc/kallsyms | awk '{print $1}'))
EXTRA_CFLAGS=-DFUNC_ADDRESS=$(FUNC_ADDRESS)
KDIR=/lib/modules/$(shell uname -r)/build
PWD=$(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
install:
	/sbin/insmod hijack_test.ko addr=$(FUNC_ADDRESS)
	@echo module inserted OK
uninstall:
	/sbin/rmmod hijack_test
clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

Reply via email to