百度空间 | 百度首页 
 
查看文章
 
MS09-002,刚刚触发了一下(二)
2009-02-21 22:57

前面已经知道call进shellcode的代码位于mshtml!CFunctionPointer::PrivateAddRef

用IDA加载mshtml.dll,找到mshtml!CFunctionPointer::PrivateAddRef函数:
.text:42AF7811 public: virtual unsigned long __stdcall CFunctionPointer::PrivateAddRef(void) proc near
.text:42AF7811                                         ; DATA XREF: .text:42A3B3C4 o
.text:42AF7811

从函数头部的交叉参考进入,可以看到它被一个常量所引用:
.text:42A3B3C0 const CFunctionPointer::`vftable' dd offset CFunctionPointer::PrivateQueryInterface(_GUID const &,void * *)
.text:42A3B3C0                                         ; DATA XREF: CFunctionPointer::CFunctionPointer(CBase *,long)+15 o
.text:42A3B3C0                                         ; CElement::get_nodeType(long *)+1660 o
.text:42A3B3C4                 dd offset CFunctionPointer::PrivateAddRef(void)
.text:42A3B3C8                 dd offset CFunctionPointer::PrivateRelease(void)

这里可以说是一个messages dispatcher的表了,这个位置又被CFunctionPointer::CFunctionPointer所引用。CFunctionPointer::CFunctionPointer是一个类的构造函数:

.text:42AF79D9 public: __thiscall CFunctionPointer::CFunctionPointer(class CBase *, long) proc near
.text:42AF79D9                                         ; CODE XREF: CBase::ContextInvokeEx(long,ulong,ushort,tagDISPPARAMS *,tagVARIANT *,tagEXCEPINFO *,IServiceProvider *,IUnknown *)+AF361 p
.text:42AF79D9
.text:42AF79D9 arg_0           = dword ptr 8
.text:42AF79D9 arg_4           = dword ptr 0Ch
.text:42AF79D9
.text:42AF79D9 ; FUNCTION CHUNK AT .text:42B3F2C0 SIZE 00000020 BYTES
.text:42AF79D9
.text:42AF79D9                 mov     edi, edi
.text:42AF79DB                 push    ebp
.text:42AF79DC                 mov     ebp, esp
.text:42AF79DE                 push    esi
.text:42AF79DF                 mov     esi, ecx
.text:42AF79E1                 call    CBase::CBase(void)
.text:42AF79E1
.text:42AF79E6                 mov     ecx, [ebp+arg_0]
.text:42AF79E9                 test    ecx, ecx
.text:42AF79EB                 mov     eax, [ebp+arg_4]
.text:42AF79EE                 mov     dword ptr [esi], offset const CFunctionPointer::`vftable'
.text:42AF79F4                 mov     [esi+10h], ecx
.text:42AF79F7                 mov     [esi+14h], eax
.text:42AF79FA                 jz      short loc_42AF7A19
.text:42AF79FA
.text:42AF79FC                 mov     eax, [ecx]
.text:42AF79FE                 call    dword ptr [eax+34h]
.text:42AF7A01                 test    eax, eax
.text:42AF7A03                 mov     [esi+18h], eax
.text:42AF7A06                 jz      loc_42B3F2C0
.text:42AF7A06
.text:42AF7A0C
.text:42AF7A0C loc_42AF7A0C:                           ; CODE XREF: CFunctionPointer::CFunctionPointer(CBase *,long)+47902 j
.text:42AF7A0C                 mov     eax, [esi+18h]
.text:42AF7A0F                 test    eax, eax
.text:42AF7A11                 jz      short loc_42AF7A19
.text:42AF7A11
.text:42AF7A13                 mov     ecx, [eax]
.text:42AF7A15                 push    eax
.text:42AF7A16                 call    dword ptr [ecx+4]
.text:42AF7A16
.text:42AF7A19
.text:42AF7A19 loc_42AF7A19:                           ; CODE XREF: CFunctionPointer::CFunctionPointer(CBase *,long)+21 j
.text:42AF7A19                                         ; CFunctionPointer::CFunctionPointer(CBase *,long)+38 j
.text:42AF7A19                 mov     eax, esi
.text:42AF7A1B                 pop     esi
.text:42AF7A1C                 pop     ebp
.text:42AF7A1D                 retn    8

那么微软怎么把这个漏洞改掉的呢?打上KB961260补丁,我们返回来看刚刚那个表:

.text:42A39708 const CFunctionPointer::`vftable' dd offset CFunctionPointer::PrivateQueryInterface(_GUID const &,void * *)
.text:42A39708                                         ; DATA XREF: CFunctionPointer::CFunctionPointer(CBase *,long)+15 o
.text:42A39708                                         ; CElement::get_nodeType(long *)+1658 o
.text:42A3970C                 dd offset CIVersionVectorThunk::AddRef(void)
.text:42A39710                 dd offset CBase::PrivateRelease(void)

把CFunctionPointer::PrivateAddRef从表上换掉了,换成了CIVersionVectorThunk::AddRef(void),这个函数的动作:

.text:42A4156D public: virtual unsigned long __stdcall CIVersionVectorThunk::AddRef(void) proc near
.text:42A4156D                                         ; DATA XREF: .text:42A0355C o
.text:42A4156D                                         ; .text:42A38434 o
.text:42A4156D                                         ; .text:42A384B4 o
.text:42A4156D                                         ; .text:42A38534 o
.text:42A4156D                                         ; .text:42A385BC o
.text:42A4156D                                         ; .text:42A38644 o ...
.text:42A4156D
.text:42A4156D arg_0           = dword ptr 8
.text:42A4156D
.text:42A4156D                 mov     edi, edi
.text:42A4156F                 push    ebp
.text:42A41570                 mov     ebp, esp
.text:42A41572                 mov     eax, [ebp+arg_0]
.text:42A41575                 inc     dword ptr [eax+4]
.text:42A41578                 xor     eax, eax
.text:42A4157A                 pop     ebp
.text:42A4157B                 retn    4
.text:42A4157B
.text:42A4157B public: virtual unsigned long __stdcall CIVersionVectorThunk::AddRef(void) endp

与之前的CFunctionPointer::PrivateAddRef对比可以发现,现在的CIVersionVectorThunk::AddRef只是设置一个引用计数(inc     dword ptr [eax+4]),没有其他调用了。

同时修改的还有CFunctionPointer::PrivateRelease,在表中它的位置直接被替换成了基类的方法CBase::PrivateRelease。

看看修改前的CFunctionPointer::PrivateRelease函数:

.text:42B1E30D public: virtual unsigned long __stdcall CFunctionPointer::PrivateRelease(void) proc near
.text:42B1E30D                                         ; DATA XREF: .text:42A3B3C8 o
.text:42B1E30D
.text:42B1E30D arg_0           = dword ptr 8
.text:42B1E30D
.text:42B1E30D                 mov     edi, edi
.text:42B1E30F                 push    ebp
.text:42B1E310                 mov     ebp, esp
.text:42B1E312                 push    esi
.text:42B1E313                 mov     esi, [ebp+arg_0]
.text:42B1E316                 cmp     dword ptr [esi+10h], 0
.text:42B1E31A                 jz      loc_42B22250
.text:42B1E31A
.text:42B1E320                 cmp     dword ptr [esi+4], 1
.text:42B1E324                 jbe     loc_42B22250
.text:42B1E324
.text:42B1E32A                 add     dword ptr [esi+8], 8
.text:42B1E32E                 push    edi
.text:42B1E32F                 push    esi
.text:42B1E330                 call    CBase::PrivateRelease(void)
.text:42B1E330
.text:42B1E335                 mov     edi, eax
.text:42B1E337                 mov     eax, [esi+10h]
.text:42B1E33A                 mov     ecx, [eax]
.text:42B1E33C                 push    eax
.text:42B1E33D                 call    dword ptr [ecx+8]
.text:42B1E340                 mov     ecx, esi
.text:42B1E342                 call    CBase::SubRelease(void)
.text:42B1E342
.text:42B1E347                 mov     eax, edi
.text:42B1E349                 pop     edi
.text:42B1E349
.text:42B1E34A
.text:42B1E34A loc_42B1E34A:                           ; CODE XREF: CElement::get_nodeType(long *)+1627 j
.text:42B1E34A                 pop     esi
.text:42B1E34B                 pop     ebp
.text:42B1E34C                 retn    4
.text:42B1E34C
.text:42B1E34C public: virtual unsigned long __stdcall CFunctionPointer::PrivateRelease(void) endp

显然也存在与CFunctionPointer::PrivateAddRef相类似的问题,可能call进shellcode中。现在换成了CBase::PrivateRelease,同样也就是直接把对象的引用计数标志减1而已。


类别:默认分类 | 添加到搜藏 | 浏览() | 评论 (1)
 
最近读者:
 
网友评论:
1
2009-02-22 12:56 | 回复
和前一个漏洞是多么的相像
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu