开源硬件USB抓包及协议分析工具分享

USB抓包工具属于小众产品,开源的就更少了!!

USB抓包工具分为纯软件的和硬件的两种,纯软件usb抓包工具需要在系统能正确枚举usb设备的前提下才能让内核的钩子函数捕抓到数据,而后者在usb不正常时也能捕捉到链路数据(令牌包等),属于更底层的抓包方式。

一、我用过的并且好用的纯软件USB抓包工具有:

1.USBlyzer(能很方便的帮你分析出HID报告描述符等等)

2.Bus Hound(没有协议分析,但抓包很直观,而且允许你发送一些自定义的控制传输命令给设备,用于调试。另外,Bus Hound不单能抓usb总线,包括串口、PCIE等都能抓)

很遗憾,他们都不是开源的,linux下倒是有开源的,如linux平台下“usbmon驱动+tcpdump”方式抓包。tcpdump -D可以列举可以抓包的设备,包括以太网、USB、CAN总线等。

3.linux使用usbmon驱动+tcpdump+wirshark调试:

需要编译linux加入usbmon驱动:
make  ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
                   Device Drivers -->
                            USB Support -->
                                     USB Monitor --> Select "M"

modprobe usbmon
mount -t debugfs none_debugs /sys/kernel/debug
cat /sys/kernel/debug/usb/devices

选择包含有 P: Vendor=xxx ProdID=xxx Rev= xxx 的段落(即筛选出你要抓包的USB设备的PID/VID号)
如果总线号是1,则是1u,如果总线号是2,则是2u,依次类推。特殊情况是0u表示监听所有总线
cat /sys/kernel/debug/usb/usbmon/1u > ./usbmon.txt得到原始数据

或者使用tcpdump -i usbmon1 -w /var/usb_log.pcap将捕捉到的usb数据导入到wirshark上阅读,能做简单的Class协议分析。

另外,USB错误码文档在Linux内核源码路径下的Documentation/usb/error-codes.txt有关于usb的错误代码意义说明。

二、开源硬件usb抓包工具

1.玩具级别的usb sniffer(硬件平台FTDI+USB PHY+FPGA )

http://ultra-embedded.com/usb_sniffer/

对应github代码路径:https://github.com/ultraembedded/usb_sniffer

FPGA使用verilog开发,主机软件使用C语言开发,功能比较简单,而且过滤条件也简陋,但麻雀虽小五脏俱全,有兴趣可以研究一下,我自己做过实验,我在USB PHY那里跪了,FPGA怎么都抓不到USB3300的数据包,没有去深入分析问题所在。

2.OpenVizsla(硬件平台FTDI+USB PHY+FPGA)

http://openvizsla.org/

对应github代码路径:https://github.com/openvizsla/ov_ftdi

完全开源,包括pcb电路板打样文件和BOM物料清单都有,FPGA使用python开发,主机软件亦使用python进行开发。个人觉得FPGA使用python开发目前还不成熟(Migen-A Python toolbox for building complex digital hardware),代码看起来比较冗余,我已经在ubuntu虚拟机上编译出ov3.bit了,暂不打算阅读FPGA源码,而是尝试改写其主机软件加入常用class的协议分析功能(但其实我改它用处并不大,因为目前OpenVizsla已经支持很多分析软件了,譬如wireshark、Beagle 480的分析软件等等)。usb PHY使用了ULPI接口,优点是管脚少,缺点是FPGA需要实现一个适配层转换为UTMI+接口。FPGA使用老掉牙的spartan6,开发工具使用ISE14.7,不过还好Xilinx官网说至少会供货到2027年,也胜在封装够简易(TQFP-144),方便手工焊接。4层板打板也便宜,我已经焊接好一套,正在调试中,打算实测一下效果!


此分割线之间的内容更新于2020-02-06:

       利用疫情期间丰富的春节假期,调试了一下openvizsla板子,虽然年前我手工焊接好一套,但在调试过程中相当于要重新再焊接一次,因为超多虚焊和管脚短路,反复焊接焊到我心灰意冷,尤其USB3343芯片,4mmx4mm QFN-24封装的,热风枪焊接完眼睛都花了。焊接技巧:拿镊子的手不要抖,拖锡(吸锡)要耐心。最后,焊接方面应该没问题了,又发现SDRAM型号兼容性不太好,由AS4C16M16S-7TCN改为MT48LC16M16A2P-75貌似好一点,过年快递不工作,唯有加点钱顺丰发货。最后貌似能抓包了,但运行官方的测试SDRAM命令貌似有点问题(我还没研究怎么去定位,理论上应该要在FPGA上写测试代码,用chipscope抓包分析看是控制时序不行还是虚焊还是其他问题,如果是用verilog写的还好,不过本项目是使用Migen库,没阅读过该库api说明,都不知道怎么例化chipscope来抓信号调试,先放下了,因为换另一批MT48LC16M16A2P-75又好了):

测试:$sudo ./ovctl.py report
USB PHY Tests
    ULPI PHY ID: 04240009 (SMSC 334x)
    ULPI Scratch register IO test: OK
    PHY Function Control Reg:  48
    PHY Interface Control Reg: 00
SDRAM tests
    ... 0: OK
    ... 1: OK
    ... 2: OK
    ... 3: FAIL

换另一批次的MT48LC16M16A2P-75芯片后测试正常:

$ sudo ./ovctl.preport
USB PHY Tests
    ULPI PHY ID: 04240009 (SMSC 334x)
    ULPI Scratch register IO test: OK
    PHY Function Control Reg:  48
    PHY Interface Control Reg: 00
SDRAM tests
    ... 0: OK
    ... 1: OK
    ... 2: OK
    ... 3: OK
    ... 4: OK
    ... 5: OK
    ... all passed

1)接上U盘后“$ sudo ./ovctl.py sniff hs | tee usbdump.log”能抓包:
[        ]  10.379599 d=  0.000000 [ 43.3 + 74.383] [ 34] DATA0: 55 53 42 43 40 28 79 13 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 3e 
[        ]  10.379600 d=  0.000001 [ 43.3 + 75.333] [  1] NYET 
[        ]  10.379627 d=  0.000027 [ 43.3 +102.800] [  3] IN   : 18.1 
[        ]  10.379628 d=  0.000000 [ 43.3 +103.300] [  1] NAK 
[        ]  10.379650 d=  0.000022 [ 43.4 +  0.667] [  3] IN   : 18.1 
[        ]  10.379651 d=  0.000000 [ 43.4 +  1.167] [ 16] DATA0: 55 53 42 53 40 28 79 13 00 00 00 00 00 81 ab 
[        ]  10.379651 d=  0.000001 [ 43.4 +  1.900] [  1] ACK 
0 / 16777216 (0.00 % utilization) 411 kB | 0 overflow, 39cdd08a total | R00066fc7 W00066fc7
[        ]  10.784078 d=  0.404427 [191.7 +106.433] [  3] PING : 18.2 
[        ]  10.784079 d=  0.000000 [191.7 +106.933] [  1] ACK 
[        ]  10.784081 d=  0.000002 [191.7 +109.417] [  3] OUT  : 18.2 
[        ]  10.784081 d=  0.000000 [191.7 +109.750] [ 34] DATA1: 55 53 42 43 10 70 fb 1a 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 37 
[        ]  10.784082 d=  0.000001 [191.7 +110.667] [  1] NYET 
[        ]  10.784112 d=  0.000030 [192.0 + 15.817] [  3] IN   : 18.1 
[        ]  10.784113 d=  0.000000 [192.0 + 16.317] [  1] NAK 
[        ]  10.784134 d=  0.000021 [192.0 + 37.400] [  3] IN   : 18.1 
[        ]  10.784135 d=  0.000000 [192.0 + 37.883] [ 16] DATA1: 55 53 42 53 10 70 fb 1a 00 00 00 00 00 db a3 
[        ]  10.784135 d=  0.000001 [192.0 + 38.617] [  1] ACK 
[        ]  10.784249 d=  0.000113 [192.1 + 27.117] [  3] PING : 18.2 
[        ]  10.784249 d=  0.000000 [192.1 + 27.617] [  1] ACK 
[        ]  10.784252 d=  0.000002 [192.1 + 30.083] [  3] OUT  : 18.2 

.................

但不稳定,有时会出现异常,尤其在U盘传输大文件时:

........
[        ] 396.229368 d=  0.000009 [142.4 + 29.783] [  1] ACK 
[        ] 396.229369 d=  0.000000 [142.4 + 30.083] [  3] IN   : 12.1 
[        ] 396.229369 d=  0.000000 [142.4 + 30.583] [  1] NAK 
[        ] 396.229395 d=  0.000026 [142.4 + 56.383] [  3] IN   : 12.1 
Unmatched byte ba - discarding
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/default/work/other/usb_stuff/ov_ftdi/software/host/LibOV.py", line 637, in __comms
    raise self.__comm_exc
  File "/home/default/work/other/usb_stuff/ov_ftdi/software/host/LibOV.py", line 616, in callback
    code = service.presentBytes(self.__buf)
  File "/home/default/work/other/usb_stuff/ov_ftdi/software/host/LibOV.py", line 310, in presentBytes
    self.consume(b[:size])
  File "/home/default/work/other/usb_stuff/ov_ftdi/software/host/LibOV.py", line 558, in consume
    assert ''.join("%02x"% r for r in buf) in ["e0e1e2", "e8e9ea"], buf
AssertionError: b'\xe0b\xb1'
需要运行“sudo ./ovctl.py -l”重新加载FPGA程序后,再重新抓包才恢复正常!

2)另外,出现抓不了包时,有可能需要重新插拔被测设备。

3)接上USB鼠标,打算抓取低速鼠标数据“sudo ./ovctl.py sniff ls”,发现只能抓取到最开始的枚举数据(setup阶段)就停掉了,手动鼠标,抓取不到X和Y的数据变化,重新加载FPGA重新也无济于事!(后面发现原来此时PC并没有识别出鼠标来,抓不到xy座标数据也能说得通,但问题是,为什么此时PC会识别不出来鼠标设备呢?拔掉直接接到PC上其实是ok的,即鼠标本身是没问题的,难道是接PC这端的USB线缆太长了!--0207--换笔记本上的USB充电口(黄色,没有测试蓝色的USB3.x),发现只有这个USB口能抓到鼠标数据,用万用表测量openvizsla上的USB端子,无论PC是否用充电口,Vbus均为4.96v,板上两个usb口间各个引脚电阻均为0.5欧左右,符合规范。猜想是D+/D-对地的阻抗不符合USB协议规范,我去掉R4/R5两个电阻,防止FPGA输出杂讯影响D+/D-,但没有改善。)

4)抓包输出标准文档,供第三方软件协议分析

目前抓包输出格式仅支持"verbose", "custom", "pcap"和 "iti1480a",如:

sudo ./ovctl.py -l sniff hs --format pcap --out ./my_upan.pcap供wireshark分析

如果要限定抓包时间为5s,可以设置timeout参数,如:

sudo ./ovctl.py -l sniff hs --timeout 5 --format iti1480a --out ./my_upan.iti1480a等

总结一下:

1.如果下次有开源硬件感兴趣需要制作,我宁愿花钱请贴片厂焊接算了,手工焊接太折腾人了!

2.openvizsla抓包需要手工指定ls、fs和hs(即低速、全速和高速)这个不好,不够自动化,搞错了会抓不到数据。

3.openvizsla终究不是企业产品,没有经过大量验证,有很多兼容性问题,如即使芯片型号一致(如SDRAM),时序还是有偏差,导致抓包不稳定。(我怀疑兼容性问题是由于该项目使用python转换为verilog代码的Migen库有关,开发过FPGA的人都知道,逻辑正确并不代表实际硬件能正确运行,自动转换的东西肯定没有手工编写verilog代码的时序优化做得好。综合前仿真过了,实现后也可能出现时序不过关,如产生毛刺,建立保持时间不足等,SDRAM这种运行频率达100MHz甚至133MHz高频的器件,没有做时序仿真真的很容易出问题!)

openvizsla的调试暂告一段落,初步能抓包分析,但不够稳定,还不能用于调试usb设备!!


3.PhyWhisperer-USB(硬件平台M3+USB PHY+FPGA)

https://www.crowdsupply.com/newae/phywhisperer-usb

对应github代码路径:https://github.com/newaetech/phywhispererusb

也是完全开源,这个项目比较新,2019年才启动,同样也是4层板。FPGA使用verilog语言开发,主机软件使用python开发。它除了支持普通的usb抓包外,还支持简单的功率分析。usb PHY使用UTMI+接口的USB3500-ABZJ芯片,无需操作寄存器直接对接FPGA。而FPGA使用spartan 7,属于比较新的系列,使用xilinx新一代开发工具vivado进行开发。因为芯片是BGA封装不方便手工焊接,需要花钱让贴片厂焊接,把动手能力差的创客/极客挡在门外,当然有钱人除外。另外板内也不含SDRAM,没法对数据进行缓冲处理,只使用FPGA片内有限的Block RAM(仅360Kbit容量)作为缓冲区,所以当抓USB2.0摄像头这种大量、连续的USB数据时应该存在丢数据的可能,最后,该项目还包含一个microchip的单片机,我认为是一个败笔,虽说可编程器件比较灵活(官网是这么说的),但不应该搞那么多可编程器件,维护那么多份不同类型的代码,容易出bug,使用FTDI的usb转FIFO多好,无需编程,我想该项目应该是micochip公司有份出钱搞的,看PhyWhisperer-USB官网介绍就知道了(PhyWhisperer-USB is part of the Microchip Get Launched 2019 design competition!),肯定尽量用多点micochip的芯片(另外usb PHY也是他家的产品)才能申请到钱,有钱才有动力,作为中国人,你懂的。综上,PhyWhisperer-USB对比先驱OpenVizsla,还没有完全成熟,各位创客/极客们可以先观望一段时间再动手制作,有能力者也可以参与开发,在github上提交push请求,或者修改Altium Designer工程,修改PCB和代码以适应自己的需求,毕竟它是完全开源的,可以任意修改!

        以上3款硬件USB抓包工具均支持硬件级别的条件触发,譬如选择只捕捉某个地址的端点、只看IN+ACK,过滤掉OUT+NAK等等。

        FPGA均使用“从串配置”的配置模式,优点是方便随时升级fpga固件、省掉一个spi nor flash,具体可参考Xilinx官网的UG470等文档。其工作原理是“微控制器MCU/FTDI等芯片利用SPI总线或并行总线将配置文件传到FPGA后加载,MCU先主动拉低PROGRAM_B(CS#)管脚以启动配置,然后轮询FPGA的INIT_B管脚电平,当它为高电平时代表FPGA准备好了,此时MCU提供SPI时钟(CLK)和数据(MOSI)直至FPGA配置完毕,当FPGA的DONE管脚被拉高就代表FPGA加载成功。但如果INIT_B被拉低或DONE一直为低电平则代表配置失败,需重试,如果重试多次均失败就需要排查问题了”,参考电路图如下,其中箭头代表信号的传输方向:

为了对比几种开源的usb分析仪,盗用PhyWhisperer-USB的图:

        正如我开头所说,USB协议分析仪终究是小众产品,这导致了商业抓包工具非常昂贵,譬如国外的Beagle 480、USB Explorer 200等,国内的,要点名批评沁恒科技的usb2.0分析仪,自己软件做得不好没关系,还不开放API接口让我们二次开发分析软件,也不能输出wireshark能分析的文档格式,不过它硬件做得也还行,也是支持触发源输入的。所以对于我们调试USB设备的朋友来说,拥有一台自己的USB抓包仪真是如虎添翼,上述三款开源的usb抓包工具你值得拥有,感兴趣的同学赶紧去打板、去github下载代码编译吧!

        最后,很感慨我们国内的开发者不如国外的,这里我说的不是技术这一层面,而是指那一份开源精神,那一份热情!

 

发布了105 篇原创文章 · 获赞 62 · 访问量 35万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章