Snooping the USB Data Stream

Follow along with the kernel hacker's actual problem-solving process as the quest to add support for a new device begins.

the option can be enabled by the user.

I used the definition module_param() instead of the old-style MODULE_PARM(), as this is the proper way to describe module parameters in the 2.6 kernel. The main difference is this definition has a third parameter. This third parameter, if set to something besides 0, causes the parameter to show up in sysfs and allows a user to query and modify the option while the module is loaded. With this code included, the usbcore module's directory in sysfs looks like:

$ ls -l /sys/module/usbcore/
-r--r--r--  1 root root 4096 May 13 15:33 blinkenlights
-r--r--r--  1 root root 4096 May 13 15:33 refcnt
-rw-r--r--  1 root root 4096 May 13 15:33 usbfs_snoop

The module now can be loaded as normal:

modprobe usbcore

When I decide to turn on logging I simply do:

echo 1 > /sys/module/usbcore/usbfs_snoop

and the kernel variable usbfs_snoop in the devio.c file is changed on the fly.

Now that I can determine whether the user wants to print out snooping messages, I need to modify the dev_info() calls again. I create the following macro to do this:

#define snoop(dev, format, arg...)             \
    do {                                       \
        if (usbfs_snoop)                       \
            dev_info( dev , format , ## arg);  \
    } while (0)

This macro tests the value of the usbfs_snoop variable, and if true, the dev_info() line is called. The macro is wrapped in a do { } while (0) statement to allow it to be used in any kind of code without having to worry about any side effects. All kernel macros containing more than one line of code are written in this way for this reason. For more details about this, read the kernel newbies FAQ (see Resources).

I next change all previously added calls to dev_info() to a call to snoop(), causing the code to look like:


snoop(&dev->dev, "control read: "
       "bRequest=%02x bRrequestType=%02x "
       "wValue=%04x wIndex=%04x\n",
       ctrl.bRequest, ctrl.bRequestType,
       ctrl.wValue, ctrl.wIndex);

But where the data is printed out, the snoop() macro does not work properly. I need to check the value of the usbfs_snoop variable directly, wrapping the code in an if statement:


if (usbfs_snoop) {
    dev_info(&dev->dev, "control read: data ");
    for (j = 0; j < ctrl.wLength; ++j)
        printk("%02x ", ctrl.data[j]);
    printk("\n");
}

I'm happy, and hopefully the USB maintainer also will be happy with the changes. I read how to generate a proper kernel patch by consulting the file Documentation/SubmittingPatches, generate a diff file and e-mail it off.

We now have a way to snoop all usbfs traffic, which can help us reverse engineer any device that uses libusb to communicate with a USB device. It also allows us to snoop any USB accesses from a guest OS running in a VMware session, allowing the possibility to reverse engineer Microsoft Windows USB drivers much more easily. But all of that has to wait until the next column.

Resources for this article: /article/7605.

Greg Kroah-Hartman currently is the Linux kernel maintainer for a variety of different driver subsystems. He works for IBM, doing Linux kernel-related things, and can be reached at greg@kroah.com.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

usbfs_snoop? Never heard of

Anonymous's picture

usbfs_snoop? Never heard of him.

bash: /sys/module/usbcore/usbfs_snoop: No such file or directory

ls -l

Anonymous's picture

ls -l /sys/module/usbcore/parameters/

Hi, How to get the log

Anonymous's picture

Hi,
How to get the log information about the communication between the usb-remote

Who is Garrick?

JibberJabber's picture

He sounds like a mischievous typesetter.

margarine

Anonymous User's picture

These things are not harmless, even at shops that I love and services that I use, Johnson said.

Doesn't work with 2.6.11

Markus's picture

Somehow it doesn't work for me with a 2.6.11 Kernel

also the usbfs_snoop file doesn't exist it's located in:
/sys/module/usbcore/parameters/usbfs_snoop

the article would be really nice but it looks like it doesn't fit anymore, the only thing I get in the logfile is following:


Jul 8 01:18:41 debian kernel: usb usb1: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb 4-2.3: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb 4-2: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb usb4: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb 4-2.3: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb 4-2: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb usb4: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb usb3: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb usb3: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb usb2: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb usb2: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb 1-3: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb usb1: usbdev_ioctl: CONNECTINFO
Jul 8 01:21:41 debian kernel: usb 1-3: usbdev_ioctl: IOCTL
Jul 8 01:21:41 debian kernel: usb usb1: usbdev_ioctl: IOCTL

see there are no values ..

anyway I think this is the only solution I have for hacking an usb driver, windows usbsniff doesn't show up all usb packets...

well I'll go on hacking it...

...

Markus Rechberger's picture

USB Snoop

Niel Smith's picture

How did you resolve the no values problem?

I also just get the IOCTL and CONNECTINFO messages..

thanks for mapping this out.

gstrock's picture

thanks for mapping this out.
I found it informative, clear and easy to follow.
Demystifying - yes, that's the word.
Thanks Greg.

- greg s.

Re: Snooping the USB Data Stream

Anonymous's picture

How do you enable this on the fly with the FC2 2.6.8-1.521 kernel? It appears that usbcore is built into the kernel since modprobe usbcore says it is not found. /sys//module/usbcore does not exist either. Matter of fact I cant find any tunable parameters in any of the directories under /sys/module/.

Enable without kernel module

Andre's picture

I would think that using USBFS_SNOOP as a boot parameter should work.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix