Windows漏洞利用与防护(2015.8)
Windows平台下的漏洞利用与防护
0x00 概述
在过去的二十几年,Windows作为网络安全的主战场之一,攻于防的较量从未停息过。内存破坏漏洞作为研究的重点之一,经历了很多的发展也沉淀了前辈们许多经验和智慧。
本人根据大牛们的各种报告总结了目前Windows平台上内存破坏漏洞利用与防护的发展史,接下来会从应用层和内核层两个方面逐一介绍。
先来看一下总的架构图:
0x01 用户层
应用层漏洞的目的都是为了执行任意代码,所以分为获得执行流+执行shellcode两部分介绍:
获得执行流程
1. 栈溢出
1.1 总览
-
发展历史
下图是微软在Black Hat 2012的演讲ppt中的一页
-
目前状况
a. 非常难以利用:在GS+SEHOP+SEH共同防护下。
b. 在编译器的帮助下,漏洞本身的数量也在减少。下图是Windows 2000到Windows 7,各种类型漏洞数量的比例,可是看出,栈溢出漏洞已经大幅减少:
1.2 最原始的利用
向局部变量填充大量的数据,直至覆盖返回地址,等到函数返回的时候,达到劫持EIP获取执行流目的。
1.3 GS
1.3.1. 概念
由Crispin Cowan提出,在编译器(从VS7.0开始)的帮助下,在发生函数调用的时候会向栈中压入一个随机数,函数返回的时候会和在.idata中的值做对比。
1.3.2. GS v1.0
a. 概念
-
VS 2002 加入
-
启发式的编译,发现问题函数
-
Prologue inserts cookie into stack frame
-
Epilogue checks cookie & terminates on mismatch
b.绕过方法
- ByPass using Exception Handing
覆盖SEH,在函数返回之前,制造一个异常
- Bypass by replacing cookie on stack and in .data section
如果有能力确定cookie存储的位置的话
- Bypass because not all buffers are protected(arg_0 for example)
-
Bypass by overwriting stack data in functions up the stack
比如某个对象或者结构的指针作为当前函数的参数,那么这个值是在当前函数的栈中的,也就是临时变量,这样可以通过直接改写来劫持EIP。
比如覆盖对象的virtuali function call table
-
Bypass by overwrite ntdll!KiUserExceptionDispatcher.
-
Bypass because you can guess/calculate the cookie.(haha)
-
Bypass because the cookie is static.(haha)
1.3.3. GS v1.1
a. 概念
- VS2003加入
- 将可能会发生溢出的local buffer variables紧挨着GS cookies放置,防止溢出后通过覆盖其它变量来劫持EIP。
1.3.4. GS v2.0
a. 概念
-
VS2005加入
-
shadow copy of parameters is made
-
strict GS pragma
b.绕过方法
1.3.5. GS v3.0
a. 概念
-
Protect more function
-
Remove unnecessary checks
-
参考 http://blogs.technet.com/b/srd/archive/2009/03/20/enhanced-gs-in-visual-studio-2010.aspx
1.4 SafeSEH
a. 概念
-
VS2003加入
-
编译选项/safeSEH,编译器在编译的时候会建立一个所有已知异常处理函数地址链表,当异常发生的时候会检查这个链表,如果是非法地址,则会立即结束进程。
-
也称为软件DEP
b.绕过方法
-
Try not to use SEH based exploit
开启了SEH但是未开启GS的进程。(haha)
-
攻击没有启用SafeSEH的模块
-
Point corrupted handler to somewhere other than an image or the stack
因为这种地址不受safeSEH的影响,所以只要在其中找到一条跳转指令就可以了
-
利用虚函数绕过
1.5 SEHOP
a. 概念
- 检查SEH链的最终异常函数是否为系统固定的函数
b. 绕过方法
- 攻击虚函数等
- 利用未启用SEHOP的模块
- 伪造SEH链表
由于ASRL,stack的地址获取是个问题,信息泄露?
2. 堆溢出
2.1 总览
a.发展历史
2.2 最原始的利用
a. 利用堆的链表管理特点,操作这个链表的时候就可以构造一个write4
b.Write What?
- 内存变量:能够影响程序流程的重要变量,比如虚函数。
- 代码逻辑:类似软件破解中的“爆破”,一个字节影响程序的流程。
- 函数返回地址:地址不固定较难确定。
- 攻击异常处理机制:SEH、VEH、UEF、PEB中的函数指针(程序结束的时候会PEB中的一对指针来调用RtlEnterCriticalSection和RtlLeaveCriticalSection函数)
2.3 安全机制
2.3.1 Win XP & Windows Sever 2003
a.Safe Unlinking
- 概念
链表项在卸载时候会检查链表的完整性
b.Heap entry header cookie
- 概念
一个8位的校验随机数,heap free 的时候进行验证
c.Pointer encoding
- 概念
Protect UEF,VEH,and others via EncodeSystemPointer
绕过方法
- Unsafe lookaside list allocations
- Unsafe unlinking of free chunks
- Unsafe unlink via RtlDeleteCriticalSection
- Exploiting FreeList[0]
- 参考
David Litchfield. Windows Heap Overflows. Black Hat USA. 2004
Alexander Anisimov. Defeating Microsoft Windows XP SP2 Heap protection. 2004
2.3.2 Windows Vista~Windows 7
a.Removal of commonly targeted data structures
such as lookaside lists and array lists
lookaside replaced by the Low Fragmentation Heap (LFH)
b.Heap entry metadata randomization
c.hardening heap cookies
extend checking heap metadata scope,verified in more places,not only when the entry is freed.
d.Function Pointer encoding
Function pointers (e.g. CommitRoutine) in heap data structures are encoded with a random value
e.Termination on heap corruption
检测到异常的时候,直接终止程序
f.Algorithm variation
改进算法,更难预测堆的状态
g.RtlDeleteCriticalSection technique mitigated by RtlSafeRemoveEntryList
h.FreeList[0] technique mitigated by RtlpFastRemoveFreeBlock
绕过方法
- Corrupting the HEAP data structure
- LFH bucket overwrite
- LFH FreeEntryOffset corruption and depth desync
- 参考:
Modern Heap Exploitation using the Low Fragmentation Heap. Chris Valasek.2011
Attacking the Vista Heap. Ben Hawkes. Nov,2008
Ghost in the Windows7 Allocator.StevenSeeley,2012
2.3.3 Windows 8
a.guard pages
b.allocation order randomization
c.LFH design changes & integrity checks
3. UAF
这里针对的是IE浏览器。
3.1 概念
a.利用可控的假对象替代真对象(内存占位),劫持程序流程
b.attack class object instead of heap metadata/mechanism
3.2 防护
a. 延迟释放
要释放的内存不会立即释放,而是先并入到一个待释放链表中,大小达到100000的时候才会释放掉。
b. 隔离堆
大多数的DOM对象和相关的类都分配到一个单独的堆中,和通常用来占位的对象比如mshtml string、javascript string等分隔开来,防止占位。
c.Virtual Table Guard
类似cookies,在调用虚函数之前会check一下。
d.Sealed optimization
通过编译器,从源头减少虚函数的间接调用。
绕过方法
- http://www.k33nteam.org/ms14-056.html
- https://www.blackhat.com/docs/us-15/materials/us-15-Gorenc-Abusing-Silent-Mitigations-Understanding-Weaknesses-Within-Internet-Explorers-Isolated-Heap-And-MemoryProtection.pdf
执行shellcode
1. 总览
2. DEP
2.1 概念
2.1.1. 软件DEP
- 其实就是SafeSEH,和NX/XD一点儿关系都木有
- 一般提到的DEP都是指的硬件DEP
2.1.2. 硬件DEP
需要CPU的支持,通常意义上的DEP,通过修改相关页面的PTE,加入特殊的标识位来达到目的
a. Windows Xp SP2加入
b. 原理图
c. 工作状态
-
Optin
默认仅为windows系统组件和服务提供,从Vista 开始具有/NXcompat编译选项的程序也会纳入到这个范围内。
一般用于用户版的操作系统。 -
Optout
默认为排除列表以外的所有程序和服务启动DEP。
一般用于服务器操作系统。 -
AlwaysOn
不存在排除列表这种东西,所有的进程和服务都在内
只有64位的系统,不可以被关闭 -
AlwaysOff
对所有进程都禁用
不能够动态的被开启
其中前面两种情况都是可以动态的关闭的。
d. 绕过方法
ROP:通过在模块中寻找指令,组成代码段调用函数关闭DEP。
- VirtualProtect
改变目标内存地址属性为可执行
- Disable DEP for the process(NtSetInformationProcess)
设置进程结构KPROCESS中相关标志位
-
VirtualAllocEx
分配一块可执行(RWX)的内存
3. ASLR
3.1 概念
3.1.1. Windows Vista 引入
3.1.2.
目前所有的漏洞利用都有一个共同的特征:需要确定一个固定地址。比如JMP ESP等跳板和ROP所使用指令的地址。所以微软加入了地址随机化来防止获得稳定的地址。
3.1.3.
- 映像随机化
当PE文件映射到内存的时候,系统会对其映射的虚拟地址做随机化处理。
每次系统重启后,地址不同。
可以在注册表中设置
- 堆栈随机化
程序随机化的堆栈基地址。
每次程序重启时都不同。
- PEB/TEB随机化
3.2 绕过方法
3.2.1. 攻击未启动ASLR的模块
3.2.2. Address space spraying(heap/JIT)
http://www.semantiscope.com/research/BHDC2010/BHDC-2010-Paper.pdf
3.2.3. 预测内存
3.2.4. 信息泄露
- 修改数组对象,越界读
- 修改BSTR null结束符
- ...
参考:
- https://cansecwest.com/slides/2013/DEP-ASLR bypass without ROP-JIT.pdf
- http://www.semantiscope.com/research/BHDC2010/BHDC-2010-Paper.pdf
- https://www.fireeye.com/blog/threat-research/2013/10/aslr-bypass-apocalypse-in-lately-zero-day-exploits.html
- http://blogs.technet.com/b/srd/archive/2014/03/12/when-aslr-makes-the-difference.aspx
3.3 Windows 8
防护机制
- Force ASLR
进程可以强制non-ASLR images 随机化
- Bottom-up & top-down randomization
更难预测内存状态。
-
随机化的程度提高
-
去掉了一些可以泄露内存的路径
4. CFG
4.1 概念
4.1.1
从Win8.1 Update3加入,Win10中正式启用。
4.1.2
代码表示
- before
- after
4.1.3
图解
4.2 绕过方法
绿盟的研究员张云海在BlackHat的议题,思路就是“Overwrite Guard CF Check Function Pointer”,由于该地址只读属性,找到了一个magic object,能够改写该地址属性。
参考
-
Jack Tang, Trend Micro Threat Solution Team--Exploring Control Flow Guard in Windows 10
-
mj0011,Windows 10 Control Flow Guard Internals
到此,应用层的漏洞利于与防护介绍完了,下面是内核层的。
0x02 内核层
总的来说,内核层和应用层有着诸多相似的地方,但是也有着自己的特点,比如空指针解引用漏洞,SMEP防护机制等。
有趣的是,一些相同原理的防护机制,滞后于对应的应用层比如:Safe Unlink在win7才开始加入到内核防护中,应用层的Safe unlink防护早在WinXP就加入了。
下面按照和应用层相同的思路介绍,分为劫持执行流和执行shellcode两部分。但是要注意的是:
可能不需要执行shellcode,直接提权成功,比如CVE-2014-4113在win8 x64上的利用和CVE-2015-1701的利用
获得执行流程
1. 栈溢出
1.1 最原始利用
大量数据直至覆盖返回地址-->改写EIP,获得执行流
1.2 stack cookies
1.2.1 概念
- Windows XP SP2引入
- 类似于应用层的cookie,一个做校验的随机数
1.2.2 绕过方法
- 和应用层类似,想办法在函数返回之前触发异常
注意try catch不能捕获所有的页异常处理,在内核中引用一块无效地址会导致BSOD,所以这里有一个技巧:
memcpy的时候就触发异常,不要等到函数返回的时候,或者strcat这种操作的时候
参考:
A Guide to Kernel Exploitation Attacking the Core
- 预测cookies的值
Win8 x64之前:成功率大于46%。
J00ru:Windows Kernel-mode GS Cookies subverted
Win8 x64之后:非常困难。
参考:
mj0011,Using a Patched Vulnerability to Bypass Windows 8 x64 Driver Signature Enforcement
2. 堆溢出
2.1 最原始利用
类似用户层堆,利用堆链表管理的特点,构造Write 4。
2.2 Write what
- HalDispatchTable+4(常用)
修改其为shellcode的地址,然后在用户层调用 NtQueryIntervalProfile(2,X)触发shellcode执行。
- Token+ PrivilegesOffset.Enabled
修改SeDebug权限,之后可以注入代码到系统进程中,完成提权
Moritz Jodeit,Exploiting CVE-2014-4113 on Windows 8.1
- LDT
- KiDebugRoutine?
2.3 Win7 之前
2.3.1 安全机制
似乎没有。。。
2.3.2 绕过方法
主要发生在ListEntry中,在下面几种堆管理的情况下,又可能将溢出变成Write4:
- Unlink in merge with next
- Unlink in merge with previous pool chunk
- Unlink in allocation from ListHeads[n] free list
参考:
- SoBeIt X’con 2005
- Kostya Kortchinsky SyScan 2008
2.4 Win7
2.4.1 安全机制
Safe Unlink
类似应用层的Safe Unlink,图示:
2.4.2 绕过方法
- ListEntry Flink Overwrite
- Lookaside Pointer Overwrite
- PoolIndex Overwrite
- Quota Process Pointer Overwrite
参考:
Tarjei Mandt BH DC 2011
2.5 Win8
2.5.1 安全机制
都是针对win7上的利用做得改进。
- Process quota pointer encoding
- Lookaside,delay free,and pool page cookies
- PoolIndex bounds check
- Additional safe unlinking checks
2.5.2 绕过方法
- BlockSize Attack
- Split Chunk Attack
- DKOHM / Object Type Confusion(重要)
参考:
Tarjei Mandt BH US 2012
Zhenhua 'Eric' Liu NoSuchCon 2013
Nikita Tarakanov--Exploiting Hardcore Pool Corruptions in Microsoft Windows Kernel NoSuchCon 2013
Nikita Tarakanov--DATA-ONLY PWNING MICROSOFT WINDOWS KERNEL: EXPLOITATION OF KERNEL POOL OVERFLOWS ON MICROSOFT WINDOWS 8.1 ZeroNights 2014
2.6 总结
越来越多的pool integrity checks,针对pool metadata/mechanisms的攻击越来越困难,DKOHM是一个趋势。
3. 其它
3.1 空指针解引用
3.1.1 利用
这算是内核中比较特殊并且数量较大的一类漏洞了,虽然应用层也有空指针解引用漏洞,但是几乎都不能利用。而在Win8之前却是内核漏洞中很流行。
比如CVE-2014-4113、CVE-2015-0003等都是这种漏洞,形式类似:
call [eax+8] // eax=0
具体可以参考这两个漏洞的利用代码,都是公开的。
3.1.2 防护
win8 开始禁止非管理员权限的零页分配
3.2 UAF
3.2.1利用
和应用层类似,但是也有自己特殊的地方,比如神奇的WorkerFactoy 对象。
参考:0x710DDDD,CVE-2014-1767_Afd.sys_double-free_漏洞分析与利用
3.2.2防护
- Isolated Pools?
- Reference count hardening
3.3 竞争条件
这类漏洞一直没能找到相关的PoC,所以并不了解,可以参考:
http://j00ru.vexillium.org/?p=1695
执行shellcode
大多数的漏洞都需要这一步,也有像CVE-2014-4113在win8上面的exp,利用了漏洞本身的特点,不再需要”shellcode“了。
1. SMEP/SMAP
1.1 概念
SMEP:处理器cr4寄存器和PTE结合,阻止ring0去执行ring3代码(Prevents supervisor from executing code in user pages)
SMAP:Supervisor Mode Access Prevention,ring0的代码不可以read/write应用层的内存。
1.2 绕过方法
思路类似于绕过DEP。
- ROP
ExAllocatePoolWithTag (NonPagedExec) + memcpy+jmp
clear SMEP flag in cr4
参考:
http://blogs.360.cn/blog/hacking-team-part5-atmfd-0day-2/
- Leak and Jmp 到一个RWX的内核内存地址(Artem’s Shishkin technique)
- Set Owner flag of PTE to 0 (MI_PTE_OWNER_KERNEL)
- Win8之前
通过确定的对象地址,写入一些代码
但是win8 加入了 non-paged pool NX
mj0011,Reversing Windows8: Interesting Features of Kernel Security
2. Non-paged pool NX
2.1 概念
non-executable non-paged pool
参考
https://msdn.microsoft.com/en-us/library/windows/hardware/hh920391(v=vs.85).aspx
3. KASLR
3.1 概念
微软在Win8.1之前,对这方面都是很重视,第一次是在Server2008 RTM引入的。
4 bits of entropy for drivers,5 bits for NTOS/HAL
3.2 防护
3.2.1 Win7
Drivers: 6 bits on x86, 8 bits on x64
3.2.2 Win8
-
Biasing of kernel segment base
-
NTOS/HAL receive 22 bits(64-bit) and 12 bits(32-bit)
-
Various boot regions also randomized(P0 idle stack)
-
限制对敏感函数的调用
如果进程运行在低完整性级别以下(保护模式或增强保护模式),那么SystemModuleInformation等相关获得内核模块基址的方法都会被阻止,这样,即使攻击者在保护模式或增强保护模式下触发了内核漏洞,由于无法获得内核基址,也很难进行进一步利用。
参考:
http://blogs.360.cn/blog/fixed_three_0days_in_may/
4. DEP
图解:
by:会飞的猫
转载请注明:http://www.cnblogs.com/flycat-2016