VC++中利用/GS开关防止缓冲区溢出[组图](2)
图1演示了在C++编译器6、7.0、7.1中,堆栈概念上的布局,并演示了堆栈由高地址向低地址空间方向增长,这也是当程序执行时,堆栈增长的方向。堆栈向下增长,正是导致缓冲区溢出的主要原因,因为溢出会覆写在比缓冲区更高的内存地址空间上,而此正是易受攻击数据结构的栖身之地。
图1:堆栈逻辑布局
除了把异常处理方法等信息移到堆栈中数据缓冲区之下,Visual C++.NET 2003的链接器也把结构化异常处理方法的地址放到可执行文件的头部中。当异常发生时,操作系统可以检查堆栈中的异常信息地址,是否符合记录在文件头信息中的异常处理方法,如果情况不符,异常处理方法将不会执行。比如说,Windows Server 2003就可检查结构化异常信息,而此项技术也在Service Pack 2中移植到了Windows XP上。
而Visual C++ 2005(8.0)在此基础上又更进了一步,通常当有函数调用发生时,如果其中的一个本地缓冲区超出限度了,攻击者可能改写堆栈中在此之上的任何东西,包括异常处理、安全cookie、帧指针、返回地址和函数参数。而这些值的大多数被不同的机制所保护(如安全异常处理),但对一个有函数指针作参数的函数来说,仍有机会被溢出。如果一个函数接受一个函数指针(或结构、类中包含有函数指针)作为参数,攻击者就有可能改写指针中的值,使代码执行任何他想要的函数。鉴于此,Visual C++ 2005编译器将分析所有可能存在此漏洞的函数参数,并复制一份函数参数--并不使用原有的函数参数,把它放在堆栈中本地变量之下。如果原有函数参数被溢出改写了,只要副本中的值仍保持不变,整个函数就不会被攻破。
- 上一篇:vc在应用程序中播放声音资源文件
- 下一篇:弹出式菜单