Analysis CVE-2011-0978 Microsoft Office Excel Axis Properties Record Parsing Buffer Overflow
Author: instruder of Code Audit Labs of vulnhunt.com
Analysis ID: CALA-2011-001
Time: 2011/8/8
url:
http://blog.vulnhunt.com/index.php/2011/08/08/analysis-cve-2011-0978/
1 Affected Products
=================
测试版:Micrsoft Office Excel 2003 (11.8307.8221) SP3
漏洞编号:CVE-2011-0978
2 Vulnerability Details
=====================
Microsoft Office Excel在解析Axis Properties Record属性时,采用了有符号扩展,将WORD扩展成一个DWORD,同时在后面使用这个数组索引时,虽然有判断,但是采用了有符号比较,导致被绕过,允许攻击者索引任意DWORD,而这个DWORD指向的内存中前2个字节是拷贝的长度,后面是拷贝的源,源和拷贝长度都可以控制,理论上可以利用,从而导致恶意代码的执行可能。
3 Analysis
=====================
载入poc样本后 用windbg挂上后,点击关闭excel,弹出是否需要保存框,点击保存,触发crash(也可以直接点击cw 表也可以触发),信息如下:
(848.b24): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=05b4629c ebx=05b40460 ecx=00000000 edx=ffff5554 esi=00000000 edi=00000001 eip=30177d15 esp=00137938 ebp=00137944 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246 *** ERROR: Symbol file could not be found. Defaulted to export symbols for E:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE - EXCEL!Ordinal41+0x177d15: 30177d15 8b0490 mov eax,dword ptr [eax+edx*4] ds:0023:05b1b7ec=???????? 0:000> u EXCEL!Ordinal41+0x177d15: 30177d15 8b0490 mov eax,dword ptr [eax+edx*4] 30177d18 3bc6 cmp eax,esi 30177d1a 741e je EXCEL!Ordinal41+0x177d3a (30177d3a) 30177d1c 0fb708 movzx ecx,word ptr [eax] 30177d1f 894d10 mov dword ptr [ebp+10h],ecx 30177d22 41 inc ecx 30177d23 51 push ecx 30177d24 ff750c push dword ptr [ebp+0Ch] 0:000> dd eax 05b4629c 05b462e4 05b462fc 05b46314 05b4632c 05b462ac 05b46344 05b4635c 05b46374 05b4638c 05b462bc 05b463a4 00000001 00000001 00000001 05b462cc 00000001 00000001 00000001 00000001 05b462dc 00000001 00000001 00630009 0061006c 05b462ec 00730073 006f0077 006b0072 0e000000 05b462fc 00630009 0061006c 00730073 006f0077 05b4630c 006b0072 0e000000 00630009 0061006c 由上面crash信息可知edx是数组的索引,变成了FFFF5554,同时根据exploitdb 上面这个漏洞的概述知道5554 这个字段是在poc中的0x39E7处,猜测可能是有符号扩展导致由5554变成了FFFF5554. 转至IDA中查看 asm in Excel.exe .text:30177CDE sub_30177CDE proc near ; CODE XREF: sub_30173D14+33A p .text:30177CDE ; sub_30175B4C+309 p ... .text:30177CDE .text:30177CDE arg_0 = dword ptr 8 .text:30177CDE Dst = dword ptr 0Ch .text:30177CDE arg_8 = dword ptr 10h .text:30177CDE arg_C = dword ptr 14h .text:30177CDE arg_10 = dword ptr 18h .text:30177CDE arg_14 = dword ptr 1Ch .text:30177CDE .text:30177CDE ; FUNCTION CHUNK AT .text:30324E3C SIZE 000000C9 BYTES .text:30177CDE .text:30177CDE push ebp .text:30177CDF mov ebp, esp .text:30177CE1 mov ecx, [ebp+arg_0] .text:30177CE4 mov eax, [ecx+40h] .text:30177CE7 mov edx, [ebp+arg_10] .text:30177CEA push esi .text:30177CEB xor esi, esi .text:30177CED mov dword_3088D744, esi .text:30177CF3 cmp edx, [eax+0Ch] //edx是数组索引 .text:30177CF6 jge loc_30324E3C//关键 有符号比较,导致如果edx为负数就可绕过限制。 .text:30177CFC cmp [ebp+arg_14], esi .text:30177CFF push ebx .text:30177D00 push edi .text:30177D01 jz loc_30324E59 .text:30177D07 mov ecx, [ebp+arg_C] .text:30177D0A cmp ecx, esi .text:30177D0C jg loc_30324EFA .text:30177D12 .text:30177D12 loc_30177D12: ; CODE XREF: sub_30177CDE+1AD222 j .text:30177D12 mov eax, [eax+10h] .text:30177D15 mov eax, [eax+edx*4] ; edx为索引 .text:30177D18 cmp eax, esi .text:30177D1A jz short loc_30177D3A .text:30177D1C movzx ecx, word ptr [eax]//前2个字节是拷贝长度 .text:30177D1F mov [ebp+arg_8], ecx .text:30177D22 inc ecx .text:30177D23 push ecx ; int .text:30177D24 push [ebp+Dst] ; Dst //指向堆栈 .text:30177D27 add eax, 2 .text:30177D2A push eax ; Src //后面是拷贝的源 30177D2B E8 6345E9FF CALL EXCEL.3000C293 此时堆栈: 0013792C 05B4633E >c? //SRC 00137930 001379EA . UNICODE "classwork" //DST 00137934 00006349 Ic.. //SIZE 3000C293 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C] 3000C297 03C0 ADD EAX,EAX 3000C299 50 PUSH EAX 3000C29A FF7424 0C PUSH DWORD PTR SS:[ESP+C] 3000C29E FF7424 0C PUSH DWORD PTR SS:[ESP+C] 3000C2A2 E8 8EF4FFFF CALL EXCEL.3000B735 3000C2A7 C2 0C00 RETN 0C 此时堆栈: 0013791C 05B4633E >c? //SRC 00137920 001379EA . UNICODE "classwork" //DST 00137924 0000C692 .. //SIZE 3000B735 55 PUSH EBP 3000B736 8BEC MOV EBP,ESP 3000B738 F645 13 80 TEST BYTE PTR SS:[EBP+13],80 3000B73C 0F85 8E7D2100 JNZ EXCEL.302234D0 3000B742 FF75 10 PUSH DWORD PTR SS:[EBP+10] ; SIZE 3000B745 FF75 08 PUSH DWORD PTR SS:[EBP+8] ; SRC 3000B748 FF75 0C PUSH DWORD PTR SS:[EBP+C] ;DST 3000B74B E8 82FBFFFF CALL <JMP.&MSVCRT.memmove> 3000B750 83C4 0C ADD ESP,0C 3000B753 0345 10 ADD EAX,DWORD PTR SS:[EBP+10] 3000B756 5D POP EBP 3000B757 C2 0C00 RETN 0C 看到这里是个拷贝,[ebp+c]指向了堆栈,[ebp+10]是可以控制的(数组过界,向上溢出,可以控制索引的数据,拷贝的长度.拷贝的源) 此时堆栈: 00137908 001379EA . |dest = 001379EA //指向堆栈 0013790C 05B4633E >c? |src = 05B4633E //索引的源 00137910 0000C692 .. \n = C692 (50834.) //size …. 拷贝前: 001379E8 00630009 ..c. ----》001379EA 001379EC 0061006C l.a. 001379F0 00730073 s.s. 001379F4 006F0077 w.o. 001379F8 006B0072 r.k. ……. 00137A30 00000037 7... 00137A34 05B41908 ? 00137A38 0000012F / .. 00137A3C 0000007E ~... 00137A40 05B4259C ?? 00137A44 3017BC61 a?0 返回到 EXCEL.3017BC61 来自 EXCEL.30171240 拷贝后堆栈: 001379E8 05B40009 ..? 001379EC 05B4636C lc? 001379F0 05B461A8 ? 001379F4 05B46390 ? UNICODE "\tclasswork" ……… 00137A2C 00000001 ... 00137A30 00000001 ... 00137A34 00000001 ... 00137A38 00000001 ... 00137A3C 00630009 ..c. 00137A40 0061006C l.a. 00137A44 00730073 s.s.---返回地址被覆盖
4 Causes of vulnerability
通过一层层往上追溯,重启excel n次之后终于追踪到源头。
301B72E8 . 0FBF4E 02 MOVSX ECX,WORD PTR DS:[ESI+2]//esi指向文件中的0x95F3偏移处(poc更改后的) 301B72EC . 8948 04 MOV DWORD PTR DS:[EAX+4],ECX//有符号扩展 从CB50扩展到FFFFCB50 这个FFFFCB50就是上面提到的数组索引EDX 301B72EF . 0FBF06 MOVSX EAX,WORD PTR DS:[ESI] 301B72F2 . 8B8D C4E7FFFF MOV ECX,DWORD PTR SS:[EBP-183C] 301B72F8 . 8941 10 MOV DWORD PTR DS:[ECX+10],EAX 301B72FB . 0FBF46 04 MOVSX EAX,WORD PTR DS:[ESI+4] 301B72FF . 8B8D C4E7FFFF MOV ECX,DWORD PTR SS:[EBP-183C] 301B7305 . 8941 0C MOV DWORD PTR DS:[ECX+C],EAX 301B7308 . 8A4E 06 MOV CL,BYTE PTR DS:[ESI+6]

5 exploit
5.1 about shellcode position
这个poc里面有好几张表,我在最后一张表中,随便找个表格添加许多的字符”jjjjjjjjjjj”
然后点击保存。再次打开后,点击第二个表“” 一样会崩溃。这样就可以用od载入excel,然后搜索字符串”jjjjjjjjjjjjjjjjjj” 找到这个在内存中的位置(一般是unicode类型)。(shellcode最好按这种方式添加,先用字符串站位,直接在excel中用二进制文件打开写不一定行,很容易写坏文件格式或者写了之后根本不读入内存)(个人看法,不知道别人是不是这样:)。

这里后面会填入shellcode,先作为标记。
这里回到上面分析的地方30177D15
30177D15 . 8B0490 MOV EAX,DWORD PTR DS:[EAX+EDX*4]==eax=05B46250
30177D18 . 3BC6 CMP EAX,ESI
30177D1A . 74 1E JE SHORT EXCEL.30177D3A
30177D1C . 0FB708 MOVZX ECX,WORD PTR DS:[EAX]
30177D1F . 894D 10 MOV DWORD PTR SS:[EBP+10],ECX
30177D22 . 41 INC ECX
30177D23 . 51 PUSH ECX
30177D24 . FF75 0C PUSH DWORD PTR SS:[EBP+C]
30177D27 . 83C0 02 ADD EAX,2
30177D2A . 50 PUSH EAX
30177D2B . E8 6345E9FF CALL EXCEL.3000C293
这里我们需要构造这样的数据:
EAX+EDX*4 指向的内存中我们的shellcode,而且这个内存的前2个字节是要拷贝的长度。
测试中发现这个EDX中的CC不能改成C6,改成80以下都不行。
而BB可以改成任意值。
(FFFF0000+XX<<8+YY)*4
XX>=0x80;
Y 属于N
这里就要我们自己构造这样的EDX了 同时要保证索引后指向的内存里面存放了我们shellcode的地址,我们可以在excel中添加更多的垃圾数据来定位,多试验几次。
我这里设置的是edx= FFFFCB50
如下图:

(好像不是很通用,有时地址会变….:)
5.2 about exploit
此时拷贝的源和大小我们都可以控制了,接下来开始利用了
由于excel对字符的处理,这里要用unicode的shellcode来进行利用。同时返回地址利用的jmp esp(或其他指令)需要时unicode类型的.,同时momove拷贝之后,还需要经过很长的路才能执行到返回地址处,中间就会导致异常,故打算采用SEH的方式来进行利用

可知最近的SEH处理函数时处于堆栈0x0013F890,只要覆盖这个SEH即可。(必须是UNICODE)
找一个指令序列是pop xx popxx retn(不仅限于)即可返回的时候跳到堆栈0013F890处执行,此处已经被我们的控制。
覆盖SEH时,各寄存器值以及堆栈值

过SEH可以使用的指令
Pop xx
Pop xx
Retn
Call dword ptr [ebp]
Jmp dword ptr [ebp]
Call dword ptr [esp+2c]
Call dword ptr [esp+8]
…..
Ps :暂时并没有找到合适的地址,没有成功利用… 接下来就看你的了 :)