Skip to main content

Hack USB with USBQ

The first USB equipped devices were produced in 1996 and 23 years later there the interface is ubiquitous. Billions of USB ports are soldered onto PCB's every year. When I've worked on security assessments I'll often find hidden USB ports, too. Designers often put USB on a device to use in development stages or have USB connecting the main CPU to peripheral devices.

An example of why USB is an important part of device security

When I'm performing a security assessment of a device I'm on the hunt for USB interfaces and want to understand what they do and how they might be abused. For example one design I worked on had a fairly sophisticated system to authenticate firmware updates. Introducing a modified firmware update wasn't easy... until I found the hidden USB interface. The SOC implemented a USB device interface and the firmware provided a mass storage endpoint. After a quick solder job I could mount the SOC as a drive and modify the firmware update before it was applied!

Hidden USB interface on a PCB

There are a lot of possible USB attacks

Researchers Nir Nissim, Ran Yahalom, and Yuval Elovici published "USB-Based Attacks" (Sci-Hub link) which summarized 29 different types of attacks which can use USB as the vector of attack. These attacks range from electrical assaults against the USB hardware (USBKiller) to more subtle efforts such as creating a buffer overflow in a privileged device driver or application using a rogue USB device.

I want to become a (USB) spy

On another recent assessment we observed that a very powerful peripheral device was using a USB interface to work with the primary SOC. We really wanted to know more about these communications but quickly ran into a tool problem. At the time we were working (January 2019) one of the best known USB tools, the Facedancer21 hardware+Facedancer software combo, didn't have USB high-speed support. The peripheral just demanded USB high-speed. Would not work at low-speed at all. Michael Ossman's GreatFET One (paper) wasn't available off-the-shelf (in January 2019) and I didn't feel like starting a hardware build-out project.

I considered purchasing the commercial Total Phase Beagle USB 5000 v2 SuperSpeed Protocol Analyzer - Ultimate Edition but this product ($5,000 USD!) is a read-only tool. I knew we'd want to observe and modify traffic.

Benoît Camredon's USBiquitous

The device would tolerate a mere USB high-speed connection even if it wasn't all that fast and still work. I discovered a project, thanks to Andrey Konovalov's hardware village links, which used an off-the-shelf board, the Beaglebone Black, to implement a man-in-the-middle on the USB host-to-peripheral communications.

This tool, Benoît Camredon's USBiquitous, worked for me. I was able to make some USB PCAP files and observe get the assessment tasks I wanted to do done. Cool.

I don't usually do re-writes... but just this one time why not?

For the edope.bike project I needed to do more than just observe. I wanted to build a full man-in-the-middle that could inspect and then modify ANT+ communications over USB. USBiquitous worked but I had some ideas on how to make a different programming environment that I felt would be more useful. So I ported the Python userspace portion of USBiquitous to Python 3 and got working.

By the time I "finished" I had revamped almost every line of USBiquitous. To avoid confusion with Benoît's original work I've shortened the name of mine to USBQ. Don't bother Benoît with USBQ questions, please.

Plugins FTW

USBQ is a really simple "packet-pump". There is a main loop that reads a USB device packet and sends it to the host. Then it reads a host packet and sends it to the device. Last step is a "tick" to let plugins do work. All of the plugin hooks are defined with Pluggy. The main loop doesn't do anything on its own. All it does is call the defined hooks and the plugins do all of the work.

USBQ main loop

USBQ comes with a set of default plugins:

- decode: Decode raw USBQ driver packets to Scapy representation.
- encode: Encode raw USBQ driver packets to Scapy representation.
- hexdump: Display USBQ packet and hexdump of USB payload.
- ipython: Start an IPython session so that USBQ can be updated on the fly.
- lookfor: look for a specific USB device to appear
- pcap: Write a PCAP file containing USB communications.
- proxy: Send and receive USB packets from a USBQ proxy device using the usbq_core module.
- reload: Monitor usbq_hooks.py file and reload if changed.
- usbq_hooks: Optional user-provided hook implementations automatically loaded from from ./usbq_hooks.py

These plugins are used to implement the core mitm command which forwards USB packets while recording a PCAP.

How do the USB packets get to USBQ?

Right now the proxy plugin is dependent upon the usbq_core loadable kernel module. This loadable kernel module is unmodified from the original USBiquitous project and can be found on Github.

The kernel module must be used with a device that supports two kinds of USB ports:

  • USB host interface: The typical USB port like you find on computers most commonly.
  • USB device interface: A less common USB port, most typically found on cell phones, which allows the computer to be a USB device to another USB host interface.

There are three key functions of the ubq_core module:

  1. Forwarding USB device packets received on the USB host interface to/from the network.
  2. Defining a USB "gadget" device in the Linux kernel, when commanded by USBQ, which sets up the USB device interface to with a specified USB device configuration.
  3. Forwarding packets to/from USB to the USB device interface.

USBQ architecture

Replacing usbq_core

One key limitation I know of with the ubq_core module is that it only works with 32-bit kernels. This is a problem if you want to work with USB 3.0 devices which are almost always found on 64-bit CPUs. usbq_core is also a little hard to use. The target IP address is built into the kernel module.

I'd like to replace ubq_core and the existing USB proxy plugin with something more powerful. The mainline Linux kernel implements the USB/IP Protocol which implements a network protocol for accessing USB devices:

USB/IP protocol allows to pass USB device from server to client over the network. Server is a machine which provides (shares) a USB device. Client is a machine which uses USB device provided by server over the network. The USB device may be either physical device connected to a server or software entity created on a server using USB gadget subsystem.

The only missing piece is #3 in the list above. USB/IP does not provide a means to send USB packets received over the network out a physical USB device interface. I've seen this discussed in mailing lists but so far I don't think that's been built.

Plugins are where the action is!

USBQ itself should stay pretty simple. It really just needs to pump packets back and forth. What I'd like to do is build out a suite of additional USBQ plugins that can do more sophisticated device security checks, help automate certain types of attacks, and implement application specific protocols. One example of this is ELANCE. ELANCE is an ANT+ protocol layer for cheating at the virtual cycling application Zwift. Read more about ELANCE at edope.bike.

Building your own USB hacking tools

If you'd like to get started with hacking application protocols sent over USB I'd suggest considering USBQ for the job. The source is available on Github.