Derby Makers

The heart of Derby's Maker community

Capturing USB communications to reverse engineer a driver

The USB specification includes details of how various standard devices should communicate so that they Just Work without needing a specific driver for your operating system (OS). The standards don’t include all devices and functionality though, so sometimes manufacturers define new ways to communicate with their device, and write a driver for one or more operating systems. Some manufacturers are open about what they’ve done so that others can write drivers for an OS the manufacturer doesn’t support, while others keep it secret. In that case if you want to write a driver you first need to work out how it communicates, so you need to listen in on its USB communications.

Common Tool – Wireshark

Wireshark is a widely used tool for traffic analysis. Originally for interpreting network protocols, it expanded to cover many other wire protocols including USB. In some OSs it can capture communications directly, while in others you need to capture to file with another tool then open in Wireshark for analysis.

Capture Options

In practice we’re usually looking at capturing traffic from a Windows USB driver, since almost all devices will have one.

Direct capture in OS

In Windows you can try USBPcap to capture USB communications. An outstanding bug report says that it doesn’t work for all devices though.

Linux has built in debug capability that can be used to log USB communications, and Wireshark can use this.

Capture via virtual machine

This option comes with a lot of IFs, but works well for the usual case of capturing traffic from a Windows machine. You need a virtual machine that does USB passthrough – letting the virtual machine have access to the physical USB device. You need to be able to run the OS with the USB driver on the virtual machine – not a problem for PC based operating systems, but may be tricky for phones and tablets. Finally you need to be able to capture the USB traffic, either through a tool on the host OS, or a capability of the virtual machine.

VirtualBox 5 can run Windows (among others) as a guest OS, does USB passthrough, and can capture the USB traffic.

Hardware devices

There are hardware devices that you connect in between the computer and the device to listen in on the USB communications. This means that they work with any OS, but they’re usually expensive and aimed at professionals debugging their USB devices.

A practical example

For a real life example take the Focusrite Forte, a rather nice but now discontinued USB audio interface. Its most basic function follows the UAC2 standard for audio devices, so will work with any OS that supports the standard. Its internal switching, volume control and mixing are all controlled through custom communications though, so you need to use their Windows or MacOS software for it to work properly. That software hasn’t been updated, and some users are reporting problems with the latest MacOS and Windows 10 versions. I’d like it to work with linux.

General approach

I’ll be using Kubuntu 18.04 as my host OS as that’s what’s on my desktop, although the process will be similar with other varieties of linux. The guest OS will be Windows 7 Pro as that’s the one I have a licence for. The virtual machine will be VirtualBox 5 because that’s the first I remembered the name of, and it worked. I’ll use Wireshark to capture and view the communications.

Installing the tools

I’ll give the command line instructions as it’s more compact than screenshots of a gui. The packages we need are:

  • virtualbox – the core of the virtual machine
  • virtualbox-ext-pack – required for USB 2 and USB 3 support
  • wireshark-qt – I picked the Qt version as I’m using KDE, but you could use wireshark-gtk or just wireshark
sudo apt install virtualbox virtualbox-ext-pack wireshark-qt

During installation you will need to accept the VirtualBox licence. You will also be asked whether you want to configure wireshark for group (non-root) access, which you need to do. If you don’t do this, or if wireshark has previously been installed without this set, you can reconfigure it by running:

sudo dpkg-reconfigure wireshark-common

Setting permissions

To be able to capture USB traffic in Wireshark you need to be in the ‘wireshark’ group. To do USB passthrough to the virtual machine you need to be in the ‘vboxusers’ group. You can add yourself to the group using the GUI tools, or from a terminal using the commands below. $USER is the current user, or you can use a specific username if you prefer. This only needs doing once.

sudo adduser $USER wireshark
sudo adduser $USER vboxusers

To capture USB traffic you need to load the ‘usbmon’ module, and grant yourself access to the devices it creates. You will need to do this every time you reboot.

sudo modprobe usbmon
sudo setfacl -m u:$USER:r /dev/usbmon*

You should remove the module when you’ve finished:

sudo modprobe -r usbmon

Set up the virtual machine

Start VirtualBox, in my case version 5.2.18. When it appears click the ‘New…’ menu button. Set a name for your virtual machine, then pick the OS Type and Version, in my case ‘Microsoft Windows’ and ‘Windows 7 (32-bit)’ then click the ‘Next’ button. Pick how much RAM you want the VM to have, then click the ‘Next’ button. I went with the recommended 1024MB. Next for the hard disk use the default ‘Create a virtual hard disk now’ and click the ‘Create’ button. Keep the default ‘VDI (VirtualBox Disk Image)’ and click ‘Next’. The next choice is up to you. I picked ‘Fixed size’ as it’s faster and I’m not short of disk space. Next give it a name and pick a size, then click ‘Create’. I stuck with the defaults. If you picked ‘Fixed size’ this bitmay take a while. Eventually you’ll be back at the main VirtualBox Manager window with your new machine in the list, showing as powered off.

If you’ve got a USB 2 or USB 3 device you need to check that this is enabled before starting your virtual machine. First check that the required extensions are installed properly by selecting menu ‘File’ ->’Preferences…’ and selecting ‘Extensions’ from the list on the left. If you don’t see ‘Oracle VM VirtualBox Extension Pack’ in the list then click the ‘+’ button on the right to install it. It should be in folder /usr/share/virtualbox-ext-pack/. Click ‘OK’ once you’ve installed it too return to the ‘VirtualBox Manager’ window.

Select your machine, then click the ‘Settings…’ button. Pick ‘USB’ from the list on the left of the new ‘Settings’ window. In the right hand side pick the USB version you need, then click ‘OK’ to return to the ‘VirtualBox Manager’ window.

Double-click the machine to start it. You will then be prompted to select a drive to boot from. Put your Windows install dvd in your drive, then select your drive to boot from it.

You should now see a window with the Windows install process going on as you would if you were installing on a real PC. I’m going to assume you know how to do this, and that you’ll go through as many cycles of going to Windows Update, checking for updates and installing them and rebooting when prompted as it takes to get to the point where there aren’t any more updates to do. I stopped counting after the third reboot…

Finally it’s time to install the drivers for your usb device, as the instructions usually say to do this before plugging it in. That probably means opening Internet Explorer, going to the manufacturer’s website and downloading the driver installer.

Check that your USB device works

Plug your USB device into your computer. Now go to your virtual machine window and look at the icons at the bottom right, below the virtual screen. Hover your mouse over the one that looks like a USB connector and you will see a tooltip ‘No USB devices attached’. Right-click on the icon to get a list of the devices you can attach, then click on the one you want. This will ‘plug in’ the device on the virtual machine. Windows will probably show a message about searching for the driver for the new device, which it should find as you installed it earlier. Your device should now start working.

To ‘unplug’ your device right-click on the USB icon again to get the list of devices. The checkbox next to your device will be checked if the device is ‘plugged in’. Click it again to unplug.

Identify the bus and device numbers

Before collecting data it is useful to find out the bus and device number belonging to your device. This will make it easier to separate its data from that of any other USB devices you have. The ‘lsusb’ command will tell you this, giving results something like:

 Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 010: ID 1235:8010 Focusrite-Novation Forte
Bus 001 Device 004: ID 045e:0797 Microsoft Corp. Optical Mouse 200
Bus 001 Device 003: ID 06a3:8020 Saitek PLC Eclipse Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

We’re looking at the Forte in this example, so we’re looking at Bus 1 and Device 10. We need to distinguish its data from the data from the mouse and keyboard which are on the same bus.

Note that if you physically unplug and replug your device it will be given a new device number.

Collect some data!

Start Wireshark. Below the ‘Capture’ title in the main window you should see several ‘usbmonX’ entries where X is a number, starting with 0. These are the USB capture interfaces. ‘usbmon0’ is a special interface that captures traffic from all USB buses, while the others capture traffic from the bus with the matching number. Since we know from the previous stage that our device is on Bus 1 we want to capture from ‘usbmon1’, so we select that one. Unfortunately the ‘Capture filter’ doesn’t work for USB capture, so we leave it blank. Now click the ‘Shark fin’ icon at the left of the button bar to start capture.

When capture starts the window content will change to have 3 panels, with the top one showing an increasing list of packets captured. The source and destination will be ‘host’ and a number starting with the bus and device, including devices like the mouse that we’re not interested in. We can narrow this down by entering a ‘Display filter’ in the bar below the button bar. There are pages of manual that get into the details of how this works, but for starters we can narrow it down to those starting with our bus and device number. This uses a regular expression match, which is another subject in its own right. In this case we’re only using a couple of special bits:

  • ^ – this means the start of the line.
  • \. – this matches an actual ‘.’ in a string.

We want to match a USB address starting 1.10. for the bus and device number. The final number is a subsection of our usb device, and for now we want to see all of those. The filter to do this is:

usb.addr matches "^1\.10\."

After entering it press the ‘Enter’ key, or the arrow pointing right at the end of the filter line, to apply the filter. You can now use the ‘red square’ or ‘green shark fin’ buttons to stop or restart capture as needed, and see only the packets for your device. Typically you would prepare for some known action, start capture, do the action and stop capture, then save the captured data for later analysis. The action could be ‘pluggin in’ the device on the virtual machine to see the initialisation process, clicking the ‘Mute’ button for a channel in the Windows interface, or anything similarly well defined. Once captured you an go to the ‘File’ menu to save your data, or select a subset of it for export.

Now you’ve got some data. Analysis is something for a separate post. Good luck!

Comments are closed.