摘要
目标:不需源码,检测Windows内核漏洞。
工具:Digtool功能,监视内核对象分配、内核内存访问、线程调度、函数调用。
结果:在windows驱动和杀软驱动中发现45个0day,包含TOCTTOU、OOB、UAF、UNPROBE。
1.Introduction
(1)相关论文介绍
用户程序检测:DESERVE[29]、Boundless[15]、LBC[21]。
内核程序检测:Kmemcheck[32]、Kmemleak[6]、KEDR[35],依赖内核源码;Driver Verifier[28]—挖掘windows驱动漏洞,需要源码,检测漏洞类型有限。
虚拟化工具:VirtualVAE[18]、PHUKO[38],针对特定类型漏洞;Xenpwn[41](使用Libvmi[34]和Xen),采用EPT扩展页表记录物理地址,不能记录虚拟地址。
(2)贡献
a.实现Digtool,不用触发OS崩溃,可识别多种漏洞并获取内核执行上下文;不需要源码;不依赖已有的虚拟化平台Xen及模拟器bochs。
b.识别4种类型漏洞:UNPROBE/TOCTTOU/UAF/OOB。
c.发现windows和第三方驱动的45个0day。
2.漏洞介绍
UNPROBE:未检测用户指针是否指向用户内存,可能造成无效内存引用、任意内存读、任意内存写。
TOCTTOU:time-of-check-to-time-of-use,类似double-fetch漏洞,多次读取用户内存,第一次用于检查,第二次是使用时用户数据可被篡改。Bochspwn[24]可检测此类漏洞,但模拟器性能低,不能模拟某些真实功能,如显卡驱动。
UAF:释放后重引用。
OOB:越界访问。AddressSanitizer[36]/DriverVerifier[28]可检测此漏洞,但需要源码。
3.Overview
Digtool总体架构见Figure1。窄箭头—调用关系/消息传递;宽箭头—事件触发。
(1)hypervisor组件
功能:监视虚拟内存访问,是接口检测和内存检测的基础。
现有技术:Driver Verifier[28]/AddressSanitizer[36]—内核漏洞检测,需要源码;Pin[27]/DynamoRIO[13]—用户级二进制插桩;QEMU[11]/PEMU[42]—虚拟化工具,性能低;Xenpwn[41]—记录物理地址,不能记录虚拟地址;Bochspwn[24]—性能低;现有hypervisor—Xen/KVM。
技术:提出影子页表SPT,使用硬件虚拟化技术监视虚拟地址空间。
步骤:
a.VMM infrastructure—检测硬件兼容性;初始化hypervisor(构建影子页表SPT监视虚拟内存访问;初始化追踪线程调度的模块;创建内核与hypervisor的通信);加载OS到VM。
b.Interface detection—检查syscall时的参数,监视syscall执行时的用户内存空间需用到SPT。注意不用检查用户模式执行,可只检查部分syscall。
c.Memory detection—检查内核内存的使用,需用到SPT。注意可只监视部分内存的使用,出现memory allocation/deallocation时可动态调整被监视内存(通过service
interface实现)。
(2)内核空间组件
功能:middleware。设置需要监控的内存空间;与Hypervisor交互,连接hypervisor与用户空间;拦截特定内核函数(hook内核函数)。
原理:通讯采用Digtool的service
interfaces提供,内核可向hypervisor请求服务。
步骤:
a.加载阶段向hypervisor传递配置信息(用户定义需要监视哪些syscall),也传递fuzzer进展信息。
b.Interfacedetection—middleware往log文件中记录syscall信息(调用号、事件类型、事件时间、指令地址、访问的内存),便于log analyzer检测UNPROBE/TOCTTOU漏洞。注意可只检测指定syscall。
c.memorydetection—通过hook内核函数来动态调整被监视的内存。注意可以只监视指定内存区域和指定范围的代码。若发现漏洞,则middleware记录并中断guest OS,用Windbg调试获取上下文信息。
(3)用户空间组件
组成:loader/fuzzer/log analyzer。
功能:
loader—激活hypervisor并加载fuzzer,加载目标进程,通过配置文件指定监视的syscall和内存的区域;
fuzzer—负责路径探索,增大代码覆盖;路径上的行为特性记录于Logs;
log analyzer—分析log文件,检测UNPROBE/TOCTTOU漏洞。
4.实现
4.1 VMM Infrastructure
主要任务:初始化 Hypervisor 并将原始 OS 加载到虚拟机中。
初始化流程:
a.Digtool作为驱动被加载到操作系统内核空间中,通过 CPUID 指令检查处理器是否支持硬件虚拟化
b.通过初始化某些数据结构(如VMCS)和寄存器(如CR4)
c.最后,根据原始操作系统的状态设置 Guest OS的状态。
(1)虚拟页监视器
Digtool 使用 SPT 来监控指定线程的虚拟内存访问,未受监视的线程使用 Guest OS的原始页表GPT。Digtool使用稀疏的 BitMap 来跟踪进程空间中的虚拟页。
(2)线程调度监视器
Digtool需要跟踪线程调度来确保只关注受监视的线程。获得:FS–>KPCR–>KPRCB–>CurrentThread。对 CurrentThread 的任何写操作都意味着一个新的线程处于运行态,Hypervisor 捕获后发现是受监视的线程,激活虚拟页面监视器来检测漏洞。
(3)内核与 Hypervisor 通信
主要包括两个方面:
a.内核组件向Hypervisor 发出请求,Hypervisor 提供服务。通过服务接口实现。
b.Hypervisor 将消息发送到内核组件,内核组件处理消息。通过共享内存实现消息传递。
4.2系统调用接口检测漏洞
接口检测需要跟踪系统调用的执行过程并监视从用户模式程序传递的参数。接口检测可以监控系统调用执行从进入内核态到返回用户态的整个过程,此过程中监控内核代码对用户内存的处理过程,然后记录行为特征以分析潜在的漏洞。
(1)事件监视器
十种类型的行为事件:Syscall、Trap2b、Trap2e、RetUser、MemAccess、ProbeAccess、ProbeRead、ProbeWrite、GetPebTeb、AllocVirtualMemory。
(2)CPU 仿真器
Hypervisor中的 CPU 仿真器用来帮助获得常规方法难以获得的行为特征。CPU 仿真器通过解释执行 Guest 操作系统的一段代码来实现。
(3)检测 UNPROBE 漏洞
理论上,在使用从用户态程序传递的指针之前,系统调用处理程序应检查它以确保它指向用户态空间。因此,在正常情况下,它会在 MemAccess 事件之前触发 ProbeAccess、ProbeRead 或 ProbeWrite 事件。如果在 MemAccess 事件之前没有这种类型的检查事件,则内核代码中可能存在 UNPROBE 漏洞。
(4)检测 TOCTTOU 漏洞
如果有两个 MemAccess 事件在相同的用户内存中获取,通过比较Syscall/Trap2b/Trap2e 和 RetUser 事件综合判断是否在相同的系统调用中被触发,从而判断是否存在 TOCTTOU 漏洞。(两次访问同一内存è两次访问位于同一syscall中。这样会漏报/误报)
4.3通过内存指纹检测漏洞
(1)检测 UAF 漏洞
hook内存分配/释放函数跟踪释放的内存页,直到它们被再次分配,任何对释放内存的访问都将被标记为 UAF 漏洞。
(2)检测 OOB 漏洞
越界访问堆的内存可能导致 OOB 漏洞,监控的内存空间限制在未分配的内存区域,任何对未分配内存区的访问都会被认为是 OOB 漏洞。Hook 分配/释放内存的函数,用AVL 树记录分配的内存空间,发生内存访问时则搜索AVL树,若找不到则发生OOB漏洞。对于两个内存块相邻,对内存块 A 的操作越界到内存块 B 中的问题,Digtool 在 Hook 内存分配函数时为其多分配 M 字节的额外内存区(仍会漏报)。
5.工作评估
结果:实验结果速度比Bochspwn快,发现windows和第三方驱动的45个0day
优势:
a.Crash Resilient:Digtool 能够捕捉潜在漏洞的动态特征,而不需要“蓝屏死机”(BSOD)。
b.在确定的上下文中断操作系统:通过中间组件,Digtool 可以设置为在发生程序错误时中断 Guest 操作系统,同时连接到调试工具为漏洞分析提供确切的上下文,减少人工分析。
c.捕获更多漏洞:Digtool可以有效检测 UNPROBE 和 TOCTTOU 漏洞。
Digtool 的局限:
a.尽管其比仿真器快,但监视线程的性能开销仍然很高,性能开销主要来自 Hypervisor 和 Guest 操作系统之间的频繁切换。
b.目前仅支持 Windows系统,Hypervisor 在 Guest 操作系统外运行,所以修改中间组件即可支持各种平台。
c.可以扩展检测算法来检测其他类型的漏洞,如竞争条件。