HEVD-StackOverflowGS
一: 概述
HEVD:漏洞靶场,包含各种Windows内核漏洞的驱动程序项目,在Github上就可以找到该项目,进行相关的学习
Releases · hacksysteam/HackSysExtremeVulnerableDriver · GitHub
Windows 7 X86 sp1 虚拟机
使用VirtualKD和windbg双机调试
HEVD 3.0+KmdManager+DubugView
二:前置知识:
(1)栈中的守护天使:GS
安全编译选项-GS
GS编译选项为每个函数调用增加了一些额外的数据和操作,用以检测栈中的溢出。 在所有函数调用发生时,向栈帧内压入一个额外的随机 DWORD,随机数标注为“SecurityCookie”。 Security Cookie位于EBP之前,系统还将在.data的内存区域中存放一个Security Cookie的副本,如图
当栈中发生溢出时,Security Cookie将被首先淹没,之后才是EBP和返回地址。在函数返回之前,系统将执行一个额外的安全验证操作,被称做 Security check。 在Security Check的过程中,系统将比较栈帧中原先存放的Security Co okie和.data中副本的值,如果两者不吻合,说明栈帧中的Security Cookie已被破坏,即栈中发生了溢出。
当检测到栈中发生溢出时,系统将进入异常处理流程,函数不会被正常返回,ret 指令也不会被执行,如图
但是额外的数据和操作带来的直接后果就是系统性能的下降,为了将对性能的影响降到最小,编译器在编译程序的时候并不是对所有的函数都应用GS,以下情况不会应用GS。 (1)函数不包含缓冲区。 (2)函数被定义为具有变量参数列表。
(3)函数使用无保护的关键字标记。
(4)函数在第一个语句中包含内嵌汇编代码。 (5)缓冲区不是8字节类型且大小不大于4个字节。
除了在返回地址前添加Security Cookie外,在Visual Studio 2005及后续版本还使用了变量重排技术,在编译时根据局部变量的类型对变量在栈帧中的位置进行调整,将字符串变量移动到栈帧的高地址。这样可以防止该字符串溢出时破坏其他的局部变量。同时还会将指针参数和字符串参数复制到内存中低地址,防止函数参数被破坏。如图
通过GS安全编译选项,操作系统能够在运行中有效地检测并阻止绝大多数基于栈溢出的攻击。要想硬对硬地冲击GS机制,是很难成功的。让我们再来看看Security C ookie产生的细节。 1.系统以.data节的第一个双字作为Cookie的种子,或称原始Cookie(所有函数的Cookie都用这个DWORD生成)。 2.在程序每次运行时Cookie 的种子都不同,因此种子有很强的随机性 3.在栈桢初始化以后系统用ESP异或种子,作为当前函数的Cookie,以此作为不同函数之间的区别,并增加Cookie的随机性 4.在函数返回前,用ESP还原出(异或)Cookie 的种子
在微软出版的Writing Secure Code一书中谈到GS选项时,作者还给出了微软内部对GS为产品所提供的安全保护的看法: 修改栈帧中函数返回地址的经典攻击将被GS机制有效遏制; 基于改写函数指针的攻击,GS很难防御; 针对异常处理机制的攻击,GS很难防御; GS是对栈帧的保护机制,因此很难防御堆溢出的攻击。
所以绕过GS保护有几种方法
利用未被保护的内存突破GS
覆盖虚函数突破GS
攻击异常处理突破GS
同时替换栈中和.data中的Cookie突破GS
(2)攻击SEH绕过GS保护
GS机制并没有对S.E.H 提供保护,换句话说我们可以通过攻击程序的异常处理达到绕过GS 的目的。我们首先通过超长字符串覆盖掉异常处理函数指针,然后想办法触发一个异常,程序就会转入异常处理,由于异常处理函数指针已经被我们覆盖,那么我们就可以通过劫持S.E.H 来控制程序的后续流程。
每个SEH结构体包含两个DWORD指针:SEH链表指针next seh和异常处理函数句柄Exception handler,共八个字节,存放于栈中。如下图所示,其中SEH链表指针next seh用于指向下一个SEH结构体,异常处理函数句柄Exception handler为一个异常处理函数。
1
2
3
4
5
EXCEPTION_DISPOSITION
__cdecl _except_handler( struct _EXCEPTION_RECORD
*
ExceptionRecord,
void
*
EstablisherFrame,
struct _CONTEXT
*
ContextRecord,
void
*
DispatcherContext);
Visual C++为使用结构化异常处理的函数生成的标准异常堆栈帧,它看起来像下面这个样子:
1
2
3
4
5
6
7
EBP
-
00
_ebp
EBP
-
04
trylevel
EBP
-
08
scopetable数组指针
EBP
-
0C
handler函数地址
EBP
-
10
指向前一个EXCEPTION_REGISTRATION结构
EBP
-
14
GetExceptionInformation
EBP
-
18
栈帧中的标准ESP
(0day第十章有详细介绍)
关于异常更详细的知识:
[原创]内核学习-异常处理-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com
三:漏洞点分析
漏洞原理:栈溢出漏洞,使用过程中使用危险的函数,没有对参数进行限制 BufferOverflowStackGS开启GS保护
(1)加载驱动
(这部分内容直接使用上一篇分析的HEVD_BufferOverflowStack的图片了)
安装驱动程序,使用kmdManager 加载驱动程序,DebugView检测内核,可以看到加载驱动程序成功。
windbg:
1
2
3
lm 查看所有已加载模块
lm m H
*
设置过滤,查找HEVD模块
lm m HEVD
[注意]看雪招聘,专注安全领域的专业人才平台!