Interrupt Requests, Handlers and Keyboards

Low Level:

Interrupts are the means by which hardware devices signal the processor. In the case of a keyboard, this would involve the keyboard controller signalling the processor to let it know there is a new available key press. The processor then notifies the linux kernel. This is called an IRQ or Interrupt request.

It is up to the kernel to run a request handler that associates with each specific interrupt. This handler functionality is part of the device driver for the specified device. The handler functions must run with great efficiency. These quickly move large amounts of data and return to an accepting state. Passing the work into queues and manipulating memory.

Each device driver must register a request handler using the request_irq() function. This registers a given interrupt handler for a given interrupt line. If we run the following

cat /proc/bus/input/devices

This will show our hardware input devices, we can then correlate that what the data returned from running

cat /proc/interrupts

This will show what handlers are currently registered.
Handlers can be unregistered and subsequent lines freed with the free_irq() function.

High Level:

This is where the larger, less time sensitive chunk of our interrupt handling occurs. This manages work that was deferred in queues from the lower level of our interrupt handling process. The 2.6 kernel takes advantage of 3 higher level mechanisms, softirqs, tasklets and work queues.

Softirqs are used for things such as networking and block devices, they are statically added to the kernel at compile time. Tasklets run on top of these softirqs, they are much more dynamic and work fine for the vast majority of cases. Tasklets are managed by a scheduling mechanism. Work queues are an interface for creating kernel threads to handle work queued from elsewhere.

images (1)

How a keyboard works?

This process will be investigated further in the next blog post using systemtap.

  1. Keyboard sends a scancode to our device driver.
  2. Scancode handler in driver converts this into a series of key presses and release events using a translation table.
  3. These key codes and potential modifiers are matched to symbols.
  4. The character symbols are put in a tty queue.
  5. receive_buf() function is called periodically putting the characters into a read queue.
  6. sys_read() is called on stdin of process and returns to process.

 

 Different rootkit key-logging options?

The first option that comes to mind is to build an interrupt handler but as this occurs at a much lower level, it means complete platform dependency. This means it would require a lot more work to implement and even if we did, it’s not guaranteed at all to work on any other devices.

We could also hijack any of the functions above involved in the operation of a keyboard and replace their functionality with some form of logging mechanism.

Our final option is that we could hijack the sys_read() system call and use this to log the keys.

I will look into both function hijacking and system call hijacking  in my next post as a method of implementing our key-logger.

Systemtap installation on CentOS 6.5

This post is simply just a quick note about how to install systemtap on a fresh install of CentOS 6.5. This will also be the development environment and OS I’ll be using for the development of my rootkit. Below you will find a very simple script I wrote to complete this process.

We will need to first acquire the kernel debuginfo packages for our current kernel version. This will allow Systemtap to take full advantage of the the kernel probing system it requires to operate. The debug packages we need to install are kernel-debuginfo, kernel-debuginfo-common and kernel-devel.

We then also need to install systemtap. You can find the script below. You may also find that after you update/upgrade your kernel, the debuginfo packages may need to be installed again. Running this script in these scenarios should also work.

centos-systemtap-debuginfo.sh

#!/bin/bash
WEB="http://debuginfo.centos.org/6/i386/"
RELEASE=`uname -r`
MACHINE=`uname -m`
PKG1="kernel-debuginfo-$RELEASE.rpm"
PKG2="kernel-debuginfo-common-$MACHINE-$RELEASE.rpm"
wget $WEB$PKG1
wget $WEB$PKG2
#Build Downloaded debuginfo packages
rpm -Uhv kernel-debuginfo-*.rpm
#Install systemtap and kernel-developemnt packages
yum install systemtap kernel-devel

After running this, systemtap should be installed and ready to go. I  ran this on a fresh install without any other previous tampering. You can test if it worked by running something such as the following.

stap

stap -L 'kernel.function("*")'

Running this should present a list of kernel functions. In my next post I will be discussing how an IO device such as a keyboard operates, I will also be fully investigating the various components within the kernel using systemtap and how keyboard input is processed. This will preempt the development of my kernel key logger.