Loadable Kernel Module Exploits

Beat potential invaders at their own game by learning how to use cracker tools and improve your own security.
A Final Example

Listing 2 [available at ftp.linuxjournal.com/pub/lj/listings/issue89/4829.tgz] demonstrates a useful module that can help prevent your system from falling victim to stack-smashing attacks. A stack-smashing attack basically consists of writing past the end of a fixed-size buffer, so that the return address of the current function is overwritten, usually with a jump to exec (/bin/sh, ...). Since there really is no reason for programs like httpd, fingerd or wu-ftpd to exec a shell, we shall provide a mechanism to disallow it. By this point, you already have the knowledge to understand most of the code, with one small exception: the strncpy_from_user function. As you might expect, it functions much like its C-library counterpart, strncpy, and is a handy way to get a null-terminated string from user space. Since the code is straightforward, we'll briefly discuss the approach, and then I'll leave you to come up with great ideas of your own for improving your system's security.

The implementation in Listing 2 is straightforward. It is not as efficient or robust as one might want, but this code was written in the interest of clarity, and it is easy work to make it better by changing the linear search in wrapped_execve to something more efficient. Essentially, what this module does is overload the kill system call so that if you send signal 42 to a process; it is added to a list of “unsafe” processes, processes that should not be allowed to execute any binary with “sh” in its filename. (42 is one of the real-time signals; you probably aren't using it. If you are, feel free to substitute any number between 32 and 64.) The execve system call then checks to see whether the process is an unsafe one and, if so, checks to see if it is trying to execute a shell. If so, it returns success without doing anything. It is easy to use this module for all of your server processes; simply add this to your init scripts:

kill -42 ...

Listing 2 represents an evolutionary step from Listing 1, but it shows that one can modify the behavior of calls, not just add behavior to the call path. It also does useful work. I hope that you are as excited as I am about the possibilities of writing kernel module exploits to improve your security. This article has given you the basic tools to get started. Fortunately, there is a wealth of documentation available to Linux programmers that will help you write more complex and functional modules; see the Resources section.


William C. Benton (willb@acm.org) is a graduate student at the University of Wisconsin. He is interested in performance monitoring of parallel programs and in language and compiler approaches to security problems.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

LKM Exploits

Anonymous's picture

I currently working on a monitoring tool in a form of LKM, which I want to use to monitor the system calls made and aruguments passed during the calls.

I can access into the system call table and replace system calls but this is only for one system call.

Any idea how to capture parameters passed and monitor the system calls made by applications?

When security is really

elf's picture

When security is really important, kernel modules should be disabled and kernel compiled static. Otherwise, once someone gets root access, it will be easy to takeover the kernel space area and hide all kind of intrusion evidences.

Re: Kernel Korner: Loadable Kernel Module Exploits

Anonymous's picture

When I try to insmod the module : "Listing 1. Checking and Logging Function ", i get the error : unresolved symbol sys_call_table, though the compilation gives no warning.

(kernel 2.4-18, red hat)

why ?

Re: Kernel Korner: Loadable Kernel Module Exploits

Anonymous's picture

sys_call_table is no longer supported, as it is dangerous to replace system calls . If you want to add explicitly, add the following to kyms.c and recompile the kernel.

Get address of un-EXPORT kernel symbol from /boot/System.map

Biswajit Paul's picture

sys_call_table is no longer EXPORT_ed by kernel(=>2.4.20) may be due to security reason.
# more /proc/ksyms|egrep sys_call_table : Shows nothing.

But i guess for that you do not required to EXPORT the symbol in kyms.c and recompile the kernel.Here is a nobel trick that can come handy.

All the kernel symbols( irrespective of whether it is EXPORT_ed or not) are saved along with their address in /boot/System.map during the kernel compilation for the purpose of future debugging.This file comes handy in the situation where symbols are not exported !!!

# more /boot/System.map|egrep sys_call_table : Display the address of sys_call_table.

Use that address in your code instead of defining sys_call_table as external symbol and ask the insmod to resolve it during the module insersion.


yudi dudulz's picture

Firstly i want to appologies. I have read your paper. I have try your command. But there is still some unresolve symbol. I have make external symbol there is nr_free_pages and buffermem_pages.
when i finish make external symbol. I try to remake modul but there still unresove.

extern int nr_free_pages(void) in the source code
then remake. Then insmod -f ip.o