On USB Driver Coding #6


In the previous post we have seen the basical skeleton of a PnP Filter Driver, going a bit Off Topic, now we will see the Basical Data Transaction Capture Mechanism, so we will directly consider only IRP_MJ_DEVICE_CONTROL, to work with IOCTLs and pass down other IRPs.

After hooking the Next Lower Device (FDO) Dispatch Table obviously we have to implement the IOCTL management system.

NTSTATUS MyInternalIOCTLCompletion(PDEVICE_OBJECT fido, PIRP Irp, PVOID inContext)

PDEVICE_EXTENSION   deviceExtension;

Context->Stack->CompletionRoutine = Context->CompletionRoutine;
Context->Stack->Context           = Context->Context;
Context->Stack->Control           = Context->Control;

now we are in the IOCTL Routine so we can dump/log all what we want 🙂

Finally we have to spent some words about FDO Hooking and next you will be able to understand the basical structure of a Filter Driver.

Locating our FIDO DEVICE_EXTENSION, is accomplished by replacing the IRP_MJ_INTERNAL_DEVICE_CONTROL callback of the FDO (not our FDO), and then the FDO AttachedDevice field can be used to recover our filter’s device object.

FdoHookDispatchPnp(PDEVICE_OBJECT DeviceObject,  // The FDO Device Object

PDEVICE_OBJECT      FilterDeviceObject = DeviceObject->AttachedDevice;
PDEVICE_EXTENSION   deviceExtension = (PDEVICE_EXTENSION )FilterDeviceObject->DeviceExtension;

// Provide Additional Information for IRP_MN_QUERY_INTERFACE
if( irpStack->MinorFunction == IRP_MN_QUERY_INTERFACE )
if( IsEqualGUIDAligned(

and final FDO Restoring

// Call The FDO’s Original IRP_MJ_PNP Callback
return (deviceExtension->OriginalLowerDriverObject)->MajorFunction[IRP_MJ_PNP]( DeviceObject,Irp );

Here ends our basical filter driver, now we need to study how to Dump and Interpret this Collected Data, to do this we have to analyse and study the URB format. An URB (USB Request Block) is the basic structure for every USB request, specifically this request  is used to send

or receive data to or from a specific USB endpoint on a specific USB device in an asynchronous manner.

The best source to study URB structs is obviously MSDN the first important structure is _URB_HEADER, that provides basic information about the host controller driver.

void DumpURB(struct Buffer *b, PURB pUrb, BOOLEAN bReturnedFromHCD)
USHORT wFunction, wLength;
USBD_STATUS lUsbdStatus;

wFunction = pUrb->UrbHeader.Function;
wLength = pUrb->UrbHeader.Length;
lUsbdStatus = pUrb->UrbHeader.Status;

Status values are defined in usbdi.h as USBD_STATUS_XXX, and these values can be printed, so here begins our real Sniff Procedure 🙂


struct _URB_SELECT_CONFIGURATION *pSelectConfiguration = (struct

if(pSelectConfiguration->Hdr.Length < URB_SELECT_CONFIGURATION_SIZE)
BufferPrintf(b,”!!! Hdr.Length is wrong! (is: %d, should be at least: %d)\n”,

return ;



and now we can print the entire pCD struct such as:  pCD->bLength, pCD->bDescriptorType, pCD->wTotalLength, pCD->bNumInterfaces, pCD->bConfigurationValue, pCD->iConfiguration, pCD->bmAttributes, pCD->MaxPower,

For interface information, we can print PUSBD_INTERFACE_INFORMATION as in the previous way any others informations can be retrived in this way, now we will consider the
URB_FUNCTION_SELECT_INTERFACE Switch’s case, where we can access to _URB_SELECT_INTERFACE, USB client drivers set up this structure to select an alternate setting for an interface or to change the maximum packet size of a pipe in the current configuration on a USB device.

URB_FUNCTION_SELECT_INTERFACE can be accessed in this way:

struct _URB_SELECT_INTERFACE  *pSelectInterface = (struct _URB_SELECT_INTERFACE *) pUrb;

and next we can enumerate all members in this way..

The same thing can be done for:

and Data Transaction Structs:

that are a bit more complex because is used by USB client drivers to perform data transaction.

struct _URB_CONTROL_TRANSFER   *pControlTransfer = (struct _URB_CONTROL_TRANSFER *) pUrb;

the complexity is caused by the TransferBuffer, that is a pointer to a resident buffer for the transfer, can be a resident buffer or an MDL.

So we have to dump, separately the TransferBuffer and/or the PipeHandle.

In the next post we will see some other struct and some other particularity to consider during the Sniffing Process 😉

See you to the next post.. 🙂

2 Responses to On USB Driver Coding #6

  1. Pn says:

    Evil did you just see this project??
    #usblib (SharpUSBLib). One goal is to provide a platform independent (Linux/Win32 solution) USB access layer for .NET.

    http://www.icsharpcode.net/ 😉

  2. evilcodecave says:

    Yeah man it’s a good lib. for User Mode Apps 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: