USB与HID外设流量
USB与HID外设流量
本文适合
已经理解 流量包基础 和 文件头、文件尾与真实类型 的 Misc 学习者。学完你能:识别 USB/HID 抓包,导出键盘或鼠标数据,用脚本还原输入内容、鼠标轨迹或隐藏图形
一句话判断
题目给 pcap、pcapng、usbmon、USBPcap 或 Wireshark 里大量 URB_INTERRUPT in 数据,而且没有正常 TCP/HTTP 会话时,就要考虑 USB/HID 外设流量。
CTF 中最常见的是键盘流量还原输入内容,其次是鼠标流量还原轨迹。
题目中常见信号
文件来源:
usbmon
USBPcap
Wireshark USB capture
keyboard.pcapng
mouse.pcapngWireshark 过滤器:
usb
usbhid
usb.transfer_type == 0x01
usb.capdata典型现象:
- 数据包很多,但没有 IP、TCP、HTTP。
Leftover Capture Data长度固定。- 键盘 HID 报文常见长度为 8 字节。
- 鼠标报文常见长度为 4 字节或更多。
usb.src、usb.dst、endpoint 方向固定。
核心概念
HID 是 Human Interface Device,常见设备包括:
- 键盘。
- 鼠标。
- 手柄。
- 触控板。
- 条码枪。
键盘常见报告格式:
[modifier][reserved][key1][key2][key3][key4][key5][key6]modifier 表示 Shift、Ctrl、Alt 等修饰键,key1 到 key6 表示同时按下的键码。
鼠标常见报告格式:
[buttons][dx][dy][wheel]dx、dy 是相对位移。还原轨迹时要把每个包的位移累加成坐标点。
关键点:HID 报文记录的是按下和释放,不是“字符流”。还原时必须去重、处理 Shift、Backspace 和键盘布局。
最小分析流程
1. 确认是不是 USB/HID
先看协议统计:
tshark -r capture.pcapng -q -z io,phs如果主要协议是 USB、USBHID,继续用 USB 思路。
2. 找含数据的字段
常用导出:
tshark -r capture.pcapng -Y "usb.capdata" -T fields -e usb.capdata如果没有输出,在 Wireshark 里点开数据包,确认字段名可能是:
usb.capdata
usbhid.data
Leftover Capture Data3. 判断键盘还是鼠标
看每条数据长度:
00:00:0b:00:00:00:00:00 -> 8 字节,常见键盘
01:03:fe:00 -> 4 字节,常见鼠标也可以看设备描述符、interface class 或包中是否有 HID usage。
4. 解析并验证
键盘:
- 过滤全 0 释放包。
- 映射 keycode。
- 处理 Shift。
- 处理 Backspace、Enter。
- 检查输出是否像 flag、URL、命令或口令。
鼠标:
- 解析
dx、dy。 - 有符号转换。
- 累加坐标。
- 画散点或线段。
- 检查是否出现字母、二维码、图案。
最小验证示例
导出键盘数据
tshark -r keyboard.pcapng -Y "usb.capdata" -T fields -e usb.capdata > keys.txtkeys.txt 中看到:
00:00:0b:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:09:00:00:00:00:00最小解析骨架:
keymap = {
0x04: ("a", "A"), 0x05: ("b", "B"), 0x06: ("c", "C"),
0x09: ("f", "F"), 0x0b: ("h", "H"),
0x28: ("\n", "\n"), 0x2a: ("<BACKSPACE>", "<BACKSPACE>"),
}
out = []
last = None
for line in open("keys.txt", encoding="utf-8"):
raw = bytes.fromhex(line.strip().replace(":", ""))
if raw == b"\x00" * len(raw):
last = None
continue
if raw == last:
continue
last = raw
shift = raw[0] in (0x02, 0x20) or (raw[0] & 0x22) != 0
code = raw[2]
ch = keymap.get(code, ("", ""))[1 if shift else 0]
if ch == "<BACKSPACE>":
if out:
out.pop()
else:
out.append(ch)
print("".join(out))验证标准:输出能解释题目行为,并且重复运行结果稳定。
画鼠标轨迹
points = []
x = y = 0
for line in open("mouse.txt", encoding="utf-8"):
b = bytes.fromhex(line.strip().replace(":", ""))
dx = int.from_bytes(b[1:2], "little", signed=True)
dy = int.from_bytes(b[2:3], "little", signed=True)
x += dx
y -= dy
points.append((x, y))
print(points[:10])之后用 matplotlib 画图,或导出坐标到表格查看。
常见利用 / 解题路线
路线总览:
路线一:键盘输入还原
适合:
- 8 字节 HID 报文。
- 出现大量按下/释放事件。
- 题目暗示输入密码、flag、命令。
步骤:
- 导出
usb.capdata。 - 过滤释放包和重复包。
- keycode 映射成字符。
- 处理 Shift 和 Backspace。
- 输出候选 flag。
路线二:鼠标轨迹还原
适合:
- 4 字节鼠标报文。
dx/dy连续变化。- 题目暗示手写、绘图、轨迹。
步骤:
- 导出鼠标数据。
- 把位移解释为有符号整数。
- 累加坐标。
- 画图。
- 翻转 Y 轴、缩放或去噪。
路线三:条码枪或特殊 HID
条码枪常表现得像键盘,会快速输入一串字符并回车。
步骤和键盘类似,但要注意:
- 输入速度很快。
- 可能只有数字或大写。
- 末尾常有 Enter。
路线四:多设备混合
如果抓包里同时有键盘和鼠标,要按 endpoint 或设备地址分开导出:
tshark -r capture.pcapng -Y "usb.addr == 1.3.1 && usb.capdata" -T fields -e usb.capdata具体 usb.addr 以 Wireshark 显示为准。
常见失败原因
- 把 USB 当普通网络流量:一直搜 HTTP、flag,忽略 HID 字段。
- 字段名不一致:不同 Wireshark/tshark 版本字段可能不同,需要手动点包确认。
- 没有过滤释放包:全 0 报文会导致重复或空字符。
- 没有处理 Shift:
{}、_、大写字母和符号都会错。 - 没有处理 Backspace:输出里残留被删掉的字符。
- 鼠标位移无符号解析:负位移被当成 255,图形会飞掉。
- 键盘布局不同:默认美式键盘不一定适合所有题。
迷你案例
题目给:
keyboard.pcapngWireshark 里过滤:
usb.capdata看到大量 8 字节数据:
00:00:09:00:00:00:00:00
00:00:0f:00:00:00:00:00
00:00:04:00:00:00:00:00
00:00:0a:00:00:00:00:00导出:
tshark -r keyboard.pcapng -Y "usb.capdata" -T fields -e usb.capdata > keys.txt脚本解析后得到:
flag{hid_input_replay}WP 中要写明证据链:
协议统计显示 USB/HID
usb.capdata 为 8 字节键盘报告
过滤释放包后按 HID keycode 映射
处理 Shift 和 Backspace
得到 flag{hid_input_replay}这样读者能复现,而不是只看到最终字符串。