Reading Kernel Memory Using a Module

Reading kernel memory using a module

Let me first start by saying reading arbitrary kernel memory is tricky business! And there are many ways to do it, which vary in their degree of complexity and flexability.

1) Hard-code the address.

Search for it in your kernel version's System.map file:

# grep sys_call_table /boot/System.map-2.6.18-238.12.1.el5
c06254e0 R sys_call_table

With this, hard-code the address:

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

Then, assuming you #include <linux/syscalls.h>, you can use the __NR_syscall definitions to grab the addresses of those syscalls within the code:

syscall_table[__NR_close]

This is the easiest method, but by far the least flexible. This module will only work on that exact kernel. If you insmod it into a different kernel, you're liable to get a kernel OOPs.

2) Brute-force scan for the table

Have a look at this:

http://memset.wordpress.com/2011/03/18/syscall-hijacking-dynamically-obtain-syscall-table-address-kernel-2-6-x-2/

He uses a method to brute force the kernel memory address range to find the sys_call_stable. As-is, it only works on 32bit (64bit has a different memory address range for the kernel).

This method is somewhat flexible, but may break down the road as the kernel semantics change.

3) Dynamically search System.map load time

You can read your kernel's System.map file when you load the module. I demonstrate this in the tpe-lkm module I wrote. The project is hosted on github.

Have a look at the find_symbol_address_from_file() from this file:

https://github.com/cormander/tpe-lkm/blob/master/symbols.c

Very flexible, as you can find any symbol you want, but reading files from kernel space is a big 'no no'. Don't ask me why, but people are always telling me that. You also run the risk that the System.map it looks at is invalid, and could cause a kernel OOPs. Also, the code is... messy.

4) Use kallsyms_on_each_symbol()

As of around kernel version 2.6.30, the kernel exports kallsyms_on_each_symbol(). We can thank the ksplice folks for that. With this you can't find the sys_call_table (it isn't in there for some reason), but you can find most other symbols.

Very flexible, very stable method of finding addresses of symbols, but somewhat complicated to understand ;)

I demonstrate this in my tpe-lkm project. Have a look at the find_symbol_callback() and find_symbol_address() function in this file:

https://github.com/cormander/tpe-lkm/blob/master/symbols.c

Linux kernel module - accessing memory mapping

From the module's code THIS_MODULE macro is actually a pointer to the struct module object. Its module_init and module_core fields point to memory regions, where all module sections are loaded.

As I understand, sections division is inaccessible from the module code(struct load_info is dropped after module is loaded into memory). But having module's file you can easily deduce section's addresses after load:

module_init:
- init sections with code (.init.text)
- init sections with readonly data
- init sections with writable data

module_core:
- sections with code (.text)
- sections with readonly data
- sections with writable data

If several sections suit to one category, they are placed in the same order, as in the module's file.

Within module's code you can also print address of any its symbol, and after calculate start of the section, contained this symbol.



Related Topics



Leave a reply



Submit