This post is available to download as a whitepaper.
Introduction
Tampering with hardware is method by which attacker can physically modify systems in order to introduce new malicious functionality, such as the ability to exfiltrate data without resorting to exploiting software based vulnerabilities.
In this post, we demonstrate the possibility of modifying a standard KVM switch to include an Arduino based key logger. We show that this can be achieved using off-the-shelf tools and components by anyone with a minimum of electronic engineering and programming knowledge.
KVM switches are hardware devices frequently used in operational environments that allow a user to easily switch between and control multiple computers from a single keyboard, monitor and mouse.
They fall into some broad categories:
- Entry-level domestic and SoHo KVM switches operating from a physical button, with little scope for hacking.
- 'Hot-Key' KVM switches that allow the user to switch between attached computers by entering a combination of key presses. The inclusion of a microcontroller to identify a hot-key press suggests that these devices may be subverted as a key-logger.
- Enterprise level KVM switches offering tighter system integration. These are likely to be significantly more complex, and may be running small, real-time operating systems, with the consequent opportunities for hacking.
The Belkin E Series OmniView 2-Port KVM switch is a domestic/SoHo unit that provides hot-key switching. This was selected as being representative of devices in this category, so the outcome of any analysis is expected to be broadly applicable across similar devices from other manufacturers. Low cost units can be found on eBay (less than £10).
Belkin E Series OmniView 2-Port KVM Switch
Opening the Case
- Microcontroller PIC16C57C
This is an OTP PIC microcontroller made by Microchip Technology. This can be seen in the picture below as the larger chip towards the right of the PCB at the rear next to the cylindrical black buzzer. As can be seen from the picture, the microcontroller is in a DIP package, and is mounted in a socket. This makes it particularly easy to remove the microcontroller to help with reverse engineering. - 5 x 74HC4053D
These are triple analogue dual multiplexers made by NXP. A dual multiplexer is capable of switching a single input to one of two outputs, so these five devices likely form the core logic for switching the PS/2 keyboard and mouse signals between one of the four output ports.
Belkin E Series OmniView 2-Port KVM Switch Internals
The PIC16C57C Microcontroller
This includes documentation on the programming and verification protocol, which is useful for reverse engineering.
Firmware analysis
Programming and Verification Protocol
- Apply power (5V Vdd, Ground Vss).
- Hold T0CKI high.
- Hold OSC1 low.
- Bring Vpp up to the programming voltage (13V).
(this puts the PIC into programming mode and resets the program counter) - The value at the current program counter can be read from pins RA0-RA3, RB0-RB7 (the PIC16C57C has a 12-bit word).
- Set OSC1 high. This increments the program counter.
- Set OSC1 low, and repeat step 5.
- Continue until all locations are read.
Using this procedure, the first location to be read is a special configuration register, which has a pseudo-address of 0xFFF. Once OSC1 is clocked (at steps 6 and 7) the next location to be read is memory location 0x000 then location 0x001 and so on.
Building a verifier
The picture below shows an Arduino Uno board wired to a ZIF socket holding the PIC16C57C removed from the KVM switch. The power supply for providing the 13V programming voltage is also shown. Due to I/O restrictions on the Arduino Uno, only four bits are being read from the PIC, but it would be possible to reconfigure the device to read all other bits, such that the entire contents of the PIC16C57C could be read in several passes. Other development boards (such as the Arduino Mega) have sufficient I/O to read all 12 bits simultaneously.
Verification of PIC16C57C using Arduino
Code Protection
Unfortunately, reading the configuration register from the PIC16C57C taken from the Belkin KVM switch showed that the code protection bits were enabled, meaning that it was not possible to read the firmware from the PIC16C57C.
Logic analysis
Rationale
- Analyse the logic implemented by the PIC16C57C microcontroller, and rewrite the firmware from scratch on an equivalent PIC device.
- Analyse enough of the logic implemented by the PIC16C57C microcontroller to determine how to piggy-back a secondary microcontroller to a subset of the device pins in order to monitor keypress data and implement a key-logger in the secondary microcontroller.
Determine Pinout Functions
Overview
Each pin should be investigated while running through a variety of functional scenarios with the KVM switch:
- Switching between outputs.
- Typing on the keyboard while each of the outputs is active.
- Moving the mouse while each of the outputs is active.
- Plugging an end system in/out of one of the output ports.
Using an Oscilloscope to Test Pin Functionality
Some of the pins on the PIC16C57C have fixed functionality (see pinout diagram above) but it is the general purpose I/O pins 6-25 which are of interest. Investigation with an oscilloscope and multimeter revealed the following:
Pins 6-14
- Pin 6 - RA0 - Usually high, but pulled low while push-button switch is depressed.
Most likely the input pin for the push-button switch to change outputs. - Pin 7 - RA1 - Low when KVM Port 1 output is selected, and high when KVM Port 2 output is selected.
Examining traces on the PCB, this also matches the sense of the input select pins on the 74HC4053D multiplexers.
Using the multimeter in resistance mode, this pin is connected to the multiplex selector inputs S1, S2 and S3 on ICs U7, U8, U9, U10 (the 74HC4053D multiplexers).
This therefore looks like an output pin that selects between Port 1 and Port 2 output on the KVM switch. - Pin 8 - RA2 - As with Pin 7, this is low when KVM Port 1 output is selected, and high when KVM Port 2 output is selected.
Using the multimeter in resistance mode, this pin is connected to the multiplex selector inputs S1, S2 and S3 on IC U2
Using the multimeter in resistance mode, this pin is also connected to OE1 in IC U3 (similar functionality to the multiplexer).
This therefore looks like another output pin that selects between Port 1 and Port 2 output on the KVM switch.
It's not entirely clear why both Pin 7 and Pin 8 appear to have similar functionality. One possibility is that Pin 7 controls the PS/2 (mouse, keyboard) switching, and Pin 8 controls the video switching. This would need further investigation. - Pin 9 - RA3 - Usually high, but activity is seen during switching between ports on the KVM switch.
Looking in detail at the activity on this pin during switching, the oscilloscope showed a waveform of about 3 cycles/cm on the oscilloscope screen when the scope is on 1ms/cm time-base - which makes this a 3kHz waveform.
It is very likely that this pin is directly driving the buzzer, as a short high pitched (about 3kHz) beep is made by the KVM switch under certain circumstances; for instance, when switching between output ports.
- Pin 10 - RB0 - High when there is a device connected to KVM Port 1.
This appears to be an 'output enable' for the device connected to Port 1.
During switching between ports, this pin is pulled low for a significant period (~1 sec) and the returns high.
During the time the pin is pulled low, no output is seen from Port 1, although there is activity on pins 20-23 (mouse/keyboard).
As a point of interest, the LEDs showing which port is selected also do not change until after this ~1 sec period). - Pin 11 - RB1 - High when there is a device connected to KVM Port 2.
This appears to be an 'output enable' for the device connected to Port 2.
During switching between ports, this pin is pulled low for a significant period (~1 sec) and the returns high.
During the time the pin is pulled low, no output is seen from Port 2, although there is activity on pins 20-23 (mouse/keyboard).
As a point of interest, the LEDs showing which port is selected also do not change until after this ~1 sec period). - 12 - RB2 - HIGH - No activity seen - no connections seen on PCB.
- 13 - RB3 - LOW - No activity seen - no connections seen on PCB.
- 14 - RB4 - HIGH - No activity seen.
PCB trace visible, apparently to Pin 14 on U9. Confirmed with multimeter in resistance mode.
This is 'Input 1' on the 74HC4053, which means it will be switch between a pin on KVM Port 1 and Port 2 via the multiplexer.
This may be an input or output - that is, either the KVM switch will send a signal to the PS/2 connector on the KVM output port, or receive a signal. However, no activity is seen on this pin in any of the scenarios tested.
Pins 15-25
- Pin 15 - RB5 - HIGH - No activity seen - no connections seen on PCB.
- Pin 16 - RB6 - HIGH - No activity seen - no connections seen on PCB.
- Pin 17 - RB7 - HIGH - No activity seen - no connections seen on PCB.
- Pin 18 - RC0 - LOW - No activity seen - no connections seen on PCB.
- Pin 19 - RC1 - HIGH - No activity seen - no connections seen on PCB.
- Pin 20 - RC2 - PS/2 Mouse – Clock
The oscilloscope shows regular bursts of pulses on this pin when the mouse is moved.
The regularity of the pulses implies that this is the PS/2 clock for the mouse.
Some activity on this pin was also seen during switching between KVM ports, when there was no mouse movement. See comments below about the purpose of pins 10 and 11. - 21 - RC3 - PS/2 Mouse – Data
The oscilloscope shows irregular bursts of pulses on this pin when the mouse is moved.
The irregularity of the pulses implies that this is the PS/2 data for the mouse.
Some activity on this pin was also seen during switching between KVM ports, when there was no mouse movement. See comments below about the purpose of pins 10 and 11. - 22 - RC4 - PS/2 Keyboard – Clock
The oscilloscope shows a regular burst of pulses on this pin when a key is pressed or released.
The regularity of the pulses implies that this is the PS/2 clock for the keyboard. - 23 - RC5 - PS/2 Keyboard – Data
The oscilloscope shows an irregular burst of pulses on this pin when a key is pressed or released.
The irregularity of the pulses implies that this is the PS/2 data for the keyboard. - 24 - RC6 - LED1
This pin corresponds directly to the state of the LED for KVM Port 1. It is therefore likely to be the output driver for the LED. - 25 - RC7 - LED2
This pin corresponds directly to the state of the LED for KVM Port 2. It is therefore likely to be the output driver for the LED.
Purpose of Pins 10-11: Output Isolation
In addition to this the KVM switch supports hot-key switching. This is triggered by pressing the 'Scroll Lock' key twice. At this point, the unit beeps (to indicate that it has entered its 'hot-key' state) and waits for additional keypresses for about 1 second. Any keypress during this time is interpreted by the KVM switch and not passed on to the connected computer. This functionality requires that the PS/2 output ports can be disabled while in this 'hot-key' state, and this is achieved by pulling pin 10 or 11 low.
Incomplete Analysis
As the analysis is incomplete, regenerating a working firmware from scratch is likely to be a challenge. Of the two options for subverting the KVM switch to implement a key-logger (see the 'Rationale' section above) the option of piggy-backing a secondary microcontroller seems more tenable.
The PS/2 Interface
The PS/2 interface can be driven by either the host or the device, and the electrical characteristics of the interface mean that it should be possible to inject data onto the PS/2 bus even when both host and device are connected. This will be useful when attempting to piggy-back a secondary microcontroller in the KVM switch.
Implementing a Keylogger
Exfiltration should be via the existing interfaces on the KVM switch. The attacker would then only need in-situ access to the KVM switch in order to extract the data. One option is to implement an additional hot-key sequence in the secondary microcontroller. When this hot-key sequence is triggered, the secondary microcontroller would dump logged keypresses as keypress data to whatever system is connected to the KVM switch. This would allow an attacker to (for example) open a text editor on the target system and then press the hot-key sequence to dump the logged data into a text file.
Electrical Constraints
"A pin actively outputting a high or a low should not be driven from external devices at the same time in order to change the level on this pin (“wired-or”, “wired-and”). The resulting high output currents may damage the chip."
This means that an attempt to implement a keylogger, and exfiltrate the logged data, must use only pins on the PIC16C57C that are configured as inputs.
Sharing the PS/2 Bus
The PS/2 bus is designed to be a point-to-point connection between a host computer and a peripheral device. It is a simple two-wire protocol (clock and data) and allows bi-directional communication. This is achieved by using an open-collector interface for both clock and data pins (see "The Electrical Interface" section), allowing either host computer or peripheral device to drive the state of either pin to low.
So, from a purely electrical standpoint, it is possible for a second peripheral device (the KVM switch) to drive the clock and data pins of the PS/2 interface. From the host computer, both peripheral devices (real keyboard, and KVM switch acting as 'fake' keyboard) would be indistinguishable. However, there is a question of whether activity from the 'fake' keyboard may cause unexpected behaviour in the real keyboard.
In the PS/2 protocol, a majority of the communication is in the direction between the peripheral device and the host. The clock is always generated by the peripheral device, meaning that the peripheral device is generating clock and data signals the majority of the time. If the host needs to send data to the peripheral device (for example, to set the state of LEDs, such as caps lock), the host first alerts the peripheral device that it wishes to send data by holding the clock line low for more than 100μs as part of a 'request to send' signal. Therefore the concern is that activity on the PS/2 bus of the KVM switch acting as a 'fake' keyboard could be interpreted by the real keyboard as a 'request to send' from the host.
When sending data on the PS/2 bus, the peripheral device generates a clock signal in the range 10-16.7kHz, therefore the clock cycle is 100μs at the slowest clock speed (10kHz). This means that the 'fake' keyboard will be pulling the clock low for a maximum of 50μs, meaning that this should not be interpreted by the real keyboard as a 'request to send', therefore, sharing the PS/2 bus should be possible.
Detecting the Hot-Key Sequence
There are two options for implementing the hot-key sequence for exfiltration of logged data:
- Detect the triggering key sequence ('Scroll Lock' pressed twice) independently in the piggy-back microcontroller.
- Detect the 'output enable' pins being pulled low, indicating that the hot-key sequence has been triggered.
Proof-of-Concept Hardware
Proof-of-Concept Keylogger Hardware
- Black: PIC16C57C pin 4 (Ground). Arduino ground.
- Blue: PIC16C57C pin 22 (PS/2 keyboard clock). Arduino digital I/O pin 2.
- Green: PIC16C57C pin 23 (PS/2 keyboard data). Arduino digital I/O pin 8.
- Red: PIC16C57C pin 11 ('Output enable' signal for KVM switch port 2). Arduino digital I/O pin 9.
Proof-of-Concept Software
Control Flow
- • While the 'output enable' is high (output enabled), log keypress data.
- • When the 'output enable' is low (output disabled due to hot-key trigger sequence), detect the exfiltration hot-key sequence.
- • If the exfiltration hot-key sequence has been detected and the 'output enable' transitions from low to high (becoming enabled again), exfiltrate the keypress data.
Key Logging
Due to the manner in which the Arduino board is connected to the KVM PIC16C57C, the same pins on the Arduino need to be used to both read PS/2 keyboard data during key logging, and write PS/2 keyboard data during exfiltration. The 'PS2Keyboard' library only supports reading PS/2 data, a separate library is required to send data. In order to support this, a small addition to the 'PS2Keyboard' library had to be made in the addition of an end() method for the 'PS2Keyboard' library to release the interrupt used to read data. Without this addition, the 'PS2Keyboard' library would continue to read data during exfiltration.
During key logging, keypress data received from this library is stored in a ring buffer, ready for exfiltration. Note that this keypress data is ASCII rather than PS/2 scan codes, so this needs to be taken into account during exfiltration.
Exfiltration
The PS/2 protocol uses a clock running in the 10-16.7kHz range, and sends serial data with the following characteristics:
- One start bit (data held low)
- 8 data bits, LSB first
- One parity bit (odd parity)
- One stop bit (data held high)
This data transmission format does not correspond with any of the built-in data transmission protocols in the Arduino, meaning that a custom driver needed to be written. In order to implement the PS/2 protocol, a timer can be used that generates software interrupts at twice the rate of the 10-16.7kHz range required (in order to generate both rising and falling clock edges). The Arduino Uno supports 3 hardware timers that can generate software interrupts, and Timer 2 was selected for this proof-of-concept (Timer 1 is used by some of the standard Arduino libraries, making it unsuitable).
A driver was written that manually sets the PS/2 clock and data pins on a 25kHz interrupt running off Timer 2 on the Arduino board. On each interrupt, the clock pin is driven successively high or low, and the data pin is manipulated to generate the start bit, data bits, parity and stop bits as required.
When exfiltration is triggered by the hot-key sequence, logged data from the ring buffer needs to be exfiltrated. This is ASCII data, so cannot be sent directly as PS/2 scan codes. Instead, the data is exfiltrated as the hexadecimal representation of the ASCII of the logged keypresses. This can easily be converted back to the original keypress data once exfiltrated. For ease of conversion, the data was exfiltrated in a form compatible with the 'xxd' utility program available on Linux and other similar systems, similar to that shown below:
7373682074617267657473797374656d
0a726f6f740a50617373773072643132
330a
For each hex character output, the 'key depressed' keyboard scan code corresponding to that hex character (0-9 and A-F) is generated by the PS/2 driver, immediately followed by the 'key released' scan code for that same key. This continues until the entire ring buffer has been output.
The outcome of this exfiltration process is that the attached host computer sees a sequence of keypresses corresponding to the hex representation of the logged data. An attacker wishing to capture this data simply has to open a text editor on the target system, trigger the exfiltration, and watch as the exfiltrated data is 'typed' into the text editor.
Source Code
Conclusion
Understanding ‘normal’ network traffic and remaining vigilant for unexpected and unusual network traffic, such as a new device suddenly connecting externally, can help organisations detect and block exfiltration over networks. However, in critical environments organisations need to identify and track hardware that is allowed to connect to critical systems including simple devices such as peripherals that are easy to overlook. The threat of physical tampering of devices means that in some environments physical examination of equipment is necessary to detect unauthorised modification.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.