当前位置: 首页 > 科技观察

USBFuzzing基础知识:从漏洞挖掘到漏洞报告

时间:2023-03-12 20:19:01 科技观察

最近,我开始使用基于Facedancer的工具来查找USB主机堆栈中的漏洞。本文首先介绍了我的模糊测试方法,然后给出了一个完整更新的Windows8.1x64中漏洞的实际示例。本文的目的不是重新定义USBFuzzing测试,也不是完整描述我的Fuzzing测试架构,而是描述从Fuzzing测试到漏洞报告的完整步骤。0x01Fuzzingmethod我的fuzzing结构基于Facedancer和Umap工具,并添加了一些功能:捕获模拟设备PCAP中的流量;从记录的PCAP重放流量;基于Radamsa的数据包突变。0x02USBBasics本文的目的不是详细描述USB是如何工作的,但仍然需要一些知识才能更好地理解USBFuzzing。连接设备时,主机向设备发出标准请求以检索有关设备的信息(供应商ID、产品ID、可用功能等),以便配置它并将适当的驱动程序加载到操作系统中在中,此信息称为描述符。这些请求/描述符在特殊端点上交换:每个连接的新标准设备都必须响应发送给它的请求。端点是设备接口和USB主机堆栈之间的逻辑链接,接口由一个或多个端点组成,并提供类功能(HID、大容量存储等)或特定功能。0x03模糊测试示例我模拟了一个USB大容量存储设备并丢弃了交换的流量,然后,我决定对配置描述符进行模糊测试,尤其是bNumEndpoints字段。变异只是用一个随机的字节替换这个字节。一段时间后,我在Windows8.1x64上触发了BSOD。在这里,我的突变描述符以红色框的形式发送到主机。在使用变异的描述符重播数据包序列几次后,我推测主机在发送橙色框中的设置配置请求后立即触发了BSOD。在Wireshark中,变异的描述符如下所示:崩溃转储分析几乎没有用,因为内核池内存已损坏:每次崩溃都在另一个位置。我继续注入数据包,有时WindowsBSOD给了我以下问题位置:USBSTOR.sys。驱动程序名称是明确的:它是大容量存储驱动程序。0x04反转大容量存储驱动程序下载USBSTOR.sys的符号后,我将其加载到IDAPro中。幸运的是,这些符号很容易理解,我很快就找到了有趣的函数:USBSTOR_SelectConfiguration()基本块显示了对usbd.sys导出的调用:USBD_CreateConfigurationRequestEx(),它返回指向URB_FUNCTION_SELECT_CONFIGURATION结构的指针。根据MSDN[6],此“例程分配并格式化URB以选择USB设备的配置”。URB是客户端驱动程序用来描述它想要发送到设备的请求的结构[7]。第二个基本块以先前创建的URB作为第一个参数调用USBSTOR_SyncSendUsbRequest()。调用此函数后,请求通过USB堆栈发送,然后从主机控制器物理发送到设备。如果我中断USBSTOR_SyncSendUsbRequest()调用,我发现并不是这个调用导致系统崩溃。在USBD_CreateConfigurationRequestEx()函数中,我看到它基于USBD_INTERFACE_INFORMATION结构从USB_INTERFACE_DESCRIPTOR结构的NumberOfPipes复制bNumEndpoints(我将其设置为0用于模糊测试空间)。USB_INTERFACE_DESCRIPTOR枚举过程结构初始化,本文不做研究。现在,在调用USBD_CreateConfigurationRequestEx()之后,我回到USBSTOR.sys,RDI指向:struct_URB_SELECT_CONFIGURATION{structURB_HEADERHdr;PUSB_CONFIGURATION_DESCRIPTORConfigurationDescriptor;USBD_CONFIGURATION_HANDLEConfigurationHandle;USBD_INTERFACE_INFORMATIONInterface;};R14指向:USHORTLength;UCHARInterfaceNumber;UCHARAlternateSetting;UCHARClass;UCHARSubClass;UCHARProtocol;UCHARReserved;USBD_INTERFACE_HANDLEInterfaceHandle;ULONGNumberOfPipes;//OurbNumEndpoints=0ishere!USBD_PIPE_INFORMATIONPipes[1];}USBD_INTERFACE_INFORMATION,*PUSBD_INTERFACE_INFORMATION;[objectObject]现在,将_USBD_INTERFACE_INFORMATION结构复制到RCX,我将此指针放回RAX。这些指令的伪代码是:ECX<-endpointnumberIfthenumberofendpointiszeroECX<-ECX-1ECX<-0-1=0xffffffffR8(0xffffffff*3*8)+80memset(@dest,0x0,R8)memset(@dest,0x0,0x1800000038)in在这里,有一个大小等于0x1800000038的memset,导致无法利用的内核池溢出。Windows8.132位我看到在64位模式下发生了什么,但在32位模式下没有。我不会详细介绍指令流程,因为它完全相同。以下代码段对应于前面代码段的32位等效代码:在伪代码中,memset()的大小如下:EAX<-endpointnumberIfthenumberofendpointiszeroEAX<-EAX-1EAX<-0-1=0xffffffffEAX(0xffffffff*0x14)+0x38=0x24memset(@dest,0x0,EAX)memset(@dest,0x0,0x24)这里由于结构体中指针的大小不同,所以大小计算也不同。因为EAX只有32位长,结果0x1400000024放不下,所以存储0x00000024。_URB_SELECT_CONFIGURATION的大小为0x38字节,因此分配的结构中有20个字节未初始化,如果紧随其后的分配空间未被memcpy()正确填充,则在某些情况下可以利用此漏洞。0x05参考[1]http://goodfet.sourceforge.net/hardware/facedancer21/[2]https://github.com/nccgroup/umap[3]https://code.google.com/p/ouspg/wiki/Radamsa[4]UniversalSerialBusSpecification2.0page250[5]UniversalSerialBusSpecification2.0page260[6]http://msdn.microsoft.com/en-us/library/[7]http://msdn.microsoft.com/en-us/library/windows/hardware/ff538923%28v=vs.85%29.aspx本文翻译自:https://blog.quarkslab.com/usb-fuzzing-basics-from-fuzzing-to-bug-reporting。html转载请注明原文地址: