栈溢出防御之——Windows安全机制GS编译选项
2012-10-14 15:26
274 查看
安全漏洞中有个重灾区:栈溢出。利用类似memset之类的字符串修改函数,输入超出正常长度的字符串,导致栈溢出,从而影响其它数据(返回地址、标志变量等)。
维基百科给出的资料http://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88%E6%BA%A2%E5%87%BA主要是函数无限调用导致的堆栈溢出,下面给出个0day2里面的例子温习下栈溢出:
编译运行后会发现任何99999999等大于1234567的八位数字字符串都可以通过验证,这是什么原因呢。很简单,首先要了解栈结构,大概说下authenticated栈中位置在buffer字符串后面,而输入8个字符导致最后一个NULL字符串结束标志就覆盖了authenticated的前1个byte(小端规则,这也是为什么要大于1234567,否则覆盖后authenticated是00FFFFFF,而不是00000000),从而认证成功。(authenticated由01000000被覆盖为00000000)
面对这个重灾区,Windows在VS 7.0(Visual Studio 2003)及以后版本的Visual Studio中默认启动了一个安全编译选项——GS(针对缓冲区溢出时覆盖函数返回地址这一特征),来增加栈溢出的难度。(很明显,对没有重新编译的软件来说,得不到保护,仍旧有这种安全漏洞。)
GS编译选项为每个函数调用增加了一些额外的数据和操作,用以检查栈中的溢出:
1、在所有函数调用发生时,向栈帧内压入一个额外的随机DWORD,这个随机数被称为canary(想把栈帧数据当成金丝雀般用笼子圈起来),如果用IDA反汇编的话,会看看到IDA会将这个随机数标志为Security Cookie。
2、Security Cookie位于EBP之前,系统还将在.data的内存区域中存放一个Security Cookie的副本,从而进行校验;
3、当栈中发生溢出时,Security Cookie将被首先淹没,之后才是EBP和返回地址;
4、在函数返回之前,系统将会执行一个额外的安全验证操作,被称作Security Check;
5、在Security Check的过程中,系统将比较栈帧中原先存放的Security Cookie和.data中副本的值,如果两者不吻合,说明栈中的Security Cookie已经被破坏了,即栈中发生了溢出;
6、当检测到栈中发生溢出时,系统将进入异常处理流程,函数不会被正常返回,ret指令也不会被执行。
但是额外的数据和操作带来的直接后果就是系统性能的下降,为了将对性能的影响降到最小,编译器在编译程序的时候并不是对所有的函数都应用GS,一下情况不会应用GS:
1、函数不包含缓冲区;
2、函数被定义为加油变脸参数列表;
3、函数使用无保护的关键字标记;
4、函数在第一个语句中包含内嵌汇编代码;
5、缓冲区不是8字节类型而且大小不大于4个字节。
(有了例外,就有利用相对特性的GS突破。)
除了在返回地址钱添加Security Cookie外,在Visual Studio 2005及后续版本还使用了变量重排技术,在编译时根据局部变量的类型对变量在栈帧中的位置进行调整,将字符串变量移动到栈帧的高地址。这样可以防止该字符串溢出时破坏其他的局部变量。同时还会降指针参数和字符串参数复制到内存中的低地址,防止函数参数被破坏。
GS的Security Cookie产生的一些细节:
1、系统以.data节第一个双字作为Cookie的种子,或者原始Cookie(所欲函数的Cookie都用这个DWORD生成)
2、在程序每次运行时Cookie的种子都不用,因此种子加油很强的随机性;
3、在栈帧初始化以后系统用EBP异或种子,作为当前函数的Cookie,以此作为不同函数之间的区别,并增加Cookie的随机性;
4、在函数返回时前,用EBP还原出(异或)Cookie的种子。
突破方法:
1、利用未被保护的内存突破GS。为了将GS对性能的影响降到最小,并不是所有的函数都会被保护,所有就可以利用其中一些未被保护的函数绕过GS的保护;
2、基于改写函数指针的攻击,如C++虚函数攻击;
3、针对异常处理机制的攻击;
4、堆溢出没有保护。
维基百科给出的资料http://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88%E6%BA%A2%E5%87%BA主要是函数无限调用导致的堆栈溢出,下面给出个0day2里面的例子温习下栈溢出:
#include <stdio.h> #define PASSWORD "1234567" int verify_password (char *password) { int authenticated; char buffer[8]; authenticated=strcmp(password,PASSWORD); strcpy(buffer,password);//over flowed here! return authenticated; } main() { int valid_flag=0; char password[1024]; FILE * fp; if(!(fp=fopen("password.txt","rw+"))) { exit(0); } fscanf(fp,"%s",password); valid_flag = verify_password(password); if(valid_flag) { printf("incorrect password!\n"); } else { printf("Congratulation! You have passed the verification!\n"); } fclose(fp); }(用VC6编译吧,别选上了GS)
编译运行后会发现任何99999999等大于1234567的八位数字字符串都可以通过验证,这是什么原因呢。很简单,首先要了解栈结构,大概说下authenticated栈中位置在buffer字符串后面,而输入8个字符导致最后一个NULL字符串结束标志就覆盖了authenticated的前1个byte(小端规则,这也是为什么要大于1234567,否则覆盖后authenticated是00FFFFFF,而不是00000000),从而认证成功。(authenticated由01000000被覆盖为00000000)
面对这个重灾区,Windows在VS 7.0(Visual Studio 2003)及以后版本的Visual Studio中默认启动了一个安全编译选项——GS(针对缓冲区溢出时覆盖函数返回地址这一特征),来增加栈溢出的难度。(很明显,对没有重新编译的软件来说,得不到保护,仍旧有这种安全漏洞。)
GS编译选项为每个函数调用增加了一些额外的数据和操作,用以检查栈中的溢出:
1、在所有函数调用发生时,向栈帧内压入一个额外的随机DWORD,这个随机数被称为canary(想把栈帧数据当成金丝雀般用笼子圈起来),如果用IDA反汇编的话,会看看到IDA会将这个随机数标志为Security Cookie。
2、Security Cookie位于EBP之前,系统还将在.data的内存区域中存放一个Security Cookie的副本,从而进行校验;
3、当栈中发生溢出时,Security Cookie将被首先淹没,之后才是EBP和返回地址;
4、在函数返回之前,系统将会执行一个额外的安全验证操作,被称作Security Check;
5、在Security Check的过程中,系统将比较栈帧中原先存放的Security Cookie和.data中副本的值,如果两者不吻合,说明栈中的Security Cookie已经被破坏了,即栈中发生了溢出;
6、当检测到栈中发生溢出时,系统将进入异常处理流程,函数不会被正常返回,ret指令也不会被执行。
但是额外的数据和操作带来的直接后果就是系统性能的下降,为了将对性能的影响降到最小,编译器在编译程序的时候并不是对所有的函数都应用GS,一下情况不会应用GS:
1、函数不包含缓冲区;
2、函数被定义为加油变脸参数列表;
3、函数使用无保护的关键字标记;
4、函数在第一个语句中包含内嵌汇编代码;
5、缓冲区不是8字节类型而且大小不大于4个字节。
(有了例外,就有利用相对特性的GS突破。)
除了在返回地址钱添加Security Cookie外,在Visual Studio 2005及后续版本还使用了变量重排技术,在编译时根据局部变量的类型对变量在栈帧中的位置进行调整,将字符串变量移动到栈帧的高地址。这样可以防止该字符串溢出时破坏其他的局部变量。同时还会降指针参数和字符串参数复制到内存中的低地址,防止函数参数被破坏。
GS的Security Cookie产生的一些细节:
1、系统以.data节第一个双字作为Cookie的种子,或者原始Cookie(所欲函数的Cookie都用这个DWORD生成)
2、在程序每次运行时Cookie的种子都不用,因此种子加油很强的随机性;
3、在栈帧初始化以后系统用EBP异或种子,作为当前函数的Cookie,以此作为不同函数之间的区别,并增加Cookie的随机性;
4、在函数返回时前,用EBP还原出(异或)Cookie的种子。
突破方法:
1、利用未被保护的内存突破GS。为了将GS对性能的影响降到最小,并不是所有的函数都会被保护,所有就可以利用其中一些未被保护的函数绕过GS的保护;
2、基于改写函数指针的攻击,如C++虚函数攻击;
3、针对异常处理机制的攻击;
4、堆溢出没有保护。
相关文章推荐
- 栈溢出防御之——Windows安全机制GS编译选项
- 安全编码实践一:GS编译选项和缓存溢出
- Windows小技巧:如何把安全模式选项加入启动菜单
- Windows 2003 右键突然没有了共享和安全选项
- Win10 windows更新和安全选项内手动更新补丁升级方法图解
- Windows 服务器系统安全防御加固方法
- 为网站添加安全机制,windows与Form验证。
- 关于windows 静态动态库 还有编译选项的一些问题
- windows 安全删除硬件并弹出媒体 选项灰色、无法弹出、无弹出选项
- cl.exe,link.exe编译选项以及在windows下编译lua 5.2.2
- Windows安全机制学习笔记(一)
- WEB程序的安全防御机制(一)
- 关于SQL Server 2008的安全机制问题中的SQL Server和Windows身份验证模式
- [Windows 7 安全新功能] Windows 7 应用程序控制策略:深度安全防御
- windows下eclipse中,涉及源码编译的apk开发——使用系统签名机制
- Windows安全机制学习笔记(二)
- Windows安全机制学习笔记(五)-枚举文件ACL
- WEB程序的安全防御机制(二)
- WINDOWS下文件夹属性没有“安全”选项
- Intel的特权环--联系linux和windows的内核安全机制