Intro
Keyloggers are nifty things used to grab keyboard input for later analysis and use.
The most common type of keylogger is the software keylogger as it is just some program that records key presses. Running it usually requires administrator privileges and this limits the attack surface as one must first gain this type of privileges.
Hardware keyloggers on the other hand are just small devices that sit between the keyboard and PC and listen and record all the keystrokes.
This article refers to the KeyDaemon USB, a hardware keylogger produced by the Polish company KeeLog. Official website
The device is pretty small: on one end there’s an USB A plug (this goes to the PC) and on the other end there’s an USB A receptacle (here the keyboard is plugged). The plastic casing contains a microcontroller that listens in to the USB traffic. A 2GB storage module is also embedded in the small casing and is used to store the sniffed key presses.
The default mode is the “record mode” where the device silently records data. When a magic 3-key combination is pressed ( KBS is the default) the keylogger goes into “playback mode” and it makes visible the embedded flash storage. The keyboard is disabled and in place a flash storage device is detected by the operating system. Inside the flash disk there are two important files: log.txt which contains all the key presses captured by the keylogger and config.txt, which contains configuration settings for the device. By editing config.txt one can change the magic key combination (more on this later).
The keylogger is transparent and does not change the USB vendor ID or product ID. One can not tell that the device is plugged in just by looking at the USB device enumeration ( lsusb for example). This makes the detection of the device quite difficult at first sight.
Detection
The initial approach was to see if the current drain on the USB port was higher with the keylogger in place, but this turned out to be too impractical as it’s hard to do an accurate measurement. The OS support for this is also limited and I felt that this was a dead end.
Next I wanted to see how the keylogger handled unexpected flows of commands. The ioctl interface in linux permits changing the leds on the keyboard from user space. This nifty python script makes your keyboard flash the leds like a Las Vegas Casino billboard:
import fcntl
import os
import time
KDSETLED = 0x4B32
SCR_LED = 0x01
NUM_LED = 0x02
CAP_LED = 0x04
console_fd = os.open('/dev/console', os.O_NOCTTY)
all_on = SCR_LED | NUM_LED | CAP_LED
all_off = 0
while 1:
fcntl.ioctl(console_fd, KDSETLED, all_on)
fcntl.ioctl(console_fd, KDSETLED, all_off)
Unfortunately the keylogger had no trouble in handling this type of data.
The next step was to see how the device handles traffic sent from the PC to the keyboard and not the other way around. One would expect that a properly designed keylogger would also take into consideration the direction of the traffic flow. As you will see this is not the case…
The USB keyboard uses the HID protocol to send and receive data to and from the PC. The basic data packet (or report) has 8 bytes. The first byte contains keycodes for the modifier keys (ALT, SHIFT, CTRL), the second byte is reserved for OEM and the remaining 6 bytes are used to send the keycodes for the pressed keys. So one can simultaneous press the modifier keys and 6 other keys.
Using libusb I wrote a very small application that sends the magic 3-key combination out to the keyboard. I didn’t think that this would work as I was expecting a propper design but to my surprise the device flash storage opened like a Christmas present from the first run. One interesting detail is that the keylogger needs to “warm up” since it was first plugged in. Sending the magic key combination immediately after plugging it in does not open the flash storage.
The next logical step was to further extend the app to brute force all the 3-key combinations. If no data can be written to the device then the flash storage has just popped up and a keylogger has been detected.
The device does not take into account the order in which the magic keys are pressed so KBS is also KSB or BKS. Also due to the fact that one can press a key only once a key combination of AAA for example would be invalid. This makes the number of key combinations very small and the brute force takes less than 1 second! While the code needs some polishing and some bugfixes (the USB handle is not cleanly released and this makes the keyboard unusable after execution – it needs to be replugged) it clearly proves that hardware keyloggers can be detected. This is a design flaw it will take a while until it will be fixed.
The PS2 variant of the keylogger has the same flaw and can be detected in the same manner : send all 3 key combinations out the ps2 port and the device will be detected at some point.
My proof-of-concept code uses a small library written by Paul J Stoffregen and Robin Coon of pjrc.com.
Given the fact that this device is so weak (less than 1s to detect) a script or service could be executed at boot time. Maybe companies that write security software could use this to implement a hardware keylogger detection function.
Other devices use a passphrase instead of a key combination. This is harder to brute force and as stated above it all depends on the way the keyloger snoops the traffic. If it does take into account the source of the traffic then the above method is useless and the keylogger is still invisible.
Tar file with the code : keelogdetect.tar
Source code available via SVN : http://code.google.com/p/cdumitru/source/browse/#svn/trunk/keelogdetect