十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

USB抓包实战:从原理到工具,一文掌握Wireshark与usbmon调试技巧

USB抓包实战:从原理到工具,一文掌握Wireshark与usbmon调试技巧 USB抓包这个事我一开始觉得没必要。Wireshark 抓 HTTP、抓 TCP 都很熟了USB 不就是插上就能用直到有一次调一个 USB 转串口的设备驱动装了、枚举也正常但数据就是不对发出去的和收回来的对不上固件那边一口咬定自己没问题硬件那边也说波形正常。折腾到半夜突然想起 USB 总线上的数据其实是可以完整抓下来的直接看主机和设备之间到底传了什么比哪边扯皮都有用。从那以后USB 抓包就成了我调试工具箱里的常备技能。这篇文章就围绕 USB 抓包展开把原理、工具、实操步骤、常见问题整个过一遍。不论你是做嵌入式、搞上位机还是维护打印机、扫码枪、U 盘这类外设碰到设备枚举失败数据传输出错驱动行为诡异这类问题USB 抓包都是定位问题的最后手段也是最快的手段。1. 搞清楚USB抓包到底在抓什么1.1 USB抓包解决的痛点先说说 USB 抓包和普通网络抓包的区别。Wireshark 抓网卡流量看到的是 IP 包、TCP 连接、HTTP 请求数据在网线或者 WiFi 上跑。USB 抓包抓的则是 USB 总线上主机Host和设备Device之间的通信内容。为什么需要抓 USB因为 USB 设备对开发者来说是个黑盒。设备插上之后驱动加载、枚举成功、收发数据这一整套流程里只要有一个环节出错表现出的症状可能只是没反应报错或者数据不对。你看不到 USB 总线上到底发生了什么只能靠猜。典型场景如下新买的 USB 设备无法识别系统提示设备描述符请求失败需要确认设备在上电后有没有正确响应主机的枚举请求。USB 转串口模块FT232R、CP2102N、CH340 这类收发数据异常需要确认数据有没有从主机发出去、设备有没有回复。自定义 HID 设备的报告描述符有问题导致 read/write 失败需要看主机和设备之间的控制传输内容。U 盘或者读卡器速度异常需要确认使用的是不是 Bulk-Only Transport 协议以及每次传输的块大小和数量。调试 Linux 驱动、Windows 驱动或者固件代码需要确认某一笔 UR B的请求参数和返回状态。在这些场景里抓 USB 总线相当于直接把主机和设备之间的对话录制下来谁说了什么、什么时候说的、说的内容是什么一目了然。1.2 从抓包视角理解USB协议做 USB 抓包不需要把 USB 2.0 协议规范背下来但核心框架得懂否则抓到数据也看不懂在说什么。USB 是主从架构主机Host是唯一的总指挥设备Device是被动响应方。设备内部有多个端点Endpoint端点可以理解成设备上的数据收发信箱每个端点有方向IN 是设备发往主机OUT 是主机发往设备和传输类型。USB 的传输类型有四类传输类型特点典型应用控制传输双向、可靠、有固定格式用于枚举和配置设备枚举、设置地址、获取描述符批量传输大块数据、可靠但延迟不保证U盘读写、USB转串口数据中断传输小数据、有保障的轮询间隔键盘、鼠标、游戏手柄等时传输实时性要求高、允许少量丢数据USB摄像头、音频设备抓包时最常看到的是控制传输和批量传输。控制传输是管理面负责枚举和配置批量传输是数据面负责实际业务数据。Linux 内核里用 URBUSB Request Block来表示一次 USB 请求Wireshark 在 Linux 上抓到的 USB 包也是按 URB 维度显示的。URB 里包含了传输类型、端点号、方向、数据长度、数据内容、状态等信息。理解了 URB就等于理解了 Linux 对 USB 的抽象方式这对后续分析抓到的内容很有帮助。2. 工具选型软件抓包和硬件分析仪怎么选2.1 Windows下的软件方案Wireshark USBPcapWindows 上做 USB 抓包最主流的方案是 Wireshark 搭配 USBPcap 驱动。USBPcap 是一个开源的 USB 抓包驱动由 Wireshark 项目维护。安装后它会创建一个虚拟的网络接口Wireshark 把这个接口当作普通的捕获源来读取数据。USBPcap 支持 USB 1.1、2.0 和部分 3.0 的抓包对于绝大多数 USB 外设调试场景足够了。安装 USBPcap 之后打开 Wireshark在接口列表里就能看到 USBPcap 开头的接口。选择对应的 USB 控制器接口点开始就能看到 USB 总线上的全部流量。Windows 下的软件方案最大的优势是简单无需额外硬件一台 Windows 电脑加 Wireshark 就能开工。缺点是 USBPcap 工作在网络驱动层它依赖 USB 主控制器驱动提供的 ETW 事件所以有些 USB 控制器型号下可能抓不全。2.2 Linux下的软件方案usbmonLinux 自带的 usbmon 内核模块是最干净的抓包方式。它不依赖任何用户态驱动直接从内核 USB 子系统接收所有 URB 请求记录。用 usbmon 抓包需要三步加载模块sudo modprobe usbmon挂载 debugfssudo mount -t debugfs none /sys/kernel/debug部分发行版已自动挂载在 Wireshark 里选择usbmonX接口其中 X 是对应的 USB 控制器编号usbmon 的抓包数据格式非常规整Wireshark 对它的支持也是最完善的。在 usbmon 接口上抓包每个 URB 对应一帧包含完整的请求类型、端点、方向、状态、数据长度和数据内容。有一点要注意usbmon 默认抓取的 URB 数据有大小限制超过限制的部分会被截断抓大块批量传输时要注意这一点。可以通过系统参数调整捕获长度。2.3 硬件协议分析仪软件方案虽然方便但在两两种情况下会力不从心USB 3.0/3.1 SuperSpeed 速率太快软件方案很难捕获完整数据。设备枚举阶段失败软件方案可能连设备都看不到自然也就无从抓包。硬件协议分析仪USB Protocol Analyzer直接物理接入 USB 链路中以硬件方式镜像总线信号不依赖主机操作系统所以即使是枚举失败、设备无法识别的场景也能完整抓下主机和设备之间的物理层通信。常见的硬件分析仪有 Total Phase Beagle USB 系列、Teledyne LeCroy 的 USB Advisor国内也有不少性价比高的方案。硬件分析仪价格不便宜但对付疑难杂症确实值。2.4 方案对比与选型建议对比项USBPcap Wiresharkusbmon Wireshark硬件分析仪平台WindowsLinux跨平台自带工具成本免费免费价格高USB 3.0 抓取支持有限支持有限完整支持枚举失败场景抓不到抓不到可以抓数据还原能力较好较好强能还原时序上手难度低中中高我的建议是日常调试优先用软件方案免费且够用遇到枚举失败、USB 3.0 高速信号、需要精确时序分析的疑难问题再考虑硬件分析仪。绝大多数问题在软件方案层面就能定位到根因。3. Windows下USB抓包实操USBPcap从安装到出包3.1 安装USBPcap驱动USBPcap 可以从 Wireshark 官网下载安装包。安装时建议选择完整安装因为它会一并安装 Wireshark省得单独装。安装过程中有一点要特别注意USBPcap 会安装一个内核驱动Windows 在安装结束后通常要求重启系统不要跳过这一步否则驱动可能没有正常加载。安装完成后在设备管理器的通用串行总线控制器里能看到 USBPcap 条目说明驱动已加载。3.2 在Wireshark中选择正确的接口打开 Wireshark点击首页的捕获选项卡可以看到接口列表里多出了几个USBPcap开头的接口USBPcap1对应主机的 USB 2.0 控制器USBPcap2/USBPcap3对应其他控制器可能是 USB 3.0 的 xHCI 控制器USBPcap也可能以\\.\USBPcap的形式显示如果只有一个 USBPcap 接口直接选它就行。如果有多个需要确定你要抓的设备挂在哪个控制器下面。可以先打开设备管理器查看目标设备的总线关系和设备实例路径确认它在哪个控制器下。然后选择对应的 USBPcap 接口点击开始捕获。3.3 基本过滤规则抓到的 USB 流量会非常庞杂尤其是总线上挂着多个设备时不加以过滤会看到大量无关的轮询和中断流量。以下是我常用的过滤规则按 USB 设备地址过滤usb.device_address 3按厂商 ID 过滤usb.idVendor 0x0403按传输类型过滤usb.transfer_type 0x020x02 是批量传输按端点过滤usb.endpoint_address 0x81IN 端点 1只显示 URB 状态为成功的数据usb.urb_status 0比如抓一个 USB 转串口设备FT232R厂商 ID 0x0403可以用usb.idVendor 0x0403这样过滤后剩下就是该设备的所有 USB 通信包括枚举、控制传输和批量传输。3.4 数据包解读入门抓到数据后选中一个 USB 包看 Wireshark 下方的协议详情。一个典型的控制传输 URB 会包含以下字段bmRequestType请求方向、类型、接收对象bRequest请求码0x06 是 GET_DESCRIPTOR0x05 是 SET_ADDRESSwValue描述符类型和索引wIndex接口号或端点号wLength期望返回的数据长度枚举阶段的 GET_DESCRIPTOR 请求非常典型主机发一个控制传输设备返回设备描述符18 字节里面包含 USB 版本、厂商 ID、产品 ID、类别等信息。如果设备没有返回正确的描述符就会枚举失败。4. Linux下usbmon抓包实操一条命令开抓4.1 加载usbmon模块Linux 下抓 USB 最简单的方式就是 usbmon。先看内核模块是否已加载lsmod | grep usbmon如果没有输出加载一下sudo modprobe usbmon然后检查 usbmon 接口是否已创建ls /sys/kernel/debug/usb/usbmon正常情况下会输出0u 0s 1u 1s 2u 2s ...这类文件数字对应 USB 控制器编号。4.2 用Wireshark读取usbmon接口确认接口存在后打开 Wireshark接口列表里会显示usbmon0usbmon1等接口。选择对应控制器开始抓包。但如果 Wireshark 以普通用户权限打开可能看不到 usbmon 接口或者能看到但权限不足。这时需要确保用户有权限读取 usbmon 设备文件。可以通过添加用户到wireshark组来解决sudo usermod -aG wireshark $USER重新登录后生效。如果不想改用户组也可以用命令行工具抓取后导入 Wireshark 分析sudo dumpcap -i usbmon1 -w usb_capture.pcapng然后把 pcapng 文件放到有 Wireshark 的机器上分析。4.3 定位目标设备的Bus号和Device号抓包前先确认目标设备挂在哪个控制器上用lsusb命令lsusb输出的第一列是 Bus 号第二列是 Device 号。比如Bus 001 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC说明该 FT232 设备在 Bus 1 上对应usbmon1接口。这样就知道在 Wireshark 里应该选usbmon1。抓完数据后用过滤器usb.bus_id 1 usb.device_address 4就可以精确定位这台设备的所有 URB。4.4 命令行直接查看URB如果不想打开 Wireshark只想快速看两个端点之间的数据传输可以直接在终端读取 usbmon 的文本输出sudo cat /sys/kernel/debug/usb/usbmon/1u这个输出比较原始适合脚本处理。比如配合 grep 过滤某个端点sudo cat /sys/kernel/debug/usb/usbmon/1u | grep :81:可以看到该端点收到和发出的数据。这种方式的优势是轻量、适合自动化劣势是没有协议解析数据要自己手动看。5. 实战USB转串口设备的数据抓取与还原5.1 问题背景我手头有一个 USB 转串口模块主控用的是 FT232R上位机通过虚拟串口 COM3 发送十六进制指令设备那边返回应答。现象是上位机软件显示发送成功设备端也偶尔能收到但返回的数据在特定指令下频繁出错比如发送AA 55 01 02 03回包有时候是AA 55 01 02 03有时候变成AA 55 01 02像是丢了一个字节。这类问题怪驱动、怪设备都有可能但最直接的排查办法就是把 USB 总线上的数据抓下来看看问题出在哪一层。5.2 抓包准备确认目标设备的厂商 ID 和产品 IDlsusb显示ID 0403:6001即 FT232R。在 Windows 上直接打开 Wireshark选 USBPcap 接口开抓。在 Linux 上加载 usbmon 后选择usbmon1Bus 1。为了减少干扰数据只保留目标设备的流量用过滤规则usb.idVendor 0x0403 usb.idProduct 0x6001这个过滤条件会显示该设备的所有 URB包括控制传输和批量传输。FT232R 这类 USB 转串口设备和主机的通信分两类控制传输用于配置串口参数波特率、数据位、停止位、查询状态、读取 EEPROM 等。批量传输用于实际收发串口数据。OUT 端点地址 0x02 通常对应 OUT承载上位机下发到设备的数据IN 端点地址 0x81 通常对应 IN承载设备返回的数据。5.3 从URB中还原串口数据让上位机发送AA 55 01 02 03后在 Wireshark 里找到目的端点为 0x02 的 OUT 批量传输包。Wireshark 中展开 URB 数据能看到Data (5 bytes)这行十六进制内容就是aa 55 01 02 03。这说明上位机的数据确实到达了 USB 层并且被完整地封装在单个 URB 中。接下来看设备返回的数据。找到 IN 端点0x81的批量传输包正常情况下应该也有一个 5 字节的 URB 数据aa 55 01 02 03。但如果看到 URB 数据只有 4 字节说明设备在 USB 层的返回就少了数据问题定位在设备侧固件到 USB 控制器之间和上位机无关。如果 OUT 方向本身就少了字节说明问题出在上位机软件到 USB 驱动之间先检查串口发送代码是否有缓冲区未刷新的情况。5.4 控制传输的解读抓到的控制传输同样重要。用过滤规则usb.idVendor 0x0403 usb.transfer_type 0x00可以看到主机对 FT232R 发送的 SET_LINE_CODING设置波特率等参数请求。wLength为 7数据内容包含波特率、停止位、校验位等信息。比如波特率 115200 的 SET_LINE_CODING 数据通常是00 C2 01 00 00 00 08其中前 4 字节00 C2 01 00是 0x0001C200十进制就是 115200。后面两个字节是停止位配置和校验配置最后是数据位 8。如果你在代码里设置波特率为 115200但抓包发现主机实际下发的是其他值那说明你用的串口工具或代码在设置波特率时做了换算实际传给驱动的数值不是你以为的那个值。这也是 USB 抓包很有价值的场景。5.5 一个容易踩的坑URB数据与真实串口数据的差异USB 转串口设备抓包时经常出现一个问题上位机发送 AURB 里也有 A但设备端收到的却是 B或者反过来。让人抓狂。原因通常是 FT232R 这类芯片的驱动程序在数据进入 USB 端点前会做字符编码转换比如 7 位数据位、奇偶校验配置等。实际串口线上传输的位数和 USB 上的字节数并不完全对应。这时候抓 USB 总线上的数据只能确认数据到达 USB 驱动层的状态不能完全代表串口线上的最终波形。要确认最终输出需要搭配串口调试助手或者逻辑分析仪在 TX/RX 引脚上直接抓波形。USB 抓包负责协议层数据对不对逻辑分析仪负责物理层信号对不对两个配合才能完整定位。6. 深入分析如何从USB抓包结果定位问题6.1 区分枚举阶段和传输阶段拿到一份 USB 抓包结果第一步是判断当前捕获的是设备枚举阶段还是正常传输阶段。枚举阶段的包主要是控制传输特征非常明显主机发 SET_ADDRESS0x05给设备分配地址主机发 GET_DESCRIPTOR0x06请求设备描述符、配置描述符、字符串描述符主机发 SET_CONFIGURATION0x09让设备进入配置状态如果枚举阶段的请求多了或少了直接能看出设备在哪个环节失败。比如抓包显示主机请求设备描述符后设备没有响应没有返回数据URB 状态为错误说明设备固件的 USB 协议栈没有正确回复描述符常见原因包括 I2C/SPI 读取 EEPROM 失败、固件里描述符缓冲区内容错误等。6.2 通过URB状态定位驱动层问题Wireshark 的 USB 包有一个urb_status字段表示 URB 的完成状态。正常成功的传输状态是0Success。如果看到其他状态码说明 USB 传输遇到了问题。常见状态码包括状态码含义常见原因-2ENOENTURB 被取消设备断开或驱动主动取消请求-4EINVAL参数错误端点不存在、缓冲区非法-7EOVERFLOW数据溢出设备返回的数据超过了端点最大包大小-71EPROTO协议错误设备在总线级别响应异常-84EILSEQCRC 错误USB 物理层信号问题出现-7或者-71时先怀疑固件和硬件问题比如端点描述符配置不正确、端点 FIFO 大小设置过小、时钟不稳定导致信号完整性差。6.3 抓包数据与实际业务数据的对应很多时候我们并不关心 USB 协议本身只想知道我发的数据有没有到达设备设备返回的数据内容是什么。这种情况下直接在 Wireshark 的 USB 包详情里展开 Data 字段即可。我的习惯是给 USB 数据包加一个自定义列显示数据内容。在 Wireshark 的显示列设置里添加一列字段名填usb.capdata这样每一行就能直接看到 URB 携带的十六进制数据不用一个个点开。对于数据量大的上传下载场景可以直接把这列内容导出为文本用脚本对比前后两个 URB 的数据差异快速找出通信中断或重传的位置。6.4 大文件传输场景的抓包分析如果你抓的是 U 盘读写或者固件升级这类大流量场景包数量会非常大动辄几万甚至几十万包。此时建议分两步走第一步先抓一个小的传输比如只传 1KB 数据分析正常流程。第二步再抓完整的大传输用统计功能看整体分布。Wireshark 的统计 - 端点功能可以查看每个 USB 地址的包数和字节数快速判断哪个设备占用了最多带宽。结合 IO 图还能看出传输速率波动。如果发现批量传输的包大小一直达不到端点描述符声明的最大包大小比如声明 512 字节但每个 URB 只有 64 字节说明上位机或设备在缓冲、分帧策略上有问题数据吞吐率肯定上不去。7. 常见问题速查与解决方案7.1 Wireshark里看不到USBPcap接口症状安装 USBPcap 后Wireshark 接口列表里没有出现 USBPcap。原因USBPcap 驱动未正常加载或者 Wireshark 版本太旧。解决先重启系统确认设备管理器里通用串行总线控制器下有 USBPcap 条目如果还是没有卸载后重新安装安装过程中注意不要关闭 UAC 提示最后建议使用 Wireshark 3.2 以上版本内置了 USBPcap 支持。7.2 Linux下usbmon权限不足症状能加载 usbmon但打开 Wireshark 选择 usbmon 接口后提示 permission denied。解决把用户加入 wireshark 组重新登录或者直接用sudo wireshark不建议长期用命令行下用sudo dumpcap抓取并生成 pcapng 文件更安全。7.3 抓包数据量巨大卡顿明显原因USB 总线包含大量周期性传输比如鼠标、键盘的中断轮询还有控制传输抓包时这些杂数据都进来了。解决抓包前先设置捕获过滤器比如只抓特定usb.idVendor或者抓完用显示过滤器先过滤掉干扰项还可以在 USBPcap 的配置里通过监控筛选器限制抓取某些设备。7.4 URB数据被截断症状抓到的 URB 数据长度小于实际传输长度大块批量传输的数据缺尾。原因抓包工具的捕获长度限制了单帧最大数据量。解决在 Wireshark 的捕获选项中把限制每个包的大小改为无限制usbmon 场景下检查内核参数必要时调整捕获缓冲。7.5 抓不到枚举失败时的数据症状设备插上后系统无法识别想在 Wireshark 里看枚举交互但 USBPcap 接口上什么都抓不到。解决软件方案通常无法捕获枚举失败场景因为主机控制器在该阶段可能无法提供完整的 URB 数据。这时考虑硬件协议分析仪或者在 Linux 上用dmesg查看内核 USB 错误信息配合lsusb -v观察设备是否能返回描述符。7.6 USB转串口驱动安装失败症状FT232R、CP2102N 这类芯片插入电脑后提示驱动安装失败设备管理器显示未知设备。解决先确认不是枚举失败换一个 USB 口、换一根数据线有的线只供电不通数据下载官方驱动比如 FTDI 的 VCP 驱动或 Silicon Labs 的 CP210x 驱动安装时右键以管理员身份运行如果还不行用zadig这类工具替换为 WinUSB 驱动试试但要注意替换驱动后设备的行为可能变化需谨慎。7.7 抓包显示URB成功但应用层数据不对症状USB 层数据显示发送成功且数据正确但应用层收到后内容错误。解决这类问题基本可以排除 USB 传输层重点检查驱动对数据的处理和上位机软件的解析逻辑比如字节序、帧格式、转义字符处理、缓冲区溢出覆盖等。8. 一些实操心得USB 抓包这个技能掌握了以后排查问题效率提升非常明显。个人体会是它最大的价值不是在协议层上研究 USB 是怎么工作的而是给你提供了一个上帝视角让主机和设备之间的数据交互彻底透明化。一旦透明了很多之前靠猜的问题就变成了直接看答案。如果你是第一次接触我建议做一个最简单的实验找一个 U 盘插上在 Windows 上开 USBPcap 抓包然后格式化 U 盘。这会儿你能看到主机发出的一系列控制传输和批量传输包括读取容量、建立分区表、写入文件系统结构等。全程看完对 USB 是怎么工作的会有直观感受。后续如果还想深入可以试试在 Linux 下用 usbmon 编写脚本自动化的从 usbmon 输出中提取某个端点的数据落地成一个监测工具。比如监控某个 USB 设备在运行时是否定期上报心跳包如果一段时间没有 IN 端点数据就认为设备离线。这个思路在很多工业自动化场景里很有用。再往后USB 抓包遇到 USB 3.0 速率不够用的时候可以考虑用硬件分析仪配合上位机软件自动解析 SuperSpeed 协议。但那是另一个层次的话题了先把软件方案练熟大部分问题都能解决。
返回列表