漏洞战争-cve-2011-0104

on under 二进制
3 minute read

0x00 about

目标:分析cve-2011-0104
漏洞:excel TOOLBARDEF Record栈溢出漏洞
good article:
    http://m.2cto.com/Article/201112/114614.html
实验环境:
    excel 2003 sp3
    windows 2003 sp2 32位
漏洞触发样本:
    https://github.com/riusksk/vul_wars/raw/master/%E4%B9%A6%E7%B1%8D%E9%85%8D%E5%A5%97%E8%B5%84%E6%96%99.zip
    中的exploit.xlb

0x01 调试过程

运行excel
运行windbg
    f6加载excel
    g
excel中打开exploit.xbl
windbg中发现excel异常,结果如下:

    ---------------violation--------------
    (f88.f34): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=51455047 ebx=0013ca48 ecx=00000006 edx=000014a8 esi=00000000 edi=00000400
    eip=300e06f7 esp=0013aa04 ebp=0013aa70 iopl=0         nv up ei pl nz na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE - 
    EXCEL!Ordinal41+0xe06f7:
    300e06f7 8908            mov     dword ptr [eax],ecx  ds:0023:51455047=????????
    -----------------end------------------
    
    windbg捕获excel崩溃关键信息eip=300e06f7,开始要用windbg加载excel,不能用od加载,因为od不能捕获到这个开始的崩
    溃信息,kb还可查看崩溃时的函数调用情况,如下
    kb(可查看调用堆栈)
    --------------kb---------------
    ChildEBP RetAddr  Args to Child              
    WARNING: Stack unwind information not available. Following frames may be wrong.
    0013aa70 584b4c4b 30435451 50453043 55514b4c EXCEL!Ordinal41+0xe06f7
    0013aa74 30435451 50453043 55514b4c 4b4c4c47 0x584b4c4b
    0013aa78 50453043 55514b4c 4b4c4c47 35434c43 EXCEL!Ordinal41+0x435451
    --------------end--------------

关闭excel,windbg
重新在od中打开,并加载excel

in od:
    f9
    ctrl+g:300e06f7
    在300e06f7处往上找到当前函数帧的第一句push ebp,mov mov ebp,esp,并在push ebp上(addr=300e05ad)下断

excel打开exploit.xbl

in od:
od中断到300e05ad处
f8
f8
在汇编窗口中ctrl+g:ebp(此时ebp=12aa70)
右键在ebp的地址处下内存写入断点
    内存写入断点无法通过ctrl+b查看,只有在中断时状态栏会显示.在进入300e05ad之后再在该函数的ebp上下内存写入
    断点这样就可以很快定位出是哪句汇编指令在操作数据时会覆盖ebp(覆盖ebp也即会对ebp有写入操作),由上面ebp和
    retn的关系易知,在一个函数帧中,当前ebp被处的内容被覆盖说明retn也被覆盖(一般不出现刚好覆盖到ebp,不覆盖
    的乃的情况)
    
f9
    中断发生在300de834处,如下:
    ----------------opperate_ebp-------------------
    300DE7EB   .  C3            retn
    300DE7EC   $  53            push ebx
    300DE7ED   .  8B5C24 0C     mov ebx,dword ptr ss:[esp+0xC]
    300DE7F1   .  85DB          test ebx,ebx
    300DE7F3   .  0F84 89970200 je EXCEL.30107F82
    300DE7F9   .  3B5C24 10     cmp ebx,dword ptr ss:[esp+0x10]                                               ;  EXCEL.3070DF42
    300DE7FD   .  0F87 03A71500 ja EXCEL.30238F06
    300DE803   .  8B15 442C8930 mov edx,dword ptr ds:[0x30892C44]
    300DE809   .  A1 402C8930   mov eax,dword ptr ds:[0x30892C40]
    300DE80E   .  55            push ebp
    300DE80F   .  8B6C24 0C     mov ebp,dword ptr ss:[esp+0xC]
    300DE813   .  56            push esi                                                                      ;  EXCEL.3088ECC0
    300DE814   .  57            push edi
    300DE815   >  3BD0          cmp edx,eax
    300DE817   .  0F8D F0B90300 jge EXCEL.3011A20D
    300DE81D   >  2BC2          sub eax,edx
    300DE81F   .  3BD8          cmp ebx,eax
    300DE821   .  7D 02         jge short EXCEL.300DE825
    300DE823   .  8BC3          mov eax,ebx
    300DE825   >  8DB2 40EC8830 lea esi,dword ptr ds:[edx+0x3088EC40]
    300DE82B   .  8BC8          mov ecx,eax
    300DE82D   .  8BD1          mov edx,ecx
    300DE82F   .  C1E9 02       shr ecx,0x2
    300DE832   .  8BFD          mov edi,ebp
    300DE834   .  F3:A5         rep movs dword ptr es:[edi],dword ptr ds:[esi]
    300DE836   .  8BCA          mov ecx,edx
    300DE838   .  83E1 03       and ecx,0x3
    300DE83B   .  F3:A4         rep movs byte ptr es:[edi],byte ptr ds:[esi]
    ---------------------end-----------------------
        
    300de834的入口在300de7ec,eip=300de834时,edi=12aa6f,esi=3088ecc0(内容为"ABuJIKLK..."),ebp=12aa0f,这样的话数
    据将被复制到edi(12aa6f)处,可是栈窗口中,edi(12aaf6)已经在ebp(12aa0f)的下面,如果数据从edi开始覆盖,是不会覆
    盖ebp的,这样应该不会引起retn被覆盖,既然不会覆盖当前函数帧的ebp,于是看看会不会覆盖上一函数帧的ebp

alt+k(查看调用堆栈)

    -----------alt+k------------
    调用堆栈:     主线程
    地址       堆栈       函数过程 / 参数                       调用来自                      结构
    001279C0   3070DF42   EXCEL.300DE7EC                        EXCEL.3070DF3D
    0012A9EC   30237FDF   ? EXCEL.3070DD5F                      EXCEL.30237FDA
    ------------end-------------

    上面结果表示,当前函数为300de7ec,上一帧函数为3070dd5f,为了查看上一函数帧的ebp,在alt+k窗口中右键单击
    3070dd5f,选择"显示函数过程",然后在3070dd5f上下断点,重新运行od和excel,od中断到3070dd5f处

    中断发生,eip=3070dd5f,ebp=0012aa70(这个ebp与上面进入300e05ad函数的ebp相等,可见3070dd5f函数的上一函数帧为
    300e05ad,alt+k查看调用堆栈也可看出的确是这样)

f8
f8(此时ebp=00129aac,也即上面说的"于是看看会不会覆盖上一函数帧的ebp"中的ebp),129aac<12aa6f,所以也不会覆盖到
这个3070dd5f函数的ebp,3070dd5f的入口汇编指令如下:

    ----------------3070dd5f------------------
    3070DD5F  /$  55            push ebp
    3070DD60  |.  8DAC24 C4F0FF>lea ebp,dword ptr ss:[esp-0xF3C]
    3070DD67  |.  81EC EC0F0000 sub esp,0xFEC
    3070DD6D  |.  A1 00F08930   mov eax,dword ptr ds:[0x3089F000]
    3070DD72  |.  8365 58 00    and [arg.21],0x0
    ------------------end---------------------
    
    并不是一般情况下的push ebp,mov ebp,esp,所以这里不能直接在3070dd5f中断后f8+f8到eip=3070dd67处通过查看ebp中存
    放的内容(也即[ebp])来查看上一帧函数的ebp了,要查看上一帧的ebp,通过在函数刚刚进入执行完push ebp后直接查看
    [esp]便是上一帧的ebp内容了,所以这里总结出在当前函数帧查看上一帧函数的ebp的方法有如下两种:

        1>在当前函数帧中直接查看[ebp],这种方法对一般情况下适用,对当前函数帧的最开始两句汇编指令不是push ebp,mov
        ebp,esp的情况不适用

        2>在当前函数帧刚执行完第一句push ebp后,查看[esp]为多少,上一函数帧的ebp就是多少,要求第一句是push ebp,
        几乎大多函数都适用
    
    既然也不会覆盖到上一帧函数的ebp,看看会不会覆盖到上一帧的上一帧函数的ebp
    此时eip=3070dd67,用上面的第二种方法直接查看[esp]即可得出上一帧的上一帧的ebp为0012aa70,0012aa70>12aa6f,应该
    就是覆盖了这个ebp了,12aa70的下一栈单元12aa74中的值[12aa74]为30e05ad函数的返回地址,继续调试如下
    
在汇编窗口中ctrl+g:12aa70,右键下内存写入断点

    f9中断到300de834处:
    300DE834   .  F3:A5         rep movs dword ptr es:[edi],dword ptr ds:[esi]

在堆栈窗口中ctrl+g:12aa70,右键锁定堆栈

f7
f7
f7
...
f7
    在一直f7时会一直看到栈中的数据被改变,并慢慢接近12aa70,最终覆盖12aa70中的值,覆盖12aa74中的值,...

执行到返回
...
f8
f8
...
    最后执行到300e06f7处准备发生异常

        300E06F1   .  8B0D 445B8930 mov ecx,dword ptr ds:[0x30895B44]
        300E06F7   .  8908          mov dword ptr ds:[eax],ecx
        300E06F9   >  8B45 E8       mov eax,dword ptr ss:[ebp-0x18]                                               ;  EXCEL.30413050
        300E06FC   .  A3 445B8930   mov dword ptr ds:[0x30895B44],eax
        300E0701   .  8B45 E4       mov eax,dword ptr ss:[ebp-0x1C]
        300E0704   .  A3 34DF8830   mov dword ptr ds:[0x3088DF34],eax
        300E0709   .  8B45 FC       mov eax,dword ptr ss:[ebp-0x4]
        300E070C   .  8D65 94       lea esp,dword ptr ss:[ebp-0x6C]
        300E070F   .  5F            pop edi                                                                       ;  0012CA48
        300E0710   .  5E            pop esi                                                                       ;  0012CA48
        300E0711   .  5B            pop ebx                                                                       ;  0012CA48
        300E0712   .  C9            leave
        300E0713   .  C2 2C00       retn 0x2C

    eip=300e06f7处发生异常是由windbg捕获的,此时查看seh链如下

        SEH 链用于  主线程
        地址       SE处理程序
        0012FD38   user32.77E3AF18
        0012FDA0   user32.77E3AF18
        0012FFB0   EXCEL.3087F58C
        0012FFE0   kernel32.7C821A78
在seh链窗口中右键全部"在句柄上切换断点"(也即全部下断),发现异常后会执行到77e3af18,但是不确定是12fd38处的
773af18还是12fda0处的77e3af18,于是先在12fd38上右键在堆栈窗口中跟随,转到如堆栈窗口数据:

    0012FD38  |0012FDA0  指向下一个 SEH 记录的指针
    0012FD3C  |77E3AF18  SE处理程序
    0012FD40  |77E2B890  user32.77E2B890
    0012FD44  |00000000

将0012fd3c处的77e3af18改成41414141,并从300e06f7处开始f8单步跟踪,发现这样程序会异常终止,猜测是由于其他线程
监视到41414141处并不能处理当前异常情况,如果将0012fd3c处的77e3af18改成300e0713(一个retn 0x2c指令的地址),异
常处理则无法进行,但程序不会终止,只是f8无法到下一步,一直停在300e06f7处,此时再将0012fd3c处的300e0713改回
77e3af18则会正常进入77e3af18,说明是第12fd38处的77e3af18为实际用到的异常处理程序,可见只要将恶意构造的数据覆
盖到0012fd38即可控制eip,从而执行shellcode.

由于实验中用的系统环境和《漏洞战争》中的环境一致,而书中用到的exploit.xlb是excel 2007 sp2的恶意数据,所以最
后不会执行到shellcode,只是异常.
漏洞分析, 漏洞战争, excel
home
github
archive
category