参考文章
https://github.com/AngelKitty/UsbKeyboardDataHacker
https://www.anquanke.com/post/id/85218
https://ludovicrousseau.blogspot.com/2014/10/ccid-usb-spy-using-wireshark.html
环境
Ubuntu 16.0.4 STL
Wireshark
Tshark
文件下载地址
http://shaobaobaoer.cn/cdn/USB-learning.zip

USB 通信协议简介

USB是一种协议总线,即主机与设备之间的通信需要遵循一系列约定。USB接口是目前最为通用的外设接口之一,通过监听该接口的流量,可以得到很多有意思的东西,例如键盘击键,鼠标移动与点击,存储设备的明文传输通信、USB无线网卡网络传输内容。关于USB协议,可以参考 usb.org。文后也有 usb 协议的PDF文件,内容相当复杂。从USB的制作规范到通信协议无所不全。在此只是管中窥豹。玩一玩 USB 流量分析

利用 wireshark 可以监听USB流量。当然也可以使用 wireshark 的命令行工具 Tshark

准备工作

加载 usbmon 内核

sudo modprobe usbmon

tshark 查看所有可以抓取流量的端口

root@shaobao-Precision-3510:/root# tshark -D
Running as user "root" and group "root". This could be dangerous.
1. wlp2s0
2. vmnet1
3. vmnet8
4. any
5. lo (Loopback)
6. enp0s31f6
7. nflog
8. nfqueue
9. usbmon1
10. usbmon2
11. cisco (Cisco remote capture)
12. randpkt (Random packet generator)
13. ssh (SSH remote capture)

查看USB端口情况

root@shaobao-Precision-3510:/root# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 1a2c:0c21 China Resource Semico Co., Ltd # 这个是我的键盘 其USB 地址为 1.5.1
Bus 001 Device 003: ID 1bcf:2b91 Sunplus Innovation Technology Inc. 
Bus 001 Device 006: ID 1c4f:0034 SiGma Micro # 这个是我的鼠标 其USB 地址为 1.6.1
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

监听USB流量

tshark -i usbmon1 -w trace1.pcap

之后会在屏幕上发现有数字在跳,按下ctrl-c捕获结束
我录制了两个流量包,分别是

  • trace2.pcap
    • 鼠标 流量
  • trace3.pcap
    • 键盘 流量

分析 USB 键盘流量

trace3.pcap

利用过滤器 , 可以找到所有我们键盘发出的流量。

usb.src == "1.5.1"
USB 数据包分析-ShaoBaoBaoEr's Blog
  • wireshark 的过滤规则,是将所有能够解析的数据展示出来,而最后没有能够解析的数据将命名为 Leftover Capture Data
  • 大概分析一下,不难发现有 Leftover Capture Data 这个数据。这就有点像是 HTTP 的 POST 请求中的请求内容。比如类似下面这样
  • Leftover Capture Data: 00 00 4c 00 00 00 00 00
  • 我们发现键盘的请求包 是 8个 字节 当然有很多是 00 的填充字

在USB协议的pdf 文档中搜索 keyboard。不难发现这个表(P53页),实际上这就定义了ABCD等的相关输入标准。和ASCII码并不太一样。

USB 数据包分析-ShaoBaoBaoEr's Blog
tshark -r trace3.pcap -T fields -e usb.capdata > trace3data.txt

利用该命令提取出那些数据。并保存。根据协议的内容,我们将该文件进行二次解码

mappings = { 0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";",  0x34:"'", 0x36:",",  0x37:"." }
nums = []
keys = open('usbdata.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
         continue
    nums.append(int(line[6:8],16))
keys.close()
output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'
print 'output :n' + output

最后,运行脚本,可以得到内容如下

sudo python trace3_decode.py 
output :n[DEL]MKDIR SHAOBAOBAOER.SH[unknown][unknown][unknown][unknown][unknown][unknown]VIM n[unknown]SQLMAP -U 'HTTP[DEL][unknown][unknown]SHAOBAOBAOER.CN[unknown]ADMIN[unknown] -P ACCOUNT --THREAD 9 --RISK 3 --LEVEL 3 --DBS [unknown]WQnEXITn

好吧,这是我输入的,用SQLMAP注入我wordpress博客后台的小脚本,这里 shaobaobaoer.sh 后面的[uk]的内容应该是我按住del键没有放下。可能这个没有写在上面的小脚本里面。VIM 后那个 UK应该是 insert键。还有几个应该是 反斜 也没有识别出来。

后来我尝试了下github上的那个小工具,结果并不是很理想,再次就不多说了。

真题分析

文件下载地址
kaizen-ctf 2018-Forensics-Capture_of_all_interfaces

拿到流量包,定位到USB流量

usb.addr == "2.6.1" and usb.dst == "host"

将当前流量导出为 extract.pcapng,利用tshark提取

$ tshark -r extract.pcapng -T fields -e usb.capdata > extract.data

用上面的小脚本跑一下,即可拿到键盘输入数据

$ python exp.py 
output :nHHEERREE  IISS  YYOOUURR  FFLLAAGG  EEAATTTTHHAATTFFRROOGG

分析 USB 鼠标流量

MouseTrace.pacp

USB 的鼠标流量和键盘流量有所不同,我大概看了下每个USB数据请求包的时间差,相差大概在 0.008 S 以下。
实际上USB文章中规定

通常初始化鼠标以产生特定速率的移动包。如果移动鼠标,默认速率为每秒100个数据包。如果按下或释放按钮,鼠标也会生成数据包。如果鼠标没有移动且没有单击按钮,则鼠标不会生成任何自动数据包。

鼠标的位置是离散的,但是将这些时间戳加起来就看似是个直线了。

>>> 3.752525 - 3.744619
0.007905999999999747
>>> 3.760502 - 3.752525 
0.0079769999999999

USB 数据包分析-ShaoBaoBaoEr's Blog
备注,这个流量包录制得太普通了我后来又重新录制了一个,请忽视这个source

和键盘的流量不太一样,鼠标的请求内容只有 4 个字节
Leftover Capture Data: 00 fd f5 00

具体规则如下所示:

  • 第一个字节为按键,末位中,1代表左键,2代表右键。前面几位是标志位,当发生溢出或者其他状况的时候,这个字节的前几位。
  • 第二个字节为左右偏移,是一个有符号数,正的时候代表水平左移多少像素,负的时候代表水平右移多少像素
  • 第三个字节未上下偏移,是一个有符号数,正的时候代表上移多少像素,负的时候代表下移多少像素
  • 第四个字节是扩展字节,当鼠标有滚轮的时候才会被激活,wikipedia告诉我它是这么定义的。
    • 0 - 没有滚轮运动
    • 1 - 垂直向上滚动一下
    • 0xFF - 垂直向下滚动一下
    • 2 - 水平滚动右键一次
    • 0xFE - 水平滚动左键单击一下

对此,利用下述脚本,将收集好的数据放到MouseTrackExtract.txt

nums = []
keys = open('MouseTrace.txt','r')
posx = 0
posy = 0
for line in keys:
    if len(line) != 12 :
         continue
    x = int(line[3:5],16)
    y = int(line[6:8],16)
    if x > 127 :
        x -= 256
    if y > 127 :
        y -= 256
    posx += x
    posy += y
    btn_flag = int(line[0:2],16)  # 1 for left , 2 for right , 0 for nothing; 这里抓取了为1的数据
    if btn_flag == 1 :
        print posx , posy
keys.close()

最后,利用gnuplot把它画出来。当然,也可以用MATLAB

$ gnuplot
$ >>  plot "MouseTraceInput.txt"

我摁住鼠标左键写个SH,不过效果好像并不是很好。

USB 数据包分析-ShaoBaoBaoEr's Blog

分析 USB 文件交换流量

FileTrace

很遗憾,我并没有找到能够从USB流量角度来分析USB协议的好文章。我只能通过一些实例来找出如何提取USB流量的。
我准备了一张图片来完成演示 USB 文件交换。如图所示,其实USB的文件交换似乎是不加密的,也就让我能够很方便的找到文件的位置。但是这个协议是如何运作的,那些固定字节的包又是在做什么,目前我还解释不来。

USB 数据包分析-ShaoBaoBaoEr's Blog

直接将上述内容提取,就可以找到我传输的文件。这样的道理还可以用在其他传输内容中。将文件导出字节流,就是原文件。但是文件的名称在哪里?我通过过滤器找了很多次都没有找到。如果有比较好的文章推荐的话还请在文后给我评论。

实战分析 AlexCTF2017-USBprobing

利用如下过滤器,找到文件交换流量

usb.addr == "host" and usb.dst == "3.3.2" and usb.data_len > 100

挨个儿数据包看过去,不难发现有一个PNG的图片,将它直接右击导出

USB 数据包分析-ShaoBaoBaoEr's Blog

就是FLAG

USB 数据包分析-ShaoBaoBaoEr's Blog