逆向分析实战:用usbmon解码USB HID设备(如键盘/鼠标)的原始数据包
2026/6/3 5:46:02 网站建设 项目流程

逆向工程实战:用usbmon解码USB键盘的原始通信数据

当你的手指在键盘上敲击时,一组神秘的十六进制代码正在USB总线上飞驰。这些看似随机的数字背后,隐藏着从物理按键到操作系统事件的完整转化链条。本文将带你深入USB HID协议的底层,使用Linux内核内置的usbmon工具,捕获并解析键盘每一次击键产生的原始数据包。

1. 搭建USB数据捕获环境

1.1 内核模块准备

现代Linux发行版通常已内置usbmon支持,首先验证内核模块状态:

ls /sys/module/usbmon

若目录不存在,需加载模块:

sudo modprobe usbmon

debugfs是usbmon的依赖文件系统,检查挂载状态:

mount | grep debugfs

未挂载时执行:

sudo mount -t debugfs none /sys/kernel/debug

1.2 设备总线定位

使用lsusb定位目标设备所在总线:

lsusb -v | grep -A5 "Keyboard"

典型输出示例:

Bus 003 Device 002: ID 046d:c31c Logitech USB Keyboard

这里003即为总线编号,记下设备地址002用于后续过滤。

2. 捕获键盘原始数据流

2.1 实时监控数据包

针对特定总线启动监控(以总线3为例):

sudo cat /sys/kernel/debug/usb/usbmon/3u > keyboard_capture.log

按下几个按键后Ctrl+C终止捕获,得到原始数据样本:

ffff8a1b12a8d400 1638297565 S Ci:3:002:0 s a1 01 0000 0001 0008 8 < ffff8a1b12a8d400 1638297567 C Ci:3:002:0 0 8 = 0000000000000000 ffff8a1b12a8d400 1638298512 S Ci:3:002:0 s a1 01 0000 0001 0008 8 < ffff8a1b12a8d400 1638298514 C Ci:3:002:0 0 8 = 0000040000000000

2.2 数据包结构解析

usbmon输出的关键字段说明:

字段位置示例值含义
1ffff8a1b12a8d400URB唯一标识符(内核地址)
3Ci控制输入传输(Control Input)
43:002:0总线:设备:端点号
78 <数据长度8字节,方向为设备到主机
9= 00000400...实际传输的HID报告数据

3. HID报告描述符解码

3.1 报告描述符获取

USB HID设备通过描述符定义数据格式,获取键盘描述符:

sudo lsusb -v -d 046d:c31c | grep -A50 "HID Device Descriptor"

关键输出片段:

HID Device Descriptor: bLength 9 bDescriptorType 33 bCountryCode 0 bNumDescriptors 1 bDescriptorType 34 wDescriptorLength 65 Report Descriptor: (length is 65) Item(Global): Usage Page, data= [ 0x01 ] 1 Generic Desktop Controls Item(Local): Usage, data= [ 0x06 ] 6 Keyboard Item(Main): Collection, data= [ 0x01 ] 1 Application

3.2 按键码映射表

标准USB HID键盘的键码对应关系(部分):

十六进制十进制按键
0x044A/a
0x055B/b
0x066C/c
0x077D/d
0x1A26[/ {
0x1B27]/ }
0x2840Enter
0x2941Escape

4. 实战数据包分析

4.1 单按键按下事件

捕获到的数据样本:

ffff8a1b12a8d400 1638298514 C Ci:3:002:0 0 8 = 0000040000000000

解析步骤:

  1. 数据部分0000040000000000按字节分组:00 00 04 00 00 00 00 00
  2. 第1字节00:修饰键状态(Shift/Ctrl/Alt等)
  3. 第3字节04:对应键码表可知是字母A
  4. 其余字节00:保留位或同时按下的其他键

4.2 组合键事件分析

Shift+A组合击键的典型数据:

ffff8a1b12a8d400 1638301123 C Ci:3:002:0 0 8 = 0200040000000000

关键区别:

  • 第1字节变为02:左Shift键的修饰位标志
  • 第3字节仍为04:物理A键的扫描码

4.3 数据包时序分析

连续击键的时间戳差值计算:

timestamp1 = 1638297565 timestamp2 = 1638298512 delta_ms = (timestamp2 - timestamp1) / 1000 print(f"按键间隔:{delta_ms:.1f}毫秒")

输出示例:

按键间隔:946.7毫秒

5. 高级分析技巧

5.1 使用Python解析数据

自动化解析脚本示例:

import re def parse_usbmon(line): pattern = r'.* C Ci:\d+:\d+:\d+ \d+ \d+ = ([0-9a-f]+)' match = re.match(pattern, line) if match: return bytes.fromhex(match.group(1)) return None sample = "ffff8a1b12a8d400 1638298514 C Ci:3:002:0 0 8 = 0000040000000000" print(parse_usbmon(sample)) # 输出:b'\x00\x00\x04\x00\x00\x00\x00\x00'

5.2 Wireshark联合分析

  1. 将usbmon输出转换为pcapng格式:
text2pcap -T 147,147 keyboard_capture.log keyboard.pcap
  1. 在Wireshark中应用USB HID解析器:
右键数据包 → Decode As → USBHID

5.3 异常数据诊断

常见问题数据模式及含义:

数据模式可能原因
0000000000000000按键释放事件
FF00FF0000000000全键按下(防鬼跳测试)
0100000000000000左Ctrl键按下
持续相同非零数据按键卡住或硬件故障

在虚拟机环境中测试时,可能会观察到额外的控制传输数据包,这是虚拟化层与主机通信的正常现象。实际物理键盘的数据流通常更简洁,主要集中在中断传输端点上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询