作者: nine8
QQ : 279933462
杂记: http://hi.baidu.com/tapeout
MS11-015微软补了Media Player的2个漏洞,其中库预加载的可以导致远程执行代码,但是第二个感觉只是导致后面解码时的错误不会导致远程执行代码:
1). DLL库预加载的, 通过构造相关的dll文件,涉及到dvr-ms, mpg和mtv文件类型的打开时可能会加载,导致远程执行代码。
2). Media Player在播放dvr-ms文件时,会调用Stream Buffer Engine来处理dvr-ms文件流, 在处理的时候sbe.dll中的问题导致可能存在的处理错误,但是个人分析感觉不能
被利用远程执行代码。(另外也可能是我分析的错误,或是出现问题的地方定位就不对)。
由于没有POC,以及对触发问题的dvr-ms文件格式不熟悉,相关东西都是现看的,所以分析中可能会有很多问题,如果大家发现,还请给小弟多多指出,感谢!
下面对MS11-015的DVR-MS 漏洞 CVE-2011-0042, 做简要的分析。对于CVE-2011-0032,由于不涉及WinXP, VM里跑vista或win7很不顺畅,这里就先没有分析.
0x01 相关概要
--------------------------
== 0x11 调试环境: VMware7.0 + en_windows_xp_professional_with_service_pack_3_x86
== 0x12 漏洞编号: MS11-015, CVE-2011-0042
== 0x13 问题文件: c:\windows\system32\sbe.dll
== 0x14 名词摘要: (摘录自微软MSDN)
1) . 流缓冲引擎 (SBE)。利用 SBE,应用程序可以搜索、暂停以及录制实时视频流,而不会中断该流。实时内容和录制内容之间的转换为无缝转换。现在,
SBE 支持 MPEG-2 视频和数字视频 (DV) 源,捕获速率高达每秒 30 兆比特 (Mbps)。
2). 在 Microsoft Windows XP Media Center Edition 中,Microsoft 已引入了 *.dvr-ms 文件格式。类似于 *.asf 格式,*.dvr-ms 文件增强了允
许创建关键PVR 的功能,其中包括时光平移、实时暂停以及同时录制和播放。
0x02 问题分析
---------------------------
.text:4EE52F2F public: static long __stdcall DShowWMSDKHelpers::RecoverNewMediaType(struct INSSBuffer3 *, struct _AMMediaType * *) proc near .text:4EE52F2F .text:4EE52F2F var_4= dword ptr -4 .text:4EE52F2F pINSSBuffer3= dword ptr 8 ; 第一个参数指向INSSBuffer3 .text:4EE52F2F ppAMMediaType= dword ptr 0Ch ; 第二个参数指向AMMediaType指针 .text:4EE52F2F .text:4EE52F2F mov edi, edi .text:4EE52F31 push ebp .text:4EE52F32 mov ebp, esp .text:4EE52F34 push ecx .text:4EE52F35 push ebx .text:4EE52F36 push esi .text:4EE52F37 mov ebx, [ebp+pINSSBuffer3] .text:4EE52F3A push edi .text:4EE52F3B mov eax, [ebx] .text:4EE52F3D lea ecx, [ebp+var_4] .text:4EE52F40 push ecx ; Buffer大小 .text:4EE52F41 push 0 ; 将接收属性内容的Buffer指向NULL, 获取所需大小空间 .text:4EE52F43 sub esp, 10h .text:4EE52F46 mov edi, esp .text:4EE52F48 mov esi, offset _INSSBuffer3Prop_DShowNewMediaType : 这里是下面要获取的属性GUID .text:4EE52F4D movsd ; DShowNewMediaType .text:4EE52F4E movsd :1135BEB7-3A39-47BA-D998-69Eb006BC715 .text:4EE52F4F movsd .text:4EE52F50 push ebx ; INSSBuffer3 * .text:4EE52F51 movsd .text:4EE52F52 call dword ptr [eax+2Ch] ; 通过INSSBuffer3的GetProperty获取DShowNewMediaType属性内容 .text:4EE52F55 mov esi, eax ; 这里也是通过逆向分析才推出是调用的GetProperty,之前并不知道功能。 .text:4EE52F57 test esi, esi .text:4EE52F59 jl loc_4EE5300F
上面的代码主要是通过GetProperty函数,通过将接收字符的buffer指向NULL,来获取所需的Buffer大小,关于GetProperty的实现细节,后面内容会有详细的逆向分析,
以及简单猜测INSSBuffer3结构和查找GUID内容的过程。GetProperty的COM接口如下:
HRESULT ( STDMETHODCALLTYPE *GetProperty )( INSSBuffer3 * This, /* [in] */ GUID guidBufferProperty, /* [out] */ void *pvBufferProperty, /* [out][in] */ DWORD *pdwBufferPropertySize);
.text:4EE52F5F push [ebp+var_4] ; 这里为通过上面获取的所需存储GUID内容的空间大小 .text:4EE52F62 call operator new(uint) ; 开辟内存空间, 之后出现问题的地方会涉及到这片空间内容 !!! .text:4EE52F67 test eax, eax .text:4EE52F69 pop ecx .text:4EE52F6A mov [ebp+pINSSBuffer3], eax .text:4EE52F6D jz loc_4EE5300
下面再次通过INSSBuffer3的GetProperty获取DShowNewMediaType GUID对应的内容,并存入上面开辟的动态空间。
.text:4EE52F73 mov ecx, [ebx] .text:4EE52F75 lea edx, [ebp+var_4] .text:4EE52F78 push edx ; 所需接收空间大小,单位byte .text:4EE52F79 push eax ; 接收buffer指向上面开辟的空间 .text:4EE52F7A sub esp, 10h .text:4EE52F7D mov edi, esp .text:4EE52F7F mov esi, offset _INSSBuffer3Prop_DShowNewMediaType ; GUID .text:4EE52F84 movsd .text:4EE52F85 movsd .text:4EE52F86 movsd .text:4EE52F87 push ebx .text:4EE52F88 movsd .text:4EE52F89 call dword ptr [ecx+2Ch] ; NSSBuffer3 GetProperty .text:4EE52F8C mov esi, eax .text:4EE52F8E test esi, esi .text:4EE52F90 jl short loc_4EE52FFF
.text:4EE52F92 push 48h ; cb ; 0x48 bytes, 为AMMediaType结构大小 .text:4EE52F94 call ds:CoTaskMemAlloc(x) ; 开辟AMMediaType结构所需的0x48 bytes空间 .text:4EE52F9A test eax, eax .text:4EE52F9C mov ebx, [ebp+ppAMMediaType] .text:4EE52F9F mov [ebx], eax .text:4EE52FA1 jz short loc_4EE5
typedef struct _MediaType { // total size: 0x48 GUID majortype; // offset 0x00 GUID subtype; // offset 0x10 BOOL bFixedSizeSamples; // offset 0x20 BOOL bTemporalCompression; // offset 0x24 ULONG lSampleSize; // offset 0x28 GUID formattype; // offset 0x2C IUnknown *pUnk; // offset 0x3c ULONG cbFormat; // offset 0x40 <------- 可选数据大小,该成员会涉及到该漏洞的产生 [size_is(cbFormat)] BYTE *pbFormat; // offset 0x44 <------- 指向可选数据内容 } AM_MEDIA_TYPE;
下面将查询到GUID: DShowNewMediaType的内容的前0x48 bytes存入AMMediaType结构的空间中
.text:4EE52FA3 mov esi, [ebp+pINSSBuffer3] ; 指向new开辟的空间 .text:4EE52FA6 push 12h .text:4EE52FA8 mov edi, eax ; 指向CoTaskMemAlloc开辟的空间 .text:4EE52FAA pop ecx .text:4EE52FAB rep movsd .text:4EE52FAD mov eax, [ebx] .text:4EE52FAF mov ecx, [eax+40h] ; 这里通过可选数据大小判断是否有可选数据,如果有下面会继续开辟空间 .text:4EE52FB2 test ecx, ecx .text:4EE52FB4 jbe short loc_4EE
下面就是问题出现的地方了
.text:4EE52FB6 push ecx ; cb ; 根据AMMediaType的cbFormat大小,开辟对应的空间 .text:4EE52FB7 call ds:CoTaskMemAlloc(x) .text:4EE52FBD mov ecx, [ebx] .text:4EE52FBF mov [ecx+44h], eax ; 将指针存入AMMediaType结构的pbFormat成员 .text:4EE52FC2 mov ebx, [ebx] .text:4EE52FC4 mov edi, [ebx+44h] .text:4EE52FC7 test edi, edi .text:4EE52FC9 jz short loc_4EE
根据cbFormat的大小,将pbFormat的数据从GUID Buffer中赋值到pbFormat指向的空间,因为这里是根据cbFormat的大小,而并没有判断
GUID Buffer中从单次采样中实际或到属性内容的大小,那么如果构造畸形cbformat,使cbFormat + AMMediaType的48字节大于GUID Buffer中从GUID后的
QWORD size得到的实际所需大小(这里的QWORD Size是通过分析GetProperty得知的下面会具体分析),为GUIID后的第一个
QWORD.那么将会出现超过实际QWORD size提供大小后,后面所存入到pbFormat的额外数据信息将是从New堆后的无效数据,从而可能导致后面encdec时的
错误,但这里因为是从小复到大所以不会产生堆溢出,所以个人感觉这个漏洞,不会被利用远程执行代码。当然前面也提到可能我分析的不对,定位不准确,没有找到
真正问题的地方。
.text:4EE52FCB mov ecx, [ebx+40h] .text:4EE52FCE mov esi, [ebp+pINSSBuffer3] .text:4EE52FD1 mov eax, ecx .text:4EE52FD3 shr ecx, 2 .text:4EE52FD6 add esi, 48h .text:4EE52FD9 rep movsd .text:4EE52FDB mov ecx, eax .text:4EE52FDD and ecx, 3 .text:4EE52FE0 rep movsb
下面分析下涉及到的INSSBuffer3的GetProperty方法,因为通过其获取的GUID DShowNewMediaType内容和如何返回Buffer大小,会影响问题形成的buffer大小信息。见2楼
