漏洞战争-cve-2011-0104
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,只是异常.