USBPcap是一個開源的USB數據包抓取工具。本文旨在說明USBPcap抓取的USB數據包的數據格式。
基本數據類型
USBPcap程序中使用到了一些基本的數據類型,如下:
UCHAR - 8 bit unsigned value
USHORT - 16 bit unsigned value
UINT32 - 32 bit unsigned value
UINT64 - 64 bit unsigned value
ULONG - 64 bit unsigned value
USBD_STATUS - 32 bit unsigned value
需要注意的是,USB傳輸的數據都是小端序的,對於多字節數據,需要從右往左讀取。
基礎數據包頭
USB數據包的傳輸類型有:控制傳輸、中斷傳輸、同步傳輸、批量傳輸。
對於不同的傳輸類型,USBPcap有不同的數據包頭與之對應;但這些數據包頭中包含共同的基本數據包頭。下面是基礎數據包頭的定義:
#pragma pack(1) typedef struct { USHORT headerLen; /* This header length */ UINT64 irpId; /* I/O Request packet ID */ USBD_STATUS status; /* USB status code (on return from host controller) */ USHORT function; /* URB Function */ UCHAR info; /* I/O Request info */ USHORT bus; /* bus (RootHub) number */ USHORT device; /* device address */ UCHAR endpoint; /* endpoint number and transfer direction */ UCHAR transfer; /* transfer type */ UINT32 dataLength;/* Data length */ } USBPCAP_BUFFER_PACKET_HEADER, *PUSBPCAP_BUFFER_PACKET_HEADER;
傳輸類型數據包頭(transfer-specific header)
所有的傳輸類型數據包頭都繼承了基礎數據包頭,並處於傳輸類型數據包頭的起始位置;接下來是傳輸類型特有的存儲在數據包頭里的數據(如果有的話);最后是傳輸的數據。
傳輸類型定義如下:
#define USBPCAP_TRANSFER_ISOCHRONOUS 0 /* 同步傳輸 */ #define USBPCAP_TRANSFER_INTERRUPT 1 /* 中斷傳輸 */ #define USBPCAP_TRANSFER_CONTROL 2 /* 控制傳輸 */ #define USBPCAP_TRANSFER_BULK 3 /* 批量傳輸 */
下面來看下這些不同傳輸類型的USBPcap數據包頭的定義。
同步傳輸數據包頭(USBPCAP_TRANSFER_ISOCHRONOUS)
對應於同步傳輸的數據包頭的數據類型為USBPCAP_BUFFER_ISOCH_HEADER,定義如下:
/* Note about isochronous packets: * packet[x].length, packet[x].status and errorCount are only relevant * when USBPCAP_INFO_PDO_TO_FDO is set * * packet[x].length is not used for isochronous OUT transfers. * * Buffer data is attached to: * * for isochronous OUT transactions (write to device) * Requests (USBPCAP_INFO_PDO_TO_FDO is not set) * * for isochronous IN transactions (read from device) * Responses (USBPCAP_INFO_PDO_TO_FDO is set) */ #pragma pack(1) typedef struct { ULONG offset; ULONG length; USBD_STATUS status; } USBPCAP_BUFFER_ISO_PACKET, *PUSBPCAP_BUFFER_ISO_PACKET; #pragma pack(1) typedef struct { USBPCAP_BUFFER_PACKET_HEADER header; ULONG startFrame; ULONG numberOfPackets; ULONG errorCount; USBPCAP_BUFFER_ISO_PACKET packet[1]; } USBPCAP_BUFFER_ISOCH_HEADER, *PUSBPCAP_BUFFER_ISOCH_HEADER;
中斷傳輸數據包頭(USBPCAP_TRANSFER_INTERRUPT)
對應於中斷傳輸的數據包頭的數據類型恰恰為USBPCAP_BUFFER_PACKET_HEADER,沒有額外字段。
控制傳輸數據包頭(USBPCAP_TRANSFER_CONTROL)
對應於控制傳輸的數據包頭的數據類型為USBPCAP_BUFFER_CONTROL_HEADER,定義如下:
/* USBPcap versions before 1.5.0.0 recorded control transactions as two * or three pcap packets: * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data * * Optional USBPCAP_CONTROL_STAGE_DATA with either DATA OUT or IN * * USBPCAP_CONTROL_STAGE_STATUS without data on IRP completion * * Such capture was considered unnecessary complex. Due to that, since * USBPcap 1.5.0.0, the control transactions are recorded as two packets: * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data and * optional DATA OUT * * USBPCAP_CONTROL_STAGE_COMPLETE without payload or with the DATA IN * * The merit behind this change was that Wireshark dissector, since the * very first time when Wireshark understood USBPcap format, was really * expecting the USBPCAP_CONTROL_STAGE_SETUP to contain SETUP + DATA OUT. * Even if Wireshark version doesn't recognize USBPCAP_CONTROL_STAGE_COMPLETE * it will still process the payload correctly. */ #define USBPCAP_CONTROL_STAGE_SETUP 0 #define USBPCAP_CONTROL_STAGE_DATA 1 #define USBPCAP_CONTROL_STAGE_STATUS 2 #define USBPCAP_CONTROL_STAGE_COMPLETE 3 #pragma pack(1) typedef struct { USBPCAP_BUFFER_PACKET_HEADER header; UCHAR stage; /* Determines the control transfer stage */ } USBPCAP_BUFFER_CONTROL_HEADER, *PUSBPCAP_BUFFER_CONTROL_HEADER;
批量傳輸數據包頭(USBPCAP_TRANSFER_BULK)
對應於批量傳輸的數據包頭的數據類型恰恰為USBPCAP_BUFFER_PACKET_HEADER,沒有額外字段。