Watch this space

Kernel Programming

Kernel Symbol Table

Intercepting Open System call

With 2.6 Kernel SYS_CALL_TABLE symbol is not exported. There are a few hacks to play with sys_call_table. This is one of the simple method to override the sys_call_table. I have implemented this as a kernel module to have my own implementation of OPEN system call. ( This code is tested on ubuntu 8.04 with 2.6.24-16-generic kernel).

System.map-2.6.24-16-generic is a file which will tell as to where the sys_call_table will be loaded in memory. shrikar@shrikar-desktop:/boot$ grep sys_call System* -i System.map-2.6.24-16-generic:c0320500 R sys_call_table

  • System.map-2.6.24-16-generic is a file which will tell as to where the sys_call_table will be loaded in memory.
    shrikar@shrikar-desktop:/boot$ grep sys_call System* -i
    System.map-2.6.24-16-generic:c0320500 R sys_call_table
    Now with this command we can tell that the table is located at address starting from c0320500.
  • __NR_open is the index into the syscall table which point to open system call. So a simple logic like this should work fine.

    unsigned long *sys_call_table;
    myval = simple_strtoul( "0xC0320500", NULL, 16 );
    sys_call_table = (unsigned long *)myval;

    /*
    * Keep a pointer to the original function in
    * original_call, and then replace the system call
    * in the system call table with our_sys_open
    */
    original_call = sys_call_table[__NR_open];
    sys_call_table[__NR_open] = our_sys_open;
Bingo!!! We have our own implementation of Open system call
FYI: The chances of getting kernel panic is more if things are not done properly. Please use this method at your own risk.
Source

Linux Kernel Modules

1. What are LKMs

LKMs are Loadable Kernel Modules used by the Linux kernel to expand his functionality. The advantage of those LKMs : The can be loaded dynamically; there must be no recompilation of the whole kernel. Because of those features they are often used for specific device drivers (or filesystems) such as soundcards etc.
Every LKM consist of two basic functions (minimum) :  
#define __KERNEL__         /* We're part of the kernel */
#define MODULE /* Not a permanent part, though. */

/* Standard headers for LKMs */
#include <linux/modversions.h>
#include <linux/module.h>

#include <linux/tty.h> /* console_print() interface */

/* Initialize the LKM */
int init_module()
{
printk("Hello, world - this is the kernel speaking\n");
/* If we return a non zero value, it means that
* init_module failed and the LKM can't be loaded
*/
return 0;
}
Loading a module - normally retricted to root - is managed by issuing the follwing command: insmod module.o This command forces the System to do the following things :
  • Load the objectfile (here module.o)
  • call create_module systemcall (for systemcalls -> see I.2) for Relocation of memory
  • unresolved references are resolved by Kernel-Symbols with the systemcall get_kernel_syms
  • after this the init_module systemcall is used for the LKM initialisation -> executing int init_module(void) etc.
The Kernel-Symbols are explained in I.3 (Kernel-Symbol-Table).
So I think we can write our first little LKM just showing how it basicly works: You may wonder why I used printk(...) not printf(...). Well Kernel-Programming is totally different from Userspace-Programming !
You only have a very restricted set of commands (see I.6). With those commands you cannot do much, so you will learn how to use lots of functions you know from your userspace applications helping you hacking the kernel. Just be patient, we have to do something else before...
The Example above can easily compiled by gcc -c -O3 helloworld.c<br />insmod helloworld.o Ok, our module is loaded and showed us the famous text. Now you can check some commands showing you that your LKM really stays in kernel space.
lsmod<br />Module Pages Used by<br />helloworld 1 0This command reads the information in /proc/modules for showing you which modules are loaded at the moment. 'Pages' is the memory information (how many pages does this module fill); the 'Used by' field tells us how often the module is used in the System (reference count). The module can only be removed, when this counter is zero; after checking this, you can remove your module with rmmod helloworld Ok, this was our first little (very little) step towards abusing LKMs. I always compared those LKMs to old DOS TSR Programs (yes there are many differences, I know), they were our gate to staying resident in memory and catching every interrupt we wanted. Microsoft's WIN 9x has something called VxD, which is also similar to LKMs (also many differences). The most interesting part of those resident programs is the ability to hook system functions, in the Linux world called systemcalls.

Proc as Programmers tool

What Is /proc?

Before we begin to talk about the proc filesystem as a programming facility, we need need to establish what it actually is. The proc filesystem is a pseudo-filesystem rooted at /proc that contains user-accessible objects that pertain to the runtime state of the kernel and, by extension, the executing processes that run on top of it. "Pseudo" is used because the proc filesystem exists only as a reflection of the in-memory kernel data structures it displays. This is why most files and directories within /proc are 0 bytes in size. Broadly speaking, a directory listing of /proc reveals two main file groups. Each numerically named directory within /proc corresponds to the process ID (PID) of a process currently executing on the system. The following line of ls output illustrates this: shrikar@shrikar-desktop:/proc$ ps -ef|grep bash
shrikar 6087 6084 0 14:26 pts/0 00:00:00 bash
shrikar 6170 6087 0 14:33 pts/0 00:00:00 grep bash
shrikar@shrikar-desktop:/proc$ ls -l 6087
total 0
dr-xr-xr-x 2 shrikar shrikar 0 2009-07-26 14:33 attr
-r-------- 1 shrikar shrikar 0 2009-07-26 14:33 auxv
-r--r--r-- 1 shrikar shrikar 0 2009-07-26 14:33 cgroup
--w------- 1 shrikar shrikar 0 2009-07-26 14:33 clear_refs
-r--r--r-- 1 shrikar shrikar 0 2009-07-26 14:33 cmdline
-rw-r--r-- 1 shrikar shrikar 0 2009-07-26 14:33 coredump_filter
lrwxrwxrwx 1 shrikar shrikar 0 2009-07-26 14:26 cwd -> /proc
-r-------- 1 shrikar shrikar 0 2009-07-26 14:33 environ
lrwxrwxrwx 1 shrikar shrikar 0 2009-07-26 14:33 exe -> /bin/bash

Para 4