基于CVE-2012-1889漏洞的堆喷射利用分析

漏洞分析

分析环境

系统:Windows xp pro sp3

软件:IE 6.0,IE8.0

工具:x32dbg,windbg,mona,editplus,Notepad++

获取poc

漏洞分析

漏洞复现

打开poc样本,使用x32dbg附加IE后,点击允许执行脚本

X32dbg捕获到异常断下

 

由于对js并不熟悉,这里仅做漏洞的利用学习,主要分析学习堆喷射的利用方式以及ret2libc绕过DEP。

漏洞利用

如上定位到漏洞触发点分析

 

可以发现这里利用栈中的参数作为对象指针进行了虚函数的调用。

其中栈中的数据为图片路径,可以人为构造,这样就造成了可以构造任意地址指向堆,在堆中构造对象用于调用,即实现了漏洞的利用。由于js中字符串的申请全部都保存在堆中,这就可以通过大量申请一定格式的字符串淹没指定位置构造出对象加以利用,也即堆喷射的原理。

根据上面异常处的代码,具体分析指令逻辑为

mov eax,[ebp-0x14];

mov ecx,[eax]

call [ecx+0x18]

我们可以使eax=0x0c0c0c0c,ecx=[0x0c0c0c0c]=0x0c0c0c0c

则上述调用就变为call [0x0c0c0c24]

对于一般的堆喷射都是采用大量滑板指令+shellcode的方式进行分块覆盖,这样只要虚函数的调用碰到我们的滑板指令就一定能完成shellcode的调用。结构如下图所示:

 

申请堆空间时由于堆的管理结构比较复杂,在不同情况下管理结构还不同,具体结构我也不是很清晰,但是有一种结构,即大堆块的结构下管理结构比较清晰,如下

 

当单次申请堆空间大于512kb时就会是这种管理结构:32字节管理+4字节长度+2字节尾部标识的方式。我们只需要构造这种数据即可获得地址对齐后的堆空间。

针对当前IE6.0环境(即没有DEP),可以直接申请以下类型的数据块

 

具体js代码

 

这样就完成了堆空间的构造,即现在0x0c0c0c0c地址指向的内容大概率为滑板指令了,往下执行就会执行到我们的shellcode。

结合poc异常触发点处的代码逻辑,上述调用逻辑如下图

 

这样就完成了漏洞的利用,可以顺利执行shellcode

使用x32dbg附加修改后的poc

这种方式下利用较为简单,在IE8.0下开启了DEP,即我们的数据不能在栈或者堆中执行,以上的利用方式在IE8.0下就不适用了。对于DEP的绕过很多前辈想出了很多巧妙的方式,其中就有一种ret2libc的方式构造rop,比较简单易懂。在IE8.0下我们采用该方式修改上面的poc对DEP绕过,达到利用漏洞的目的。

 

 

Ret2libc利用原理:将要执行的指令序列进行分解,构成指令+ret的序列,在dll中依次查找这些指令序列,串成一条完整的执行链,将dll中这些指令序列的地址依次填充在栈中,在漏洞函数调用点构造修改栈中的数据,在返回时ret到第一条分解指令所在的dll地址,随后依次返回执行完指令序列。具体如下图:

 

针对这里我们精确控制堆的内容比精确控制栈的内容要简单的多,所以在call中我们使用切换esp的命令将栈切换到我们构造好的堆空间中。开始rop链的执行。

一般构造的rop链不会太长,仅仅用来修改shellcode处的内存页属性具有执行权限即可。因为栈中不能执行数据,所以我们不能再使用滑板指令填充,要精确地构造栈中每一个字节的内容。这里就用到精准堆喷射。

申请堆空间时获取大小按页对齐,这样我们可以在每一页内按照页偏移精确构造一个偏移处的数据,然后批量申请堆空间,这样我们就能在精确的位置构造精确的数据。比如我们要在0x0c0c0c0c处写入0x0c0c0c0c,按照页对齐,我们只需要在页内偏移为0x0c0c处写入0c0c0c0c即可,然后按照这个小块为模板申请大堆块即可。如下图所示:

 

这样,在大堆块中,无论哪一页落在了调用点,都一定是在该页的0x0c0c偏移处,即0x0c0c处一定是我们构造的exploit。

根据上面的想法,我们要在正常调用的第一个call处修改esp的值到我们构造的堆中,可以利用ecx的值进行赋值来到我们构造的exploit处,但是这样就不能将栈中的数据覆盖为0x0c0c0c0c了,再次分析异常产生处的调用流程

 

考虑将eax减小,由于上面是我们构造的滑板指令,这样上面的内存内容全部都是0x0c0c0c0c,不会影响ecx的值和后面的执行逻辑,然后执行时就不会再构成死循环。将栈中的数据修改为0x0c0c0c08,构造rop链如下,可以实现DEP的绕过。

 

页内数据块构造如下图所示:

 

将相同的数据结构拼接达到1MB,然后按照大堆块裁剪掉头和尾即可。

根据上面精准堆喷的分析,要rop链放到0x0c0c/2=0x606处,shellcode紧随其后

使用windbg+mona插件查找指定的字节序列

Windbg附加IE浏览器,输入如下命令

.load pykd.pyd

!py mona find -s”要查找的命令”

如 xchag esp,ecx

 

依次查找rop链中的命令,构成如下的ret2libc调用

对于VirtualProtect 的第四个参数,可以找一个没有随机基址(alsr==false)的dll,在其data段随便找一个地址保存oldProtect属性,以msvcrt.dll为例:

使用x32dbg加载IE8.0,在内存布局找到msvcrt.dll,找到.data全局数据段,找一个空闲地址。

转到内存窗口,随便找一个地址(尽量往后找,防止被dll用到),比如0x77c2dd40

下面构造特殊字符串组,用于构造利用堆空间

 

 

1.padding

 

2.ret2libc

如上图

3.Shellcode

4.数据块完整构造过程

完成后打开修改后的poc,使用x32dbg附加调试,在rop入口下断点   bp 0x7c96d0fb

单步一步,查看堆栈内容

查看shellcode

直接运行,弹出hello world窗口

总结

对于对象的虚函数调用配合UAF类漏洞一般可以搭配堆喷射进行利用。

在不存在DEP的情况下,我们可以在堆中执行代码,这种情况下我们只需要按照  滑板指令+shellcode  的格式大量占据堆空间即大概率能实现漏洞的利用。

在存在DEP的情况下,我们可以利用ret2libc的方式,将虚函数调用替换为dll中的修改esp到堆中的opcode,然后配合精准堆喷射精心构造即将作为新栈的堆空间,利用多个dll中的代码片段组合完成一个完整的功能。

在本漏洞分析中主要是学习堆喷射的原理,精准堆喷射的原理以及DEP的ret2libc绕过方法等。

 

 

 

 

 

发布了6 篇原创文章 · 获赞 2 · 访问量 465

猜你喜欢

转载自blog.csdn.net/wojiukanxia/article/details/104528078