One of the most captivating aspects of hardware hacking is repurposing devices to perform tasks far beyond their original design. This creative and disruptive approach can yield surprisingly versatile tools from seemingly mundane gadgets.
Everyone approaches problem-solving differently. Diverse methodologies, habits, and skill sets naturally lead to varied approaches. This article details one such process, illustrating how a specific device can be transformed, focusing on the journey rather than just the final product.
Introduction
This project, initially presented at 44CON, explores the modification of a readily available device to serve a completely different purpose. The goal was to create a versatile USB emulation and exploitation device, starting with a set of desired features:
- LCD screen for visual feedback
- Menu buttons for user interaction
- USB device communication for data transfer and control
- Onboard storage for data and payloads
These features combined could create a powerful tool for USB-based security testing and device manipulation. An OBD-II reader, a common tool for car diagnostics, emerged as an ideal candidate, provided it possessed the necessary internal hardware.
After examining several options, the Nexpeak NX301 Obd2 Usb Reader was identified as a promising target.
A preliminary investigation of the Nexpeak NX301’s internal components revealed it had the desired hardware specifications for this ambitious project:
- STM32F103 MCU: Featuring 64KB of Flash memory and 20KB of RAM.
- 72MHz Clock Speed: Providing ample processing power for various tasks.
- Integrated Peripherals: Including an LCD screen, USB interface, CAN interface, and menu buttons.
- 8MB SPI Flash Memory: Offering substantial onboard storage capacity.
This specific device, or similar models under different brands, appeared to offer a perfect platform for transformation.
Firmware
The OBD2 USB reader’s USB interface is primarily intended for firmware updates, facilitated by a downloadable tool.
Analyzing the firmware update program revealed it utilized a standard STM32 USB CDC interface for firmware uploading. This indicated the use of standard system libraries and no proprietary USB communication hardware.
The update process involved downloading firmware files over HTTP, enabling quick retrieval of the firmware file once the download URL was identified using network analysis tools like Wireshark.
However, initial analysis of the firmware payload showed it was heavily encrypted, preventing a straightforward approach to modifying the firmware directly.
Furthermore, connecting to the STM32 microcontroller on the device revealed that it was locked, meaning firmware could not be read from the device, although overwriting was still possible.
Faced with encrypted firmware updates and read protection, two primary paths emerged:
1. Building Firmware from Scratch:
- Eliminates the need for complex software reverse engineering.
- Requires in-depth hardware reverse engineering to understand device peripherals.
- Grants full access to the 64KB flash memory.
- Disables the use of the device’s original firmware update functionality.
2. Breaking Readout/Firmware Protection:
- Allows modification of the original application, preserving core functionalities.
- Necessitates finding and exploiting vulnerabilities in the device’s security mechanisms.
- Potentially enables the continued use of built-in firmware updates.
- Avoids the need for hardware modifications initially.
Ultimately, a dual approach was chosen, pursuing both building custom firmware and attempting to bypass the existing protection measures.
Building Firmware from Scratch
The process began by soldering an SWD (Serial Wire Debug) header to the OBD2 USB reader’s circuit board. The conveniently placed pads made programming straightforward, even with the device case closed.
While logic analysis of all peripherals before erasing the original firmware is generally recommended, in this instance, the decision was made to assess functionality from the ground up. For standard interfaces like SPI Flash and CAN, datasheets provided ample information. However, the LCD screen presented a unique challenge.
A crucial step in hardware assessment involves tracing standard peripherals to their respective microcontroller pins, including menu buttons and LEDs. In this case, these components were directly connected, simplifying the tracing process.
Using STM32Cube design software, a project was initialized, each pin was labeled, and the SPI, USB, and CAN interfaces were configured.
The SPI Flash memory was mapped to the SPI2 port, enabling communication using standard SPI flash commands.
Furthermore, STM32Cube offers built-in USB libraries adaptable for emulating virtually any USB device type, providing the flexibility to configure the OBD2 USB reader to mimic various hardware.
Reverse Engineering the Screen
The LCD screen, identified by the part number DJM12864G13, lacked publicly available datasheets. However, online sales listings provided pinout diagrams, facilitating the assessment of each pin’s purpose.
Pin tracing and pinout analysis indicated the screen operated in parallel mode, as depicted in the diagram. Sending test packets based on command/data and read/write signal information, as outlined in the pinout, helped further decipher the communication protocol. This investigation revealed the screen utilized a standard protocol, also employed by LCD controllers from manufacturers who did provide datasheets. Leveraging these alternative datasheets enabled successful communication with the LCD controller.
This culminated in the ability to display ASCII bitmaps on the screen.
Further protocol exploration revealed the capability to draw images to the screen, albeit with some complexity.
USB Connectivity
Next, the focus shifted to the USB interface. The objective was to transform the OBD2 USB reader into a device capable of presenting itself as both a USB mass storage device, for writing text files, and a USB keyboard, for sending pre-programmed commands to a computer. The LCD screen and menu buttons would facilitate file selection for keyboard emulation.
Fortunately, STM32Cube provides libraries for standard USB device classes, including HID (Human Interface Device) and Mass Storage, ideal for emulating a USB drive and keyboard. The Mass Storage library was integrated with the onboard SPI flash memory, enabling 8MB of storage.
The custom firmware was designed to operate in two modes. Upon startup with a menu button pressed, it would enumerate as a USB disk. The SPI flash memory was formatted with a FAT32 filesystem.
Read and write commands from the USB libraries were mapped to the SPI Flash read and write commands. A key difference was the USB disk’s block size of 4096 bytes versus the flash memory’s 256-byte block size. This meant each USB read or write operation translated to 16 flash memory operations.
When started without any button presses, the device would present itself as a USB keyboard. To enable menu-based file selection, reading the FAT32 filesystem was necessary.
The FATFS library was employed for this purpose, providing functionalities for mounting, reading, and writing FAT32 filesystems, along with callback functions for hardware integration. This enabled reading files and displaying their contents on the screen.
To convert the text file contents into USB keyboard input, a translation to USB HID scancodes was required. This was achieved by creating a simple lookup table mapping characters to their corresponding scancodes.
Integrating these components required some development shortcuts due to hardware limitations. Notably, the USB interface would only enumerate upon initial connection. Consequently, Mass Storage or Keyboard modes were selected at startup, and mode switching necessitated disconnecting and reconnecting the device.
This resulted in a functional device fulfilling the initial project goals. However, deploying this custom firmware to a completely new Nexpeak NX301 would require hardware modification, as the firmware protections remained unbroken.
Cracking Firmware Encryption
To reiterate, the security measures in place were:
- Encrypted firmware update payload.
- Code readout protection enabled.
- No readily available generic exploits for the STM32F103 chip.
While the STM32F103 is known to be susceptible to glitching attacks, this would involve hardware modifications. Other avenues for bypassing protection were explored first.
A crucial vulnerability was that SWD remained enabled in Firmware Upgrade mode. Despite readout protection, RAM could still be read at any time, even with flash memory locked, potentially revealing sensitive information like encryption keys.
Furthermore, the use of standard USB CDC communication for firmware updates made it susceptible to man-in-the-middle attacks to analyze and potentially manipulate the update process.
Using a BeagleBone Black and the USBProxy USB analysis tool, firmware updates could be intercepted and examined in real-time. This technique is also applicable with other embedded Linux devices featuring USB device capabilities, such as Raspberry Pi Zero or NanoPi.
Initial inspection of the communication revealed it could be replayed using LibUSB. However, CRC (Cyclic Redundancy Check) values at the end of commands would require recalculation if the payload was modified.
A tool was developed to emulate and replay firmware updates. Each packet could be replayed and validated based on device responses. The CRC algorithm was identified as the standard X.25 CRC-16, easily implementable for payload modifications. Analysis also showed updates were transmitted in 512-byte blocks.
Superficial analysis of the firmware update file suggested it matched the chip’s memory space, implying a lack of conventional integrity checks. This was confirmed by the device’s failure to boot with a corrupted firmware payload. The ability to upload older firmware versions also indicated no rollback protection.
The firmware update process could be paused after each 512-byte block transmission. By doing so, the RAM location where the firmware payload was decrypted and stored could be pinpointed. Cortex-M chips, like the STM32F103, typically start their first two 32-bit blocks with 0x20 and 0x08 respectively.
This enabled manual extraction of the decrypted firmware from RAM, allowing for reconstruction of the complete firmware image. Although decryption was achieved, writing new firmware was still impossible without knowing the encryption algorithm and keys, and the chip crashed after each RAM read attempt.
While the RAM dump didn’t directly reveal the encryption algorithm, it was highly probable that encryption keys were stored in RAM. Identifying the encryption algorithm would then allow for encryption and decryption of firmware.
Therefore, attempts were made to guess the encryption algorithm. Subtle modifications to the first 512-byte block of firmware were introduced to observe their impact on the decrypted firmware in RAM. This iterative process aimed to narrow down the algorithm. The following approach was employed:
Starting with a simple modification: changing a single byte in the encrypted firmware. If only one byte changed in the decrypted firmware, a stream cipher was likely in use.
If modifying a byte resulted in changes only within the first few bytes of the decrypted firmware, it suggested an ECB (Electronic Codebook) mode block cipher, most likely AES (Advanced Encryption Standard).
If a byte modification in a later firmware section caused changes in all subsequent data blocks in the decrypted firmware, it indicated a CBC (Cipher Block Chaining) mode block cipher.
However, in this case, modifying any byte in the payload resulted in a complete change of the decrypted firmware, strongly suggesting either Block TEA (Tiny Encryption Algorithm) or XXTEA (Corrected Block TEA) algorithm was used.
Based on this assumption, the first 512-byte block of encrypted firmware and the RAM dump were processed together, iterating through each block of RAM.
This revealed the beginning of the decrypted firmware aligned with data near the start of the RAM dump, indicating the XXTEA key had been located.
- key[0] = 0x00001494;
- key[1] = 0x0000d65b;
- key[2] = 0x05e2e03f;
- key[3] = 0x00005426;
Dumping the Bootloader
With the encryption keys discovered, deploying custom firmware was now possible. However, the goal extended to dumping the bootloader, responsible for secure firmware updates.
By modifying the original firmware payload, now decryptable and encryptable with the recovered keys, the firmware could be overridden to dump the entire bootloader contents into RAM.
This RAM dump allowed for bootloader extraction and subsequent re-deployment if the flash memory was erased. A small ARM payload was crafted to ensure this persistence.
This payload, upon execution, writes a magic number (0xBBAA) to the start of RAM, then iterates through the Flash memory, writing its contents to the remaining RAM space, and finally enters an infinite loop to halt further processing. This compact code was quickly assembled using an online assembler like the one provided by shell-storm.org. The compiled code was then integrated into the update payload.
To precisely place the payload in the firmware, the reset vector address (0x04 in the binary) was identified. It pointed to 0x08004101. Flash memory starts at 0x08000000, and the bootloader size was known to be 0x4000 bytes. Removing these offsets and the Thumb code indicator bit (lowest bit set) yielded an offset of 0x100, where the assembled payload was inserted in the firmware.
Dumping RAM after running this modified firmware revealed the magic number, followed by the bootloader code.
This granted complete understanding of the device’s original firmware update process.
Knowledge of firmware update procedures enables firmware deployment without hardware modifications.
Sensitive information embedded in the firmware can be extracted.
Modification of the existing firmware is now feasible.
Access to the bootloader ensures device recovery in case of accidental flash memory erasure.
Collectively, this level of access allows for repurposing the device for various applications without hardware modifications. However, to explore further possibilities, hardware modification was also undertaken.
Modifying the Hardware
Simple hardware modifications can introduce new functionalities or replace existing ones. Removing components like the CAN interface, which was irrelevant to the new project goals, freed up pins for other purposes.
The CAN interface pins were reassigned to timer and interrupt pins.
These reconfigured pins were sufficient to replicate a previous project: creating NFC tag emulation devices.
The original CAN communication components were desoldered, and wires were soldered in their place to connect a new daughterboard.
Using a previously established design, a compact daughterboard was fabricated and connected via these wires.
An antenna was then attached to this daughterboard and routed to the back of the device case.
The software developed for the USB emulation project was adapted. The USB Mass Storage functionality was used to store binary NFC tag data on the device, accessible for emulation.
The 72MHz clock speed of the STM32F103 allowed for near-direct porting of the software to the new hardware configuration. The LCD screen served as a menu interface for selecting NFC tag data loaded via USB.
A readily available Lithium-Ion battery was taped to the back of the device and connected directly to the SWD pins for power.
With minor adjustments to the FATFS library to accommodate memory constraints, this culminated in a fully functional 13.56MHz NFC tag emulator with a menu-driven interface.
Video
Video demonstration of the modified OBD2 USB reader project
Conclusion
Modifying existing software and hardware within embedded devices can be a challenging yet highly rewarding endeavor. It fosters valuable development and reverse engineering skills applicable to broader IoT security domains, breathing new life into discarded electronics.
Exploring the inner workings of devices before discarding them is strongly encouraged. You might be surprised at what you can repurpose them to become.