USB sniffing on linux

The linux ker­nel has a facil­ity called “usb­mon” which can be used to sniff the USB bus. It’s been in there for ages, and the out­put is really easy to col­lect, even from the com­mand line shell. Sim­ply mount debugfs and ins­mod the usb­mon module:

mount -t debugfs none_debugs /sys/kernel/debug
modprobe usbmon

Then you can just cat USB traf­fic like this:

cat /sys/kernel/debug/usbmon/1u

It all comes out in an ASCII dump for­mat which is eas­ily parsed. Every USB bus also has a device file where you can sniff the raw pack­ets straight off the wire. More info in the usb­mon doc­u­men­ta­tion.

But while it’s all eas­ily parsed if you need it, there aren’t really any tools around that do it for you. That is… except for libp­cap. Libp­cap is the power behind the throne of the ven­er­a­ble tcp­dump tool. Tcp­dump is not much more than a com­mand line parser and pretty-printer of var­i­ous net­work pro­to­cols. The heavy duty lift­ing is done by libp­cap, not least by pro­vid­ing a cross-platform API for sniff­ing devices, some­thing that is oth­er­wise non-standard and dif­fer­ent on every plat­form. It’s great, I’ve used it before (in cap­stats) and it’s very easy to use.

Libp­cap on linux sup­ports usb­mon sniff­ing, which means you can use tcp­dump to sniff a USB port and write this to a cap­ture file. But best of all: wire­shark, the all-singing all-dancing net­work ana­lyzer that uses tcp­dump cap­ture files, has USB sup­port as well.
So this is the result:

Wireshark screenshot

The screen­shot shows a fil­ter applied to only see device 18 on the sniffed USB bus. That’s an arduino, i.e. an FTDI USB-serial chip. The FTDI chips send sta­tus updates to the USB host sys­tem every 16ms (!). The sta­tus update con­sists of a two-byte mes­sage (described here). This is actu­ally present in every packet com­ing in from the FTDI chip; sta­tus updates just don’t have any other data. So for a clean sniff­ing ses­sion from the arduino, we want to fil­ter out any pack­ets that are < 3 bytes in length.

The end result is ser­ial data which the arduino sent to the host sys­tem. The screen­shot shows a ses­sion on my arduino shell, arsh. This is great stuff — wire­shark includes a mas­sive amount of analy­sis tools and lots of options for fil­ter­ing and oth­er­wise mas­sag­ing your cap­tured data.

You need rel­a­tively recent ver­sions of libp­cap, tcp­dump and wire­shark for this. I com­piled all three of these out of their respec­tive repos­i­to­ries (easy com­pile all). On my ubuntu sys­tem, the libp­cap ver­sion was par­tic­u­larly old. Tcp­dump doesn’t have a pretty-printer for USB data yet, so you can only dump to a cap­ture file for pro­cess­ing by wireshark.

No related posts.