调试方法:
WINDBG载入iexplore.exe,命令行参数为PoC网页路径,第一次停在系统断点,放行之:
跑起来后IE7会出现为了保护安全性已阻止有关内容执行的条子,这时先在windbg里暂停回到调试器。
在其下位置(jscript!IDispatchExGetDispID中)
.text:75BE3064 call dword ptr [ecx+1Ch] ; mshtml!TearoffThunk7
下硬件执行断点(这样下断是因为这时jscript.dll还没有加载,不能bp),g执行:
这时可以点击允许相关内容执行,很快断下:
记下这个eax=001897e0,即之后内存破坏的位置。
继续单步可以看清楚正常的流程,即分析中的第2点,可以看到正确的流程是跳到mshtml!COmWindowProxy::subGetDispID。
取消刚刚设的断点,对导致内存破坏的始作俑者iepeers.dll!CPersistUserData::setAttribute下断,运行断下:
单步直接看到对OLEAUT32!VariantChangeTypeEx的调用:
单步步进,看到源Variant指针为0x019dc9b4,并从其中取到对应的类指针,正是0x001897e0。
单步步进直到看到对OLEAUT32!ExtractValueProperty的调用,注意其第一个参数(最后push的那个)正是esi=001897e0。
p步过,不要进去OLEAUT32!ExtractValueProperty,跟踪发现它并没有减少访问计数,继续步进直到对OLEAUT32!VariantClear的调用,注意到对OLEAUT32!VariantClear调用传入
的参数即目的Variant指针仍为0x019dc9b4,与源指针一致,这样这个调用导致对相应的对象即0x001897e0指向的TearoffThunk对象的访问计数减1(如果想要深入可以步入其中,
就可以发现把访问计数减1的就是mshtml!PlainRelease):
步过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:
最后,把最早的那个断点重新搞上,不过这次加上条件,让它在下次访问相应TearoffThunk结构的时候正好被断下:
步进去,最终的过程就有了:
最后是变成jmp 0x0f09f883,以一个Access Violation异常告终: