Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

* Original Author: Niqiao Security. This article is part of the FreeBuf original reward program. Reproduction without permission is prohibited.

1. Introduction

In 2014, at the Black Hat conference in the United States, researchers Jakob Lell and Karsten Nohl presented the attack method of BadUSB. Although there have been some articles related to BadUSB in China, most people still feel a vague sense of “not understanding but impressive” after reading them. After some time of study and research, I hope to share my insights to help others gain a clearer understanding of BadUSB, and I hope this article can provide some inspiration. This article is mainly divided into five parts: knowledge clarification, BadUSB firmware writing, BadUSB configuration interface, technical outlook, and conclusion.

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

2. Hardware Preparation

The hardware used in this article is the Arduino Leonardo development board, but it is not difficult to replace the Leonardo with other Arduino boards.

3. Knowledge Clarification

1. Although the USB protocol has certain vulnerabilities, not every USB device can be used to create BadUSB. There are two core requirements to create BadUSB: one is the ability to write corresponding firmware for the USB device, and the other is to burn the written firmware onto the USB device. To write the appropriate firmware, one must master the instruction specification documents of the microcontroller (or chip) in the USB device (if Intel does not provide development documents, then no one besides Intel can write programs for Intel processors);

To burn the firmware onto the USB device, one must either use a corresponding hardware programmer or rely on an existing bootloader in the USB device to assist with the burning process (the bootloader is embedded in the USB device by the manufacturer during production, and some mass production tools for certain USB drives are leaked from the manufacturer, not written by third parties).

Meeting both core conditions simultaneously is quite difficult. Even the BadUSB exploit code released by Jakob Lell and Karsten Nohl targets specific USB drives that meet certain conditions, as the leaked mass production tools are limited (since there are mass production tools available, it can be inferred that the corresponding USB drives must have a bootloader or similar firmware, and by reverse-engineering the mass production tools, one can master the communication method between the PC software and the specific USB drive, thereby creating one’s own burning tool).

2. Development boards like Arduino and Teensy are easy to create BadUSB because their microcontrollers have detailed official documentation. The most commonly used are Atmel’s microcontrollers, and Atmel’s official website provides various development documents and related libraries.

3. Atmel’s microcontrollers integrate SRAM, FLASH, and EEPROM. SRAM is like the computer’s memory and does not need to be concerned with; FLASH stores the bootloader at high addresses, while user-burned firmware is stored at low addresses. When powered on, the chip directly executes the user’s firmware, but upon reset, it first executes the bootloader (this is the key to burning), and then executes the user’s firmware; EEPROM is mainly used to store data, and users can modify the data in EEPROM freely, while the firmware can also read data from EEPROM (the firmware examples and PC programs in this article utilize this feature).

4. AVR libc is an open-source project that develops C language libraries, compilers, burning tools, and a series of auxiliary tools for various Atmel microcontrollers, as well as the WinAVR project for the Windows platform. The core of the Arduino IDE is actually AVR libc.

5. The Arduino development board has a corresponding bootloader (in the high address of FLASH) that can communicate with the avrdude.exe software from the AVR libc project to perform firmware writing and reading actions. When the Arduino development board is reset, the bootloader is loaded, allowing communication with avrdude.exe. The reset operation can be performed through the reset button on the development board or implemented via software reset (if supported by the board).

6. Intel HEX is a special file format for programmers, and it is this format that allows us to freely control the storage addresses of data. The parsing of Intel HEX file format can be searched online.

4. Knowledge Acquisition Channels

1. USB Knowledge Acquisition

If you just want a simple understanding of why USB devices can simulate keyboards, mice, and other devices, there are many blogs online that explain USB specifications in detail. You can also simply refer to “USB Development Overview” and “Detailed Examples of USB Application Development” for the general protocol section. If you are not interested in hardware, there is no need to delve deeper.

2. Arduino and AVR libc Knowledge Acquisition

Both of these are open-source, so as long as you have enough energy and capability, it is possible to dive deep into the source code to understand related knowledge. However, if you just want to experience making BadUSB, you can just look at the official documentation of Arduino and the relevant documents of avrdude.exe. When reading these documents, there is no need to delve into every detail; being able to “draw a gourd according to the gourd” to some extent is sufficient.

5. Writing BadUSB Firmware

The firmware example provided here will read data from the specified address in EEPROM during execution and send corresponding key responses to the PC host based on the read data and specified rules.

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Here are a few examples to help understand this firmware:

1. Reading ‘$’, ‘r’ from EEPROM (i.e., $r) indicates that BadUSB will press Win+R key.

2. Reading ‘$’, ‘r’, ‘;’ from EEPROM (i.e., $r;) indicates that BadUSB will press Win+R and then press the Enter key.

3. Reading ‘&’, ‘5’, ‘0’, ‘0’, ‘&’, ‘$’, ‘r’, ‘;’ from EEPROM (i.e., &500&$r;) indicates that BadUSB will press the Win+R key, then wait 500 milliseconds (to ensure the run dialog appears), and then press the Enter key.

4. Reading (&500&$rpowershell&400&;Get-Date;) from EEPROM indicates that BadUSB will first press the Win+R key, wait 500 milliseconds, input powershell, press the Enter key, wait 400 milliseconds, input Get-Date, and finally press the Enter key.

6. BadUSB Configuration Interface

The so-called BadUSB configuration interface is a simplified UI version of avrdude.exe, which also provides functionality to control the actions executed by BadUSB (essentially modifying the data at specific addresses in EEPROM, as the firmware executes actions based on the data in EEPROM).

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Figure 1 PC program interface

This program is mainly a UI interface for avrdude.exe, with only the executable and address fields designed for customizing BadUSB actions. The partno and programmer options are parsed from the selected avrdude.conf, so if avrdude.conf is not selected, the dropdowns for partno and programmer will be empty; the port number is obtained from the registry.

When the upload or dump button is clicked, it first performs a reset operation through programming (which will be explained later), and after a brief pause, executes the avrdude.exe program using CreateProcess; if the user inputs a string in the executable field, the PC program will generate an Intel HEX format file based on the user input and the address specified, (remember the Intel HEX format mentioned in the knowledge clarification section? Once familiar with the Intel HEX format, you can write the code to generate HEX files yourself, so the code will not be posted here), and then calls avrdude.exe to burn the generated Intel HEX file into EEPROM. Below is a specific demonstration.

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Figure 2 Burning firmware and specifying BadUSB execution actions

The string entered in the Executable field indicates the actions to be executed by BadUSB. Here, BadUSB first presses the Win+R key, waits for 500 milliseconds, inputs powershell, presses the Enter key, waits for 600 milliseconds, inputs Get-Date, presses the Enter key, then inputs echoabcdefghijklmnopqrstuvwxyz and presses the Enter key, and finally inputs Get-Date and presses the Enter key again. As for how I know some of the other fragmented parameters in the interface, I will explain later; if all else fails, you can try each one.

Link to demonstration video:https://v.qq.com/x/page/l03900zm1pe.html

The video does not demonstrate the extent of the harm caused by BadUSB (such as downloading trojans from servers, stealing personal information, etc.), as these belong more to the realm of PowerShell script knowledge and cmd commands, which is not the purpose of this article.

The demonstration video mainly went through the following stages:

1. After selecting the avrdude.conf file, the partno and programmer dropdowns will display the chip models and programmers supported by avrdude.exe (the programmer is essentially the protocol for communicating with the bootloader).

2. After plugging in the development board (with a prompt sound), the port dropdown will display the serial number of the development board.

3. In the executable edit box, input the key sequence that BadUSB needs to execute “&500&$rcmd”, then select the firmware to be burned into FLASH (the firmware only needs to be burned once, no need for future burns), click upload, and two command windows will pop up for burning (the first for burning firmware, the second for writing data to EEPROM), and it is found that after the development board restarts, the run dialog box pops up and inputs “cmd”.

4. Modify the content of the executable edit box to “&500&$rcmd;” (adding a semicolon, which means pressing the Enter key again), then click upload again (since no firmware is selected, it will not burn the firmware, only modify the data in EEPROM), and it is found that after the development board restarts, the run dialog pops up quickly followed by the command window.

5. Then, the content of the executable edit box was modified twice and burned to modify the EEPROM data, and it was found that once only the PowerShell window popped up, and once the PowerShell window popped up followed by executing three PowerShell commands.

7. Technical Outlook

This example only demonstrates the use of the Arduino Leonardo development board to simulate a USB keyboard, while BadUSB becomes ineffective once Windows is locked. However, it has been discovered that inserting a network card while the screen is locked causes the Windows operating system to send DHCP requests to the newly inserted network card to assign an IP address. So, could it be possible to make a USB device simulate a network card that also acts as a DHCP server and DNS server, achieving the goal of hijacking traffic and stealing information while the screen is locked? Although there are limitations, it also illustrates that BadUSB is not just a simple exploitation of USB protocol vulnerabilities, but can also leverage a series of operating system features (or flaws?) to execute in seemingly impossible environments. There are still many areas to explore with BadUSB technology.

8. Conclusion

1. To summarize, to create BadUSB, one must ensure the ability to write corresponding firmware and to burn that firmware onto the USB device through some means. The easiest way to achieve this is by using Arduino or Teensy development boards; otherwise, one needs to check if there is an official integrated development environment available, such as Cypress, which provides detailed development documents, examples, and development environments.

2. The Arduino development board mainly uses Atmel’s microcontrollers, and the compilation and burning tools also come from the open-source project AVR libc. You can go to Arduino IDE and select “File -> Preferences -> Settings” to enable detailed output of compilation and uploading, then use the IDE’s upload function to upload a sample code. In the output window, you will see a lot of useful information. Here is an example:

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Figure 3 Detailed output information from Arduino IDE (a)

3. From the output information in Figure 4, it should be recalled that the software reset of the development board is actually achieved through serial communication at a rate of 1200bps. Upon further investigation into Windows serial communication, it was found that several other parameters need to be set. What to do then? One can only check how Arduino IDE sets those parameters. The following steps can be taken to find the source code related to the settings in Arduino IDE:

① Use findstr /Sn /c:”Found upload port” in the root directory of the source code to find files containing the string “Found upload port”, and find that the path is arduino-core\src\cc\arduino\packages\uploaders\SerialUploader.java:276: (findstr is a Windows tool for searching strings in documents).

② Check the SerialUploader code and find that the string “Found upload port” is in the waitForUploadPort method. Further, it is found that the uploadUsingPreferences method calls the waitForUploadPort method, and in the uploadUsingPreferences method, the Serial.touchForCDCReset method is called, suggesting that this function is related to resetting the development board.

③ Again use findstr /Sn /c:”touchForCDCReset” to find that the implementation of the touchForCDCReset method is in the file arduino-core\src\processing\app\Serial.java:90:.

④ In Serial.java, it is found that there is a line of code:

SerialPort.setParams(1200,8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

At this point, one can boldly speculate the values of the other parameters when resetting the development board via serial communication, in addition to the 1200 parameter value.

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Figure 4 Detailed output information from Arduino IDE (b)

4. Figure 5 shows a series of parameters that Arduino IDE uses when calling avrdude.exe to burn firmware to my development board (-p is partno, -c is programmer, -b is baudrate; it can be seen that the parameters I set earlier are the same as those shown here, as those parameters were set based on the displayed settings). If interested, you can check the boards.txt, platform.txt, and programmers.txt files in the “Arduino installation path\hardware\arduino\avr” directory, which should yield many insights.

5. To create useful or highly extensible BadUSB devices using Arduino development boards, one needs to clarify the following logic:

① The Arduino development board primarily uses Atmel’s microcontrollers, which integrate SRAM, FLASH, and EEPROM. The FLASH in the Arduino development board stores a certain bootloader at high addresses, while the low addresses store the firmware uploaded by the user. The EEPROM in the Arduino development board can be used according to one’s needs.

② When the Arduino development board is reset, it first starts the bootloader, and after a period (usually a few seconds), it starts the user’s firmware. The avrdude.exe burning process is essentially communicating with the Arduino development board’s bootloader during the reset phase, so it can only successfully burn during the bootloader startup phase. It is crucial to grasp the timing.

③ The firmware program can read data from EEPROM or FLASH, and the Intel HEX format file can control writing data to specific addresses in specific memory, which greatly expands the functionality of BadUSB. Also, placing the instructions to be executed in FLASH or EEPROM can help achieve a certain degree of obfuscation.

Arduino + AVR libc BadUSB Effect Demonstration:

Can’t see the video?

https://v.qq.com/x/page/l03900zm1pe.html

* Original Author: Niqiao Security. This article is part of the FreeBuf original reward program. Reproduction without permission is prohibited.

Understanding BadUSB: Principles and Examples Using Arduino and AVR Libc

Leave a Comment

Your email address will not be published. Required fields are marked *