ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Wireshark抓取USB数据包全攻略:USBPcap安装与过滤器实战

Wireshark抓取USB数据包全攻略:USBPcap安装与过滤器实战 要说调试USB设备最头疼的事就是数据看不见摸不着。USB协议栈出错、驱动不识别、设备枚举失败……这些问题靠示波器太麻烦靠打印日志又太片面。好在WireShark不仅能抓网络包装上USBPcap插件之后连USB总线上的原始数据都能给你看得明明白白。这篇文章就是我实际调试过程中总结的WireShark抓USB包教程从插件安装、环境准备到具体抓包步骤、过滤器写法、数据包分析全部覆盖。适合搞嵌入式、写驱动、调USB转串口/虚拟串口的朋友也适合想学USB协议但被文档劝退的新手。我会把每一步为什么这么做、踩过什么坑都讲清楚照着做你也能抓到自己想要的USB数据。1. 抓USB包前必须搞明白的事1.1 USB数据在总线上到底是什么样的先说点基础概念不然你抓到的全是乱码。USB设备和主机之间通信用的是四根线除了供电和地一对差分数据线负责传输。总线是半双工的主机和设备轮流说话靠包结构来区分每个事务。一个完整的USB传输流程看起来像这样主机先发出一个令牌包Token Packet告诉设备我要做什么是读还是写然后要么发数据包要么等着设备回数据包最后来一个握手包Handshake Packet确认收到。一个事务由这三包组成而一个传输可能由多个事务组成。抓包工具做的事情就是在这对差分线上采集电平变化然后拼装成USB包。注意这里是物理层的数据包含了同步字段Sync、包标识符PID、地址字段、负载数据和CRC校验。所以你在Wireshark里看到的每一个URB其实是一整个USB事务的集合不是单纯的一个字节。1.2 WireShark能抓USB包的原理WireShark本身只认识以太网、无线局域网这些网络报文你要它直接解析USB原始数据是不行的。好在它有很好的扩展机制通过底层抓包插件把USB总线的原始数据转换成WireShark能识别的格式。Windows上最常用的是USBPcap它其实是一个内核驱动加一个用户态服务。驱动在总线层面抓取数据用户态服务负责把数据按照某种格式写出来Wireshark再以接口的方式呈现给你。Linux上则更直接内核自带usbmon接口不需要装任何额外驱动只要挂载usbmon内核模块然后把权限放开Wireshark就能直接打开这些接口。这两种方式各有优劣。USBPcap对Windows用户友好安装简单但只能抓物理控制器层面的数据虚拟机里的USB设备抓不到除非穿透直通。usbmon同样有虚拟机限制但胜在命令行友好可以配合脚本做自动化抓包。注意无论哪种方式抓到的都是总线上的逻辑数据不是电磁波射频数据。如果你想看的是USB信号质量那得用示波器不是抓包工具。2. 工具选型与环境准备Windows和Linux两条路2.1 Windows下安装USBPcap在Windows上步骤其实很固定但我见过不少人卡在第一步装完USBPcap后重启WireShark发现接口列表里还是只有以太网和无线网络。这里最容易忽略的就是权限问题。安装流程如下下载USBPcap的安装包一般是2.x版本一路下一步。但注意安装过程中要勾选Install USBPcap as a service就是安装成系统服务。如果不勾选很多设备会在休眠或拔插之后抓不到数据。装完之后建议重启系统让驱动真正加载。接下来打开WireShark点击抓包选项Capture Options你会看到 USBPcap1、USBPcap2 这样的接口分别对应不同的USB控制器。先别急着抓务必用管理员身份运行WireShark右键 → 以管理员身份运行。USBPcap驱动是内核态的没有管理员权限Wireshark连接口列表都读不完全。我曾经遇到过这种情况接口列表里能看到USBPcap1但双击之后一直提示Permission denied权限被拒绝。后来查了一下其实是Windows服务没有正常工作重新安装USBPcap并确认服务已经启动才解决。在服务管理器里搜USBPcap确认状态为正在运行。2.2 Linux下开启usbmonLinux下就清爽很多不需要装第三方驱动。先加载usbmon模块命令如下sudo modprobe usbmon sudo wireshark然后用root权限运行Wireshark在抓包接口里就能看到 usbmon1、usbmon2 等接口。usbmonX对应第X个USB控制器如果你有多块USB卡会有多个usbmon接口。但是用root跑Wireshark有风险我一般建议给当前用户加权限。你可以创建一个udev规则或者是简单粗暴地给usbmon设备文件加读权限sudo chmod r /dev/usbmon*这样普通用户也能抓包了。不过要注意usbmon接口的编号是动态的拔插设备后可能变化你要是写自动化脚本建议用ls -l /dev/usbmon*看一眼当前编号再做映射。2.3 为什么我推荐先搞懂接口选择接口的选择直接决定了你能抓到什么设备的数据。USBPcap1和usbmon1都是一套完整的USB控制器而一个控制器下面可能挂着一整颗USB HubHub下再接各种设备。如果你选错了接口目标设备刚好挂在别的控制器上那抓来的包全是别的东西。怎么确认设备挂在哪个控制器Windows上可以在设备管理器里找到你的USB设备查看位置路径里面会显示Port_#0001.Hub_#xxxx这个信息可以在USBPcap接口说明里对应。Linux下可以用lsusb -t查看设备的树形结构确认它挂在哪个usbmonX下。如果实在分不清直接挨个接口都抓一遍用过滤器把多余设备过滤掉也行但效率低我后面讲过滤器时再细化。3. 实操从设备识别到数据包过滤3.1 抓包前先确认你的设备挂在哪个总线上这一步非常关键错了你折腾半天也是白抓。假设我手头有一个FT231X USB转串口设备我想抓它和电脑之间的通信。在Windows设备管理器里找到这个设备的总线类型显示是USB并且位置路径可能显示基于某个端口。此时打开Wireshark进入抓包选项选中USBPcap1接口点选项按钮会弹出一个USBPcap特有的对话框。这个对话框里你能看到设备过滤器Device Filter栏它会列出当前这个控制器下所有接入的USB设备并给每个设备分配一个临时编号。你可以按住Ctrl键直接多选或者填写任何设备Any Device来抓全部。Linux上就用usbmonX接口直接开抓但抓到的包是全总线的所以最好用显示过滤器缩小范围。我的习惯是先确认目标设备的总线地址可以用cat /sys/kernel/debug/usb/devices或者lsusb -v看一下“Bus01 Lev01 Prnt01 Port0”之类的字段。3.2 设置过滤器抓全包还是抓目标包第一次抓USB包的人最容易犯的错就是直接点击开始抓包然后被满屏的URB淹没。USB总线上每时每刻都有各种控制传输、中断传输特别是接入USB鼠标键盘这类设备时中断包多到怀疑人生。所以一定要用过滤器。这里区分两个概念抓包过滤器Capture Filter和显示过滤器Display Filter。USBPcap本身只支持有限的抓包过滤器更多是用Wireshark的显示过滤器来做。我推荐几个实用过滤表达式直接抄作业过滤目标显示过滤器表达式只显示USB协议usb只看特定USB设备地址usb.device_address 5只看特定厂商设备usb.idVendor 0x0403只看主机发送给设备的控制请求usb.bmRequestType 0x40只看设备返回给主机的数据usb.endpoint_address 0x81只看某个方向的批量传输usb.transfer_type 0x02 usb.direction 0需要解释一下bmRequestType。这是USB控制请求的第一个字节最低位为0表示主机发送OUT最低位为1表示设备返回IN。所以0x40就是标准设备请求中的主机发送到设备这个过滤器在分析设备枚举时会很有用。还有一点设备地址在每次枚举时可能是变化的建议先用usb.idVendor或usb.product这类跟设备强相关的字段定位再结合usb.device_address二次确认。3.3 实操演示抓USB转串口的数据我现在就以FT231X USB UART为例演示一遍完整流程。第一步插上FT231X设备确认驱动正常工作。在Windows设备管理器里能看到USB Serial Port (COM3)这样的名字说明驱动装上了。第二步打开Wireshark用管理员身份运行进入抓包选项选择USBPcap1接口然后在设备过滤器里选中FT231X对应的设备注意有时候会显示成Bus 002 Device 004: ID 0403:6015 Future Technology Devices International, Ltd FT231X。直接双击选中它。第三步开始抓包然后用串口工具打开COM3发送一串数据随便写个HelloUSB也行。发送完回到Wireshark点停止抓包。此时你看到的基本都是批量传输的URB包因为FT231X的通信走的是批量传输端点。第四步在显示过滤器里输入usb.data只看有数据载荷的包或者usb.transfer_type 0x02就能看到数据内容。当你双击某个URB包时你能在详情面板里看到URB data字段展开后里面有具体的字节。这里有个很容易搞混的地方USB的批量传输不像串口那样有严格的帧格式它是按块Block传输的每个URB可能包含多个字节。FT231X驱动会把UART收到的数据攒成一个缓冲然后一次性扔给USB总线。所以你抓到的包看到的是一堆字节到了一个设备端点而不是一个字节接一个字节的串口数据。如果你想知道串口发的具体内容直接展开URB data字段的十六进制就行了。比如你发送HelloUSB你会在某个URB的data里面看到48 65 6c 6c 6f 55 53 42这就是ASCII码。4. 分析实战从原始数据到协议解读4.1 如何看懂USB控制传输的包USB控制传输是所有USB设备通信的基础包括设备枚举、配置、状态查询等。在Wireshark里控制传输的URB通常有单独的类型你可以用usb.urb_type URB_CONTROL来过滤。控制传输分为三个阶段Setup阶段、Data阶段可选、Status阶段。在Wireshark里你会看到一个完整的Control-transfer URB展开后有以下关键字段字段含义bmRequestType请求方向、类型和接收者前面讲过bRequest具体请求码比如GET_DESCRIPTOR(0x06)wValue请求相关的参数通常是描述符类型和索引wIndex接口端点索引wLength期望传输的数据长度举个例子假设你看到一个包bmRequestType0x80bRequest0x06wValue0x0100wIndex0x0000wLength0x12这是什么意思呢0x80表示设备向主机返回数据0x06就是GET_DESCRIPTORwValue的高字节是描述符类型0x01表示设备描述符低字节是索引0wLength是18字节。也就是说主机在请求前18字节的设备描述符。这类包在新设备插上时一定会出现所以当你怀疑设备枚举失败时先用它定位。我看过很多人枚举失败抓包后才发现wValue写错或者是描述符长度和实际不符。4.2 批量传输与中断传输怎么看批量传输Bulk Transfer多用于打印、U盘、串口这类大流量数据而中断传输Interrupt Transfer用于鼠标、键盘这类需要响应速度的设备。在Wireshark里切换到USB视图后你会看到每个URB都带有传输类型和端点地址。批量传输的特点是没有固定间隔只要总线空闲就发送但优先级低。中断传输则必须保证间隔时间例如鼠标每8ms汇报一次。在分析里批量包的payload通常很多你可以在抓包后直接用usb.endpoint_address 0x02 usb.data这样的组合过滤。还有一点USB传输在主机侧往往会有缓冲机制。比如STM32的USB虚拟串口它内部有端点缓冲区当缓冲区满时才提交给USB控制器。所以抓包看到的数据可能是成段的中间有间隔这不是bug是缓冲策略。4.3 结合STM32虚拟串口场景很多人调STM32的USB虚拟串口常在Windows下面临设备识别失败。这时候抓包比看代码日志有效得多。我举个例子某个开发板用STM32F407配置了VCPVirtual COM Port但插上电脑后系统提示无法识别的USB设备。用Wireshark抓包后发现在枚举过程中主机发起了GET_DESCRIPTOR请求设备返回了数据但数据最后一个字节的长度不对。原来设备描述符的长度字段被写成了0x1117而实际描述符应有18字节。Windows一看长度不对直接放弃了。修正描述符后设备立刻识别成功。如果你在调试时遇到类似问题记住一个原则抓到的USBPacket对照USB规范看每一字段是否合理。特别是描述符的bLength、bDescriptorType以及端点描述符里面的bEndpointAddress和wMaxPacketSize这几乎涵盖了90%的USB枚举问题。5. 常见问题与排查技巧实录5.1 抓不到包或者接口列表为空如果你的WireShark在打开抓包选项后看不到任何USBPcap接口或者看到接口但一个包都抓不到先从三个方向排查。第一确认USBPcap驱动已经安装。打开设备管理器在系统设备里找USBPcap Service字样。如果它被禁用了或者没启动重新启用。第二确认你用的是管理员权限。这点反复强调很多人就在这里翻车。第三确认你的USB设备是否真的活动。抓包工具抓的是总线上的事件如果设备是静态的、没有任何通信你当然什么都抓不到。最简单的方法是插上一个U盘然后格式化或拷贝文件制造数据流量看看能不能抓到。5.2 过滤器不生效过滤器不生效多半是把显示过滤器和抓包过滤器混用了。在Wireshark主界面顶部的那个输入框是显示过滤器而抓包过滤器在抓包选项对话框里。如果你在抓包选项里写了usb.device_address 5那是无效的因为抓包过滤器有独立的语法和底层驱动支持。如果你用的是显示过滤器但发现包还是满屏都是可能是语法写错了Wireshark会用红色底色提示你。建议在写过滤器时先用小写字母并且看看字段名是否拼写正确。像usb.device_address是标准字段usb.destination这种根本不存在所以查不到。5.3 数据全是乱码或看不懂数据乱码或者全是一堆无法理解的二进制通常是两种情况。一种是设备本身用的是私有协议比如某个设备的数据是加密或压缩后的此时你只能看到流没法直接看出含义。另一种是你抓到了多个设备的混合数据需要缩小范围。再就是URB数据里除了有效载荷还有协议包头QH、TD等。Wireshark已经帮你解析好了你只需要展开USB URB这个层找到Data字段或URB data字段那才是真正的业务数据。如果你用文本模式看可能会看到乱码因为很多数据是二进制或者半结构化数据用十六进制视图看更靠谱。我遇到最典型的乱码场景是抓包显示的每个URB只有十几个字节里面还夹杂着端点状态。后来发现是抓包长度设置不对默认只抓了64字节导致大量实际数据被截断。这时候在抓包选项里把Limit each packet to的数值调大比如改成65535就能看到完整数据。5.4 一个临时踩坑记录最后说一个我自己的小插曲。某次抓包明明USBPcap1能看到很多数据包可怎么都找不到目标设备的数据流。耗了半天后来在设备管理器里看到我的设备其实挂在芯片组的另一个USB控制器上也就是USBPcap2。这种多控制器的情况在笔记本上最常见右边接口走的是集线器下的控制器左边接口走的又是另一个控制器。调试前用lsusb -t(Linux) 或者设备管理器看位置路径比瞎猜快多了。结束语可以省这里补一个实用小技巧我调试了这么多USB设备最大的心得就是抓包要抓时间点。USB的枚举过程很短通常只有几百毫秒如果你提前开着抓包再插设备很容易把无关流量混进来。所以我推荐一种做法先点开始抓包再插上USB设备或者重连一次设备这样枚举包就被干净利落地捕捉到了。如果你用的是Windows的USBPcap在设备过滤器里选中任何设备后还能看到枚举之前的总线清理动作这些细微信息在排查插拔不稳时有奇效。另外如果你想保存一段干净的日志给同事分析建议在抓包结束后先用显示过滤器然后使用文件 → 导出特定分组来保存过滤后的包避免一大包垃圾数据干扰别人。这个工具用熟了你会觉得Windows和Linux下调试USB其实没那么多玄学数据都在那儿就看你会不会看了。
返回列表