文章总结: 本文介绍了如何使用USBPcap和Wireshark抓取USB摄像头传输的数据包,并通过Python和Scapy库从抓包数据中提取图像数据的技术方法。文章详细解释了UVC协议中isochronous传输类型的工作原理,特别是如何通过FrameID(FID)来识别和重组一帧完整的图像数据。作者提供了完整的Python代码示例,能够从Wireshark抓包文件中提取MJPEG格式的图像,为USB设备安全分析和数据提取提供了实用方案。
综合评分: 85
文章分类: 安全工具,IoT安全,二进制安全
从 USB 抓包数据中提取 USB 摄像头图像
原创
独钓孤舟雪
MyStackTrace
2025年11月1日 22:56
上一篇文章介绍了如何在 QEMU 中模拟一个支持 Windows Hello 的红外摄像头,后面我打算给这个假的摄像头注入带有人脸的红外图像,想骗过 Windows Hello 的检测机制,这就需要我们尽量注入真实的图像,于是我打算从真实的 USB 摄像头中获取用于实验的图像。
从真实的 USB 摄像头中提取图像方法有很多,比如使用我们上次用的 OpenCV 的方式,或者写一个摄像头驱动的过滤驱动(Filter Driver)去拦截摄像头的图像数据,不过对于 USB 摄像头还有种方法就是抓 USB 包,然后从 USB 数据包中提取图像数据。
我们需要两样工具来进行 USB 抓包:USBPcap 和 Wireshark,把这两个工具装上,我们就可以抓取 USB 摄像头传输的 USB 数据包了。
Wireshark 的使用比较简单,选中 USBPcap2,然后点击 start capturing packets 按钮就开始抓包了,这个时候电脑上有任何 USB 传输都会被 Wireshark (USBPcap) 记录下来。接下来我们启动 USB 摄像头,Wireshark 就能记录下来 USB 摄像头传输的数据,其中就包括了图像数据。等个几秒关掉摄像头,在 Wireshark 中停止抓包,保存抓包文件为 camera.pcapng。
我们可以在 Wireshark 中查看抓到的 USB 数据包,我的 USB 摄像头传输图像数据使用的是 isochronous 类型的 USB 传输,因此所有的图像数据都包含在 isochronous 类型的 USB 数据包中,我们要做的就是从这些 USB 数据包中提取出图像数据。
一个 isochronous 类型的 USB 数据包中包含了若干个 isochronous packet,对于 USB 摄像头来说这每个 packet 中都包含了一份 UVC Payload (USB Video Class Payload),每个 UVC Payload 都有 Payload header 和 Payload data。
UVC Payload header 中是元数据,包括这个 Payload header 的长度,标识这个 Payload 属于哪一帧的 Frame ID (FID),这一帧图像生成时的时间戳等。UVC Payload data 中是 USB 摄像头产生的图像数据,通常一帧图像数据会被分成多个 USB 数据包进行传输,所以我们需要把一帧图像对应的 所有的 UVC Payload data 中的数据拼接起来才能得到这一帧图像的所有数据。
如何判断一帧图像由哪些 UVC Payload data 组成的呢?这就是 UVC Payload header 中的那个 Frame ID (FID) 的作用了,这个 FID 只有一个位,USB 摄像头设备每传输完一帧图像数据之后,就会把这个 FID 翻转一次(0->1,1->0),因此每当我们看到 UVC Payload header 中的 FID 翻转了,就意味着上一帧图像数据传完了,下一帧图像数据即将开始,两次 FID 翻转之间的 UVC Payload data 就组成了一帧完整的图像。其实在 UVC Payload header 中还有个一个 End of Frame 的位能够用来标识一帧图像的最后一个 UVC Payload,不过这个位很多 USB 摄像头都不支持,因此我们根据 FID 来收集一帧图像所有的 UVC Payload 是更加保险的。
知道了如何提取 USB 数据包中的图像数据之后,下面我们就借助万能的 Python 写一个程序从 Wireshark (USBPcap) 的抓包数据中提取出每一帧图像数据。我们需要借助 Scapy,这是一个强大的 Python 库, 它的强大之处通常在于网络抓包方面,不过这里我们要用它来解析 USBPcap 格式的抓包文件。下面是完整的 Python 程序,该程序通过 Scapy 提供的 API 加载我们之前抓到的 camera.pcapng 文件并且对齐进行解析,然后我们从中提取 USB 数据包,进而按照 UVC 协议中规定的 UVC Payload 的格式从中提取图像数据。我的 USB 摄像头输出图像格式为 MJPEG,所以在代码中我就把图像保存成后缀为 .jpg 的文件。
运行这个 Python 程序,就能够把抓到的 USB 数据包中包含的每帧图像都提取出来。下面是提取出来的一部分 jpg 图片。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:MyStackTrace 独钓孤舟雪《从 USB 抓包数据中提取 USB 摄像头图像》