UAC虚拟麦克风同步传输数据结构与BUSHOUND抓包URB的对比
昨天晚上在家又在卷。。。
在Windows系统下虚拟的UAC麦克风,这是一个自己很熟练的事情了,不过自己为了再次优化一些代码,也在疯狂的试探某些数据的底线在那里,所以卷的结果就是使用BUSHOUND抓了个包。
UAC设备是USB的音视设备分类,所以我们看到的USB麦克风、扬声器(耳机)之类的,都符合UAC规范,当然也是基于USB规范的。
UAC规范定义了UAC设备的数据传输方式为USB同步传输方式,其在Windows驱动中表现为IRP的IO_STACK_LOCATION成员Parameters.Others.Argument1对应的URB,该URB支持USB的各种数据传输方式,包括同步传输数据方式。
PURB GetUrb(PIRP Irp)
{
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
PURB Urb = (PURB)IoStack->Parameters.Others.Argument1;
return Urb;
}
USB的同步传输方式相对于其它传输方式如中断传输、批量传输或者控制传输,其数据结构相对复杂一些,但是在数据处理上,也就更麻烦了一些。
URB同步方式的数据结构如下:
typedef LONG USBD_STATUS;
typedef PVOID PMDL;
typedef PVOID USBD_PIPE_HANDLE;
struct _URB_HEADER {
USHORT Length;
USHORT Function;
USBD_STATUS Status;
PVOID UsbdDeviceHandle; // Reserved
ULONG UsbdFlags; // Reserved
ULONG reversed; // Reserved
};
struct _URB_HCD_AREA {
PVOID Reserved[8];
};
typedef struct _USBD_ISO_PACKET_DESCRIPTOR {
ULONG Offset;
ULONG Length;
USBD_STATUS Status;
} USBD_ISO_PACKET_DESCRIPTOR;
struct _URB_ISOCH_TRANSFER {
struct _URB_HEADER Hdr;
PVOID PipeHandle;
ULONG TransferFlags;
ULONG TransferBufferLength;
PVOID TransferBuffer;
PVOID TransferBufferMDL;
PVOID *UrbLink; // Reserved
struct _URB_HCD_AREA hca; // Reserved
ULONG StartFrame;
ULONG NumberOfPackets;
ULONG ErrorCount;
_USBD_ISO_PACKET_DESCRIPTOR IsoPacket[10];
};
对于一组十六进制,我们可以通过本站的一个在线分析工具来进行数据分析,详见https://www.usbzh.com/tool/urb-iso.html
本人昨晚通过bushound抓取的UAC麦克风数据包如下:
38.1 1764 ISOC c8 07 c1 11 03 07 14 0e e7 07 b2 0c 57 09 fd 0b 54 09 fc 0a ec 07 10 0b da 05 37 0c af 03 de 0c
后续还有很多,这里省略
而对应的URB如下:
38.1 URB 10 01 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 01 01 00 00 00 00 00 ISOC TRANSFER
05 00 00 00 e4 06 00 00 10 91 ae 03 02 80 ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0 3f 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00
00 00 00 00 80 01 00 00 00 00 00 00 00 00 00 00 40 02 00 00 00 00 00 00 00 00 00 00 00 03 00 00
00 00 00 00 00 00 00 00 c0 03 00 00 00 00 00 00 00 00 00 00 80 04 00 00 00 00 00 00 00 00 00 00
40 05 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 c0 06 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
不过在实际测试的时候,发现音频控制面板中的虚拟出来的麦克风并没有能量波动,使用audacity-win这类软件在录制该麦克风的数据时,竟录一到任何数据。
所以这和BUSHOUND上显示的不一致,因为我从上面BUSHOUND上面来看,是有数据的,且是连续的。
那么只有一种情况就是数据可能被系统判为无效,不过BUSHOUND上确实显示了每包1764个字节,这和我们2通道16位44100的采样率是一致的。而且由于我们的麦克风传输的是PCM数据,所以也不存在数据实校验等问题,这1764就真实的PCM数据。
那问题出在哪里呢?
BUSHOUND作为第三方工具并且搞了这么久的工具,在我们不潜意识里应该是没有问题的。但是在Window系统层面来讲,确实没有数据,所以依操作系统的角度来讲,bushound是有问题的。
既然数据没有问题,那么就是其返回的数据的参数问题了,我们把焦点放在了USB的同步传输URB中,通过我们的工具分析其URB数据如下:
_URB_ISOCH_TRANSFER
_URB_HEADER Hdr
USHORT Length 10 01
USHORT Function 0A 00
USBD_STATUS Status 00 00 00 00
PVOID UsbdDeviceHandle 00 00 00 00 00 00 00 00
ULONG UsbdFlags 00 00 00 00
ULONG reversed 00 00 00 00
PVOID PipeHandle 81 01 01 00 00 00 00 00
ULONG TransferFlags 05 00 00 00
ULONG TransferBufferLength E4 06 00 00
PVOID TransferBuffer 10 91 AE 03 02 80 FF FF
PVOID TransferBufferMDL 00 00 00 00 00 00 00 00
PVOID UrbLink* 00 00 00 00 00 00 00 00
_URB_HCD_AREA hca
PVOID Reserved[8]
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ULONG StartFrame C0 3F 00 00
ULONG NumberOfPackets 0A 00 00 00
ULONG ErrorCount 00 00 00 00
_USBD_ISO_PACKET_DESCRIPTOR IsoPacket[10]
ULONG Offset 00 00 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset C0 00 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 80 01 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 40 02 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 00 03 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset C0 03 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 80 04 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 40 05 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset 00 06 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
ULONG Offset C0 06 00 00
ULONG Length 00 00 00 00
USBD_STATUS Status 00 00 00 00
在通过工具分的的URB中,可以看到:
ULONG TransferBufferLength E4 06 00 00
PVOID TransferBuffer 10 91 AE 03 02 80 FF FF
分别代表了数据传输的长度和内存地址。这里是正确的。因为E4 06 00 00 就是1764,而10 91 AE 03 02 80 FF FF 就是这1764个字节存储的地址。这和BUSHOUND显示的一致,不过实际上是没有获取到数据的,这是因为USBD_ISO_PACKET_DESCRIPTOR因引的,我们看到10个USBD_ISO_PACKET_DESCRIPTOR,其数据长度都为0,所以总的数据长度就是0。所以有效数据就是0。
所以从这里看的出来一个问题,BUSHOUND和体统取的数据位置是一样的,但有效长度是不一样的。一般情况下USBD_ISO_PACKET_DESCRIPTOR中的Length之和就是TransferBufferLength,但我们由于是虚拟的麦克风,没有对这个有效长度设置,出现了二般情况了。