CVE-2012-0158 MSCOMCTL控件漏洞分析
2015-12-24 00:49
603 查看
参考:http://bbs.pediy.com/showthread.php?t=149957(样本是此链接提供的样本)
环境 :
xp sp3 / word2007
运行样本后,会弹出计算器
因为此类型的exp的shellcode 在运行的时候都会释放文件,释放文件时需要调用kernel32.dll 中的GetFileSize函数来判断需要释放的文件,
所以在windbg开始调试poc时,在GetFileSize函数下断点,bu kernel32!GetFileSize,但是word运行时会调用很多次GetFileSize,直接下断点的话,会执行很多次。
我们知道漏洞出现在MSCOMCTL.OCX中,因此我们可以等待加载MSCOMCTL.OCX后在对GetFileSize下断点
加载MSCOMCTL.OCX模块时会断下来
然后g运行程序,程序停在GetFileSize处,
然后gu跳出GetFileSize函数,程序已经进入shellcode区域
观察右下角堆栈调用,可知上层调用位于
地址位于275c8a0a 处。猜测出现问题的地方就在此附近。
IDA打开MSCOMCTL.OCX模块,定位到275c8a0a处附近
发编译如下:
根据上结果可以大致判断,异常出现原因是因为对字符串长度判断出问题,导致溢出。
下面使用OD具体跟踪下情况:
因为MSCOMCTL.OCX 并不在word运行起来就加载,所以一开始是不能对MSCOMCTL.OCX中的地址进行断点设置的,但是一般模块的加载都是是哟用函数LoadLibraryA函数的,
因此可以在LoadLibraryA下断点(不要一开始就下断点,因为word运行时会加载很多断点)
OD加载may.doc, F9运行,出现提示(之前运行过样本)
此时MSCOMCTL.OCX模块还未被加载,如下:
此时在LoadLibraryA函数下断点,然后点击上图提示中的打开word
此时程序断在LoadLibraryA 函数处,在查看程序加载模块,此时MSCOMCTL.OCX已经被加载
此时就可以在MSCOMCTL.OCX模块中下断点了,由windbg可知,异常点在MSCOMCTL!DllGetClassObject+0x41cc6附近
跟踪可知,第二次执行问call 275C876D 后,函数的返回地址被覆盖,参见下两图
进入函数:
第二次执行问call 275C876D后,
可见堆栈上的返回地址已经被7ffa4512覆盖了,此地址即是jmp esp的地址。
如果你进入275C876D 函数中,清楚的看到数据拷贝的过程(也就IDA反编译中的那两个关键函数)
知道覆盖地址,知道覆盖点,剩下的就是shellcode了
环境 :
xp sp3 / word2007
运行样本后,会弹出计算器
因为此类型的exp的shellcode 在运行的时候都会释放文件,释放文件时需要调用kernel32.dll 中的GetFileSize函数来判断需要释放的文件,
所以在windbg开始调试poc时,在GetFileSize函数下断点,bu kernel32!GetFileSize,但是word运行时会调用很多次GetFileSize,直接下断点的话,会执行很多次。
我们知道漏洞出现在MSCOMCTL.OCX中,因此我们可以等待加载MSCOMCTL.OCX后在对GetFileSize下断点
sxe ld:MSCOMCTL.OCX
加载MSCOMCTL.OCX模块时会断下来
0:000> g (278.288): Unknown exception - code e0000002 (first chance) ModLoad: 27580000 27685000 C:\WINDOWS\system32\MSCOMCTL.OCX eax=00000000 ebx=00000000 ecx=03c30000 edx=7c92e4f4 esi=00000000 edi=00000000 eip=7c92e4f4 esp=0012392c ebp=00123a20 iopl=0 nv up ei ng nz ac pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000296 ntdll!KiFastSystemCallRet: 7c92e4f4 c3 ret 0:000> bp kernel32!GetFileSize 0:000> bl 0 e 7c810b07 0001 (0001) 0:**** kernel32!GetFileSize
然后g运行程序,程序停在GetFileSize处,
然后gu跳出GetFileSize函数,程序已经进入shellcode区域
观察右下角堆栈调用,可知上层调用位于
MSCOMCTL!DllGetClassObject+0x41cc6 处
u MSCOMCTL!DllGetClassObject+0x41cc6 MSCOMCTL!DllGetClassObject+0x41cc6: 275c8a0a 8bf0 mov esi,eax 275c8a0c 83c40c add esp,0Ch 275c8a0f 85f6 test esi,esi 275c8a11 7c3d jl MSCOMCTL!DllGetClassObject+0x41d0c (275c8a50) 275c8a13 837df800 cmp dword ptr [ebp-8],0 275c8a17 8b7d08 mov edi,dword ptr [ebp+8] 275c8a1a 742a je MSCOMCTL!DllGetClassObject+0x41d02 (275c8a46) 275c8a1c 83650c00 and dword ptr [ebp+0Ch],0
地址位于275c8a0a 处。猜测出现问题的地方就在此附近。
IDA打开MSCOMCTL.OCX模块,定位到275c8a0a处附近
.text:275C89C7 ; int __stdcall sub_275C89C7(int, BSTR bstrString) .text:275C89C7 sub_275C89C7 proc near ; CODE XREF: sub_275C8807+10p .text:275C89C7 ; sub_275E7004+11p ... .text:275C89C7 .text:275C89C7 var_14 = dword ptr -14h .text:275C89C7 dwBytes = dword ptr -0Ch .text:275C89C7 var_8 = dword ptr -8 .text:275C89C7 var_4 = dword ptr -4 .text:275C89C7 arg_0 = dword ptr 8 .text:275C89C7 bstrString = dword ptr 0Ch .text:275C89C7 .text:275C89C7 ; FUNCTION CHUNK AT .text:275D3085 SIZE 0000001D BYTES .text:275C89C7 .text:275C89C7 push ebp .text:275C89C8 mov ebp, esp .text:275C89CA sub esp, 14h .text:275C89CD push ebx .text:275C89CE mov ebx, [ebp+bstrString] .text:275C89D1 push esi .text:275C89D2 push edi .text:275C89D3 push 0Ch ; dwBytes .text:275C89D5 lea eax, [ebp+var_14] .text:275C89D8 push ebx ; lpMem .text:275C89D9 push eax ; int .text:275C89DA call __keyfun .text:275C89DF add esp, 0Ch .text:275C89E2 test eax, eax .text:275C89E4 jl short loc_275C8A52 .text:275C89E6 cmp [ebp+var_14], 6A626F43h .text:275C89ED jnz loc_275D3085 .text:275C89F3 cmp [ebp+dwBytes], 8 .text:275C89F7 jb loc_275D3085 .text:275C89FD push [ebp+dwBytes] ; dwBytes .text:275C8A00 lea eax, [ebp+var_8] .text:275C8A03 push ebx ; lpMem .text:275C8A04 push eax ; int .text:275C8A05 call __keyfun .text:275C8A0A mov esi, eax .text:275C8A0C add esp, 0Ch .text:275C8A0F test esi, esi .text:275C8A11 jl short loc_275C8A50 .text:275C8A13 cmp [ebp+var_8], 0 .text:275C8A17 mov edi, [ebp+arg_0] .text:275C8A1A jz short loc_275C8A46 .text:275C8A1C and [ebp+bstrString], 0 .text:275C8A20 lea eax, [ebp+bstrString] .text:275C8A23 push ebx ; int .text:275C8A24 push eax ; len .text:275C8A25 call sub_275C8A59 .text:275C8A2A mov esi, eax .text:275C8A2C pop ecx .text:275C8A2D test esi, esi .text:275C8A2F pop ecx .text:275C8A30 jl short loc_275C8A50 .text:275C8A32 push [ebp+bstrString] ; strIn .text:275C8A35 lea ecx, [edi-24h] .text:275C8A38 call sub_27585BE7 .text:275C8A3D push [ebp+bstrString] ; bstrString .text:275C8A40 call ds:SysFreeString .text:275C8A46 .text:275C8A46 loc_275C8A46: ; CODE XREF: sub_275C89C7+53j .text:275C8A46 cmp [ebp+var_4], 0 .text:275C8A4A jnz loc_275D308F .text:275C8A50 .text:275C8A50 loc_275C8A50: ; CODE XREF: sub_275C89C7+4Aj .text:275C8A50 ; sub_275C89C7+69j ... .text:275C8A50 mov eax, esi .text:275C8A52 .text:275C8A52 loc_275C8A52: ; CODE XREF: sub_275C89C7+1Dj .text:275C8A52 ; sub_275C89C7+A6C3j .text:275C8A52 pop edi .text:275C8A53 pop esi .text:275C8A54 pop ebx .text:275C8A55 leave .text:275C8A56 retn 8 .text:275C8A56 sub_275C89C7 endp
发编译如下:
int __stdcall sub_275C89C7(int a1, BSTR bstrString) { BSTR v2; // ebx@1 int result; // eax@1 int v4; // esi@4 int v5; // [sp+Ch] [bp-14h]@1 SIZE_T dwBytes; // [sp+14h] [bp-Ch]@3 int v7; // [sp+18h] [bp-8h]@4 int v8; // [sp+1Ch] [bp-4h]@8 v2 = bstrString; result = _keyfun((int)&v5, bstrString, 0xCu); if ( result >= 0 ) { if ( v5 == 1784835907 && dwBytes >= 8 ) { v4 = _keyfun((int)&v7, v2, dwBytes); if ( v4 >= 0 ) { if ( !v7 ) goto LABEL_8; bstrString = 0; v4 = sub_275C8A59((UINT)&bstrString, (int)v2); if ( v4 >= 0 ) { sub_27585BE7(bstrString); SysFreeString(bstrString); LABEL_8: if ( v8 ) v4 = sub_275C8B2B(a1 + 20, v2); return v4; } } return v4; } result = -2147418113; } return result; }
int __cdecl _keyfun(int a1, LPVOID lpMem, SIZE_T dwBytes) { LPVOID v3; // ebx@1 int result; // eax@1 LPVOID v5; // eax@3 int v6; // esi@4 int v7; // [sp+Ch] [bp-4h]@1 LPVOID lpMema; // [sp+1Ch] [bp+Ch]@3 v3 = lpMem; result = (*(int (__stdcall **)(LPVOID, int *, signed int, _DWORD))(*(_DWORD *)lpMem + 12))(lpMem, &v7, 4, 0); if ( result >= 0 ) { if ( v7 == dwBytes ) { v5 = HeapAlloc(hHeap, 0, dwBytes); lpMema = v5; if ( v5 ) { v6 = (*(int (__stdcall **)(LPVOID, LPVOID, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))(v3, v5, dwBytes, 0); if ( v6 >= 0 ) { qmemcpy((void *)a1, lpMema, dwBytes); v6 = (*(int (__stdcall **)(LPVOID, _UNKNOWN *, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))( v3, &unk_27632368, ((dwBytes + 3) & 0xFFFFFFFC) - dwBytes, 0); } HeapFree(hHeap, 0, lpMema); result = v6; } else { result = -2147024882; } } else { result = -2147418113; } } return result; }
根据上结果可以大致判断,异常出现原因是因为对字符串长度判断出问题,导致溢出。
下面使用OD具体跟踪下情况:
因为MSCOMCTL.OCX 并不在word运行起来就加载,所以一开始是不能对MSCOMCTL.OCX中的地址进行断点设置的,但是一般模块的加载都是是哟用函数LoadLibraryA函数的,
因此可以在LoadLibraryA下断点(不要一开始就下断点,因为word运行时会加载很多断点)
OD加载may.doc, F9运行,出现提示(之前运行过样本)
此时MSCOMCTL.OCX模块还未被加载,如下:
此时在LoadLibraryA函数下断点,然后点击上图提示中的打开word
此时程序断在LoadLibraryA 函数处,在查看程序加载模块,此时MSCOMCTL.OCX已经被加载
此时就可以在MSCOMCTL.OCX模块中下断点了,由windbg可知,异常点在MSCOMCTL!DllGetClassObject+0x41cc6附近
跟踪可知,第二次执行问call 275C876D 后,函数的返回地址被覆盖,参见下两图
进入函数:
第二次执行问call 275C876D后,
可见堆栈上的返回地址已经被7ffa4512覆盖了,此地址即是jmp esp的地址。
如果你进入275C876D 函数中,清楚的看到数据拷贝的过程(也就IDA反编译中的那两个关键函数)
知道覆盖地址,知道覆盖点,剩下的就是shellcode了
相关文章推荐
- iOS开发新手
- c#百度IP定位API使用方法
- 委托和多线程的理解
- Android Studio使用教程
- unity3d物理赛车系统
- java顺序结构之switch分支语句陷阱
- Android程序间数据的共享
- Swift 闭包(笔记)
- gcc编译提示pthread_create和pthread_detach未定义的引用的解决方法
- SignalR与ActiveMQ结合构建实时通信
- Python中用format函数格式化字符串的用法
- C++学习:函数指针
- 互联网广告的发展现状与趋势分析
- 牛顿迭代法与一道经典编程问题
- phpredis pipeline
- 解题报告:295. Find Median from Data Stream
- 我的第一篇博客文章!
- 参考C# 使用 System.Web.Script.Serialization 解析 JSON
- 美图秀秀首页界面设计(一)
- PlantUML的实例参考