First LKM
Posted on Sat 10 May 2014 in Linux Kernel Hacking
A loadable kernel module (LKM) is the easiest way to create a rootkit, although it is also the most noisy and easiest to defend against. Once root (or system level privileges) is gained on a machine, a rootkit is the best way to maintain root access to that machine.
Here I will try to explain the basics of what a LKM actually is and how to create and test a very basic one for Linux.
An LKM is a plugin to the kernel. It allows you to run code with the same permissions as the kernel, which isn't possible for normal userland applications. Device drivers are LKM's as they need permission to access the computers hardware, so either with or without knowing it, you already have some experience with LKM's. Throughout this post I will be using LKM and module interchangeably.
Creating A Hello World LKM
Here is the code for the LKM that we will be creating:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Lines 4 and 5 and just some information about the module. Line 6 is needed otherwise when we load the module we get the following error message in the systems log:
hello: module license 'unspecified' taints kernel.
The module will still load but as we are learning to write a rootkit, we want as little 'noise' as possible.
The function hello_init
on lines 8 - 12 runs when the module is loaded, here we are just printing "Hello World!\n" to the system log. The function hello_exit
on lines 14 - 18 runs when the module is unloaded, here we are just printing "Unloading hello.\n" to the system log. They are defined as such on lines 20 and 21.
Compiling The LKM
To compile it we need a Makefile
, the makefile below will do:
1 2 3 4 5 6 7 |
|
With both of these files in the same directory we can now compile our first LKM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
As we can see, the make
command has created a number of files (hello.ko
, hello.mod.c
, hello.mod.o
, hello.o
, modules.order
, Module.symvers
). The file we are interested in is hello.ko
on line 13, this is our module.
Loading/Unloading The LVM
I am using a 32 bit Debian based Linux system (Kali) for my development environment but this should work on any modern Linux system (Do not try this on a production machine! Working with the kernel always has the possiblity to crash the kernel and bring the whole system down! You have been warned!), older systems might require some changes.
Here is how we load and unload the module; and check that everything has worked:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
So first I have shown you the Linux kernel version I am using with the uname
command on line 1, this is just so if it doesn't work for you, you can check if they are the same version. The insmod
command is used to load the module on line 3 and we check the system log to make sure it has printed the string "Hello World!\n" using the dmesg
command on line 4. The lsmod
command is used on line 6 to check if the module is actually loaded. The rmmod
command is used on line 8 to unload the module and the system log is checked again on line 9 to check that our printk has run correctly. Lastly we check with lsmod
again to make sure the module has been unloaded correctly.
So we have a working LKM.
Conclusion
It is very easy to make mistakes with any programming but the majority of mistakes in a normal application will not bring a system down. While its always important to build and test code in a development environment, its even more important when coding an application that runs in kernelland as any tiny mistake can, and most likely will, bring the system down.
Happy Hacking :-)