windows溢出保护原理与绕过方法概览

前言
从20世纪80年代开始,在国外就有人开始讨论关于溢出的攻击方式。但是在当时并没有引起人们的注意,直至后来经一些研究人员的披露后,特别是著名黑客杂志Phrack上面关于溢出的经典文章,引领许多人步入溢出研究的行列,从此关于缓冲区溢出的问题才为人们所重视。随着溢出研究的深入,网上开始出现很多关于溢出攻击教程,揭露了许多溢出利用技术,特别是经典的call/jmp esp,借此溢出攻击案例层出不穷。这也引起了微软的重视,他们在 windows系统及VC++编译器上加入了各种溢出保护机制,以试图阻止这类攻击,可惜每次公布溢出保护机制之后,不久就有人公布绕过方法。MS每次都称某保护机制将成为溢出利用的末日,可惜每次都被终结掉。既而,黑客与微软之间的溢出斗争一直持续着。更多关于windows溢出的历史,可参见由 Abysssec安全组织编写的文章《Past,Present,Future of Windows Exploitation》(http://www.abysssec.com /blog/2010/05/past-present-future-of -windows-exploitation/)。在本篇文章中主要揭露了 windows平台上的各种溢出保护机制原理以及绕过方法,具体内容参见下文。

一、GS编译选项

原理:通过VC++编译器在函数前后添加额外的处理代码,前部分用于由伪随机数生成的cookie并放入.data节段,当本地变量初始化,就会向栈中插入cookie,它位于局部变量和返回地址之间:

    ┏━━━━━━━━┓内存低地址
    ┃   局部变量     ┃▲
    ┣━━━━━━━━┫┃
    ┃security_cookie ┃┃
    ┣━━━━━━━━┫┃栈
    ┃  入栈寄存器    ┃┃生
    ┣━━━━━━━━┫┃长                       
    ┃     SEH节点    ┃┃方
    ┣━━━━━━━━┫┃向
    ┃    返回地址    ┃┃
    ┣━━━━━━━━┫┃
    ┃    函数参数    ┃┃
    ┗━━━━━━━━┛内存高地址

经GS编译后栈中局部变量空间分配情况:

sub   esp,24h
mov   eax,dword ptr [___security_cookie (408040h)]
xor   eax,dword ptr [esp+24h]
mov   dword ptr [esp+20h],eax

在函数尾部的额外代码用于在函数返回时,调用security_check_cookie()函数,以判断cookie是否被更改过,当函数返回时的情况如下:

mov   ecx,dword ptr [esp+20h]
xor   ecx,dword ptr [esp+24h]
add   esp,24h
jmp   __security_check_cookie (4010B2h)

在缓冲区溢出利用时,如果将恶意代码从局部变量覆盖到返回地址,那么自然就会覆写cookie,当检测到与原始cookie不同时(也就是比较上面408040h与4010B2h两处cookie值的比较),就会触发异常,最后终止进程。

绕过方法:

1.猜测/计算cookie
Reducing the Effective Entropy of GS Cookies:http://www.uninformed.org/?v=7&a=2&t=html
至从覆盖SEH的方法出现后,这种方法目前已基本不用了,它没有后面的方法来得简便。

2.覆盖SEH
由于当security_check_cookie()函数检测到cookie被更改后,会检查是否安装了安全处理例程,也就是SEH节点中保存的指针,如果没有,那么由系统的异常处理器接管,因此我们可以通过(pop pop ret)覆盖SEH来达到溢出的目的。但对于受SafeSEH保护的模块,就可能会导致exploit失效,关于它的绕过在后续部分再述。
辅助工具:OD插件safeSEH、pattern_create、pattern_offset、msfpescan、memdump

3.覆盖虚表指针
堆栈布局:[局部变量][cookie][入栈寄存器][返回地址][参数][虚表指针]
当把虚表指针覆盖后,由于要执行虚函数得通过虚表指针来搜索,即可借此劫持eip。

二、SafeSEH

原理:为了防止SEH节点被攻击者恶意利用,微软在.net编译器中加入/sdeseh编译选项引入SafeSEH技术。编译器在编译时将PE文件所有合法的异常处理例程的地址解析出来制成一张表,放在PE文件的数据块(LQAJ)一C0N—FIG)中,并使用shareuser内存中的一个随机数加密,用于匹配检查。如果该PE文件不支持safesEH,则表的地址为0。当PE文件被系统加载后,表中的内容被加密保存到ntdl1.dll模块的某个数据区。在PE文件运行期间,如果发生异常需要调用异常处理例程,系统会逐个检查该例程在表中是否有记录:如果没有则说明该例程非法,进而不执行该异常例程。

绕过方法

利用SafeSEH保护模块之外的地址
对于目前的大部分windows操作系统,其系统模块都受SafeSEH保护,可以选用未开启SafeSEH保护的模块来利用,比如漏洞软件本身自带的 dll文件,这个可以借助OD插件SafeSEH来查看进程中各模块是否开启SafeSEH保护。除此之外,也可通过直接覆盖返回地址 (jmp/call esp)来利用。另一种方法,如果esp +8 指向EXCEPTION_REGISTRATION 结构,那么你仍然可以寻找一个 pop/pop/ret指令组合(在加载模块的地址范围之外的空间),也可以正常工作。但如果你在程序的加载模块中找不到pop/pop/ret 指令,你可以观察下esp/ebp,查看下这些寄存器距离nseh 的偏移,接下来就是查找这样的指令:

call dword ptr[esp+nn] / jmp dword ptr[esp+nn] 
call dword ptr[ebp+nn] / jmp dword ptr[ebp+nn] 
call dword ptr[ebp-nn] / jmp dword ptr[ebp-nn]
(其中的nn 就是寄存器的值到nseh 的偏移,偏移nn可能是: esp+8, esp+14, esp+1c, esp+2c, esp+44, esp+50, ebp+0c, ebp+24, ebp+30, ebp-04, ebp-0c, ebp-18)。

如果遇到以上指令是以NULL字节结尾的,可将shellcode放置在SEH之前:
• 在nseh 上放置向后的跳转指令(跳转7 字节:jmp 0xfffffff9);
• 向后跳转足够长的地址以存放shellcode,并借此执行至shellcode;
• 把shellcode 放在用于覆盖异常处理结构的指令地址之前。

三、DEP

原理:数据执行保护 (DEP) 是一套软硬件技术,能够在内存上执行额外检查以防止在不可运行的内存区域上执行代码。在 Microsoft Windows XP Service Pack 2、 Microsoft Windows Server 2003 Service Pack 1 、 Microsoft Windows XP Tablet PC Edition 2005 、 Microsoft Windows Vista 和 windows 7 中,由硬件和软件一起强制实施 DEP。DEP 有两种模式,如果CPU 支持内存页NX 属性, 就是硬件支持的DEP。只有当处理器/系统支持NX/XD位(禁止执行)时,windows才能拥有硬件DEP,否则只能支持软件 DEP,相当于只有SafeSEH保护。

绕过方法:

1.ret2lib
其思路为:将返回地址指向lib库中的代码,而不直接跳转到shellcode 去执行,进而实现恶意代码的运行。可以在库中找到一段执行系统命令的代码,比如system()函数,用它的地址覆盖返回地址,此时即使NX/XD 禁止在堆栈上执行代码,但库中的代码依然是可以执行的。函数 system()可通过运行环境来执行其它程序,例如启动Shell等等。另外,还可以通过VirtualProtect函数来修改恶意代码所在内存页面的执行权限,然后再将控制转移到恶意代码,其堆栈布局如下所示:
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓       
┃                        ┃            恶意代码              ┃内存高地址
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃        lpflOldProtect            ┃┃
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃          flNewProtect            ┃┃栈
┃       调用参数         ┣━━━━━━━━━━━━━━━━━┫┃

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
缓冲区溢出攻击是指攻击者通过向程序输入超出缓冲区长度的数据,从而覆盖程序的内存空间,执行恶意代码或者控制程序流程的一种攻击方式。缓冲区溢出攻击可以导致程序崩溃,甚至可以执行任意代码,造成严重的安全威胁。 缓冲区溢出攻击的原理是:当用户向程序输入数据时,如果输入的数据长度超过了程序预留的缓冲区长度,就会覆盖程序内存中的其他数据,甚至可以覆盖程序代码,从而执行恶意代码。 缓冲区溢出攻击的方法主要有以下几种: 1. 栈溢出攻击:攻击者通过向栈中注入超出缓冲区长度的数据,覆盖程序的返回地址,从而控制程序流程。 2. 堆溢出攻击:攻击者通过向堆中注入超出缓冲区长度的数据,达到覆盖程序的指针、控制程序流程等目的。 为了防范缓冲区溢出攻击,可以采取以下措施: 1. 对用户输入进行过滤:对用户输入的数据进行验证、过滤,去掉特殊字符、注释符等敏感信息。 2. 使用编译器选项:使用编译器提供的选项,如-fstack-protector、-Wformat等,可以检测和防范缓冲区溢出攻击。 3. 使用内存保护机制:使用内存保护机制,如ASLR(地址空间布局随机化)、DEP(数据执行保护)等技术,可以保护程序的内存空间,防止缓冲区溢出攻击。 4. 使用安全编程技术:使用安全编程技术,如使用安全函数、静态分析工具等,可以有效防范缓冲区溢出攻击。 5. 定期更新程序:及时修补漏洞,更新程序软件和开发库,以避免被攻击者利用已知漏洞实施攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值