LWN: USB数据采集和分析方案

640
点击上方蓝色“ Linux News搬运工”关注我们~

The USB debugging arsenal

By Jake Edge


ELC NA

圣地亚哥在8月份举行了2019 Embedded Linux Conference North America会议。Krzysztof Opasiak介绍了在Linux系统上如何监控甚至更改USB数据。他首先讲了一些USB协议的基本信息,然后过了一下各种相关的软件硬件方案,讲述如何利用这些来观测、修改、fuzz(模糊化、混淆)这些发送出去的信息。对于USB底层工作机制有兴趣的人建议都需要了解这些工具。

640?wx_fmt=jpeg

Opasiak在波兰供职于韩国三星。他希望能sniff(监测,感知)USB traffic,相关的工具知道的人并不多,不过其实没有什么难的,任何人都可以试试。其实某种意义上来说,USB就像是internet一样,有些工具也是通用的。

USB basics

USB device会对USB host提供一个或者多个服务(例如打印,存储,网络接口,摄像头)。每个device只能对应一个host,不过一个host可以对应多个client device。USB模型里面有个endpoint的概念,有点类似internet的端口号的概念。Device可以有最多31个endpoint,每个都是一个独立的通讯channel。Endpoint zero (ep0)是必须要先打通的,这是唯一一个双向endpoint,其他的要么是IN (从device到host)要么是OUT(从host到device)单向的。

endpoint有四种类型:control, bulk, interrupt, isochronous。control endpoint就是指ep0,这是用来做设备枚举的(enumeration),当然也可以用来做服务所用,不过通常人们不这么用,因为具体USB实现里面会有各种bug。bulk endpoint是用来传输大量数据的,只要这些数据传输对时间不敏感就行,因为bulk类型的数据传输没有预留带宽进行保证。interrupt endpoint类型则会预留贷款,专用于一些需要低延迟的小量数据传输。isochronous endpoint是专用于时间敏感的大量数据传输的,不过并不保证数据一定传输成功,它的原则是宁可丢掉一帧,也要确保数据不会被延迟。

如何能识别这个device提供了哪些endpoint呢?这就是通过ep0上做枚举(enumeration)来得到的了。endpoint再往上还有两个层级,多个endpoint会组成“interface"(接口),多个interface可以组成”configuration“(配置)。对一个设备来说,同一时刻只能选择一个configuration,所以device通常会把多种功能(服务)组合进不同的configuration里去,通过切换configuration来选择各种服务。ep0 control endpoint永远都是可见的,所以可以利用它来让device切换configuration。

USB总线是由host来控制的。host会发起所有数据传输,不会有device-to-device的通讯。在链路层(link layer),host会先发个In token给device,如果device有数据要发送,那这时它就可以发送了。否则的话会发一个NAK,host就会再发送IN token,直到超时。

对OUT endpoint来说,host会发送OUT token,然后送出数据给device。device准备就绪的话就接收数据然后发送ACK,否则就NAK,这样host就会继续发送直到达到超时上限。这种方案对带宽利用来说效率不佳,OUT token本身是8 bit,而数据是500bit左右,所以host还有方法能ping这个设备看它是否可以接收数据了,从而避免不断的重发数据。

这些都是USB底层的transaction了,不过在driver里直接调用这些transaction不是很有效率,其实驱动程序都是按照USB "transfer"层来管理的,每个transfer包含一个或多个transaction。device或者host硬件会按照transaction来实现。

Linux内核提供了一组API给驱动,对各种USB硬件都是统一的API,基于USB request block (URB),实际上是对数据进行了一层封装。这个API是异步调用,会先发起transfer,然后等transfer结束的时候会有个completion函数被调用。因为kernel只看到URB,而不是直接参与链路层的transaction,所以kernel这边的USB sniffing都是监控URB的。

Sniffing USB

首先他介绍了usbmon工具,这是一个kernel内置的log工具,能记录URB相关的event。可以看到URB的提交,完成,以及出错event。不过要注意URB的data buffer只有在特定方向传输里才有效。OUT transfer buffer只有在submit event里有效,而IN transfer buffer则只有在completion event里才有效。

usbmon里输出格式支持二进制文件和文本输出。不过其实还可以使用Wireshark来采集和分析URB event数据。他进行了一个demo,先加载了usbmon kernel module,这样在debugfs下面生成了好几个device,每个device代表了一个USB bus。此外还有一个device是用来采集全部bus的traffic的。他然后又插入了一个USB device,通过kernel log可以看到它连到哪个bus上了。然后用Wireshark来采集了我们关注的这个bus的数据,最后根据device ID过滤了数据,看到了这个新加的设备。

usbmon用起来非常简单,没什么额外开销,不过功能有限制。例如无法看到底层的transaction packet,只能看到URB transfer。此外,还需要能在host这边运行代码来跟device通讯,所以在某些设备上(例如PlayStation)就没法采集USB数据了。

还有一种硬件方案可以解决这个限制。USBProxy是一个运行在single-board computer (SBC)上的代码,可以架设在USB device和USB host之间,所有数据都会经过它。理论上来说任何SBC只要有相应的USB接口,都可以正常工作,不过他只在BeagleBone Black上用特制的kernel成功运行过USBProxy。使用这种方法,攻击者甚至可以利用adb采用man-in-the-middle攻击方式给Android device装上恶意软件。USBProxy对于想要进行USB拦截的人来说不是一个特别容易用的工具,需要不少工作先打通才行。

不少人提出用逻辑分析仪来查看USB数据。这个确实可以做到,不过通常只有在USB low-speed或者full-speed时有用。现在的high-speed signal都是480Mbps速率了,根据香农理论,需要有超过1Ghz的采样率才能抓全,这种规格的逻辑分析仪都不便宜。

Open Vizsla是一个比较便宜的、硬件设计开源的USB分析仪,也是连在host和device之间来用的。它没法做到插入一些USB tranffic,不过确实可以采集各种设备的数据而不被对方察觉到。它内置了一个FPGA,会把采集到的数据写入它内部的RAM上,然后可以走另外一条USB通路传输到PC上去分析。PC侧的分析工具很丰富,例如有一些Python脚本可以展示数据,都在Open Vizsla的GitHub上可以找到。还有一个Virtual USB Analyzer可以查看这些数据,不过Opasiak比较怀疑是否真有人能一直维护这么一个软件项目,仅仅是为了查看USB数据。

还有个很好的选择是他和一位学生添加的Wireshark扩展。可以用来分析所有traffic,实现上是利用了原有的URB解析功能,然后也增加了底层USB transaction的解析功能。这样一来,不需要很昂贵的设备也能轻松采集、分析USB device和host之间的所有数据了。他演示了一下使用Wireshark来从OpenVizsla获取数据然后显示两个设备之间的数据。如果在USB之上运行的协议也有dissector(解析器),例如adb这样,那么所有底层到应用层的协议数据都可以被解析和展示出来。

Fuzzing

接下来他介绍了FaceDancer设备,这是用来对host USB stack协议栈进行fuzz testing的。它有一个Python写的定制过的USB stack,可以运行在host PC上,能把FaceDancer变成一个研究者控制的(或者说是攻击者所控制的)USB设备。利用两个FaceDancer设备,其中一个模拟host,另一个模拟device,就能插入到一个正常的USB host和device的连接中间,就像USBProxy一样。这样就可以直接进行man-in-the-middle对两个方向都进行攻击了。

还有两个硬件方案,分别是GreatFET和GreatFET Rhododendron。GreatFET起初用来hack radio的。这两个方案都可以使用FaceDancer所用的Python stack。

Umap2工具可以配合FaceDancer, GreatFET和其他一些设备来用。Umap2会模拟成各种样子的USB device,然后扫描host确认目前支持哪些类型的USB device,这样就可以利用Kitty framework来进行基本的fuzzing测试。

还有一个fuzzing测试方法完全不需要任何硬件。Linux USB stack本身可以使用syzkaller在使用了dummy_hcd的Linux系统上进行fuzz测试。用这种方法可以让syzkaller生成各种USB traffic以及进行处理,这样来找到USB stack的问题。他提到,还有很多其他工具可以进行各种USB fuzzing测试。

Opasiak总结说,大家可以不用花多少钱就使用各种方法检查USB。OpenVizsla和GreatFET方案都只要花费$100左右。还有各种开源软件和开源硬件方案可用。不过还是具体要看研究者需要做什么来决定采用哪种方案了。没有一个对所有人都适用的完美方案。USB现在到处都在用,包括车载、手机、笔记本等等。因此务必要确保它的功能是正常的。他希望能看到更多的USB测试以及fuzzing的方案。

[I would like to thank LWN's travel sponsor, the Linux Foundation, for funding to travel to San Diego for ELC.]

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议修改再创作~

长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~

640?wx_fmt=jpeg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值