今天来点干货:研究 IE 开发者工具的调用。如果你只是想知道怎么调用的话,可以直接查看我的开源项目 SuperF12。下面的内容是我整个的分析过程,所谓授之以鱼莫若授之以渔,我这里提供的是一种解决问题的思路和方法。
首先,用 IE 把开发者工具显示出来。然后用 Spy++ 看该窗口的信息:
需要关注的地方已经被我高亮出来了。接下来,使用 Process Explorer 来查看窗口过程的所在位置。
是时候启动调试器了。打开 WinDbg,Attach 一个新的 IE 子进程,并监控 iedvtool.dll 的加载:
sxe ld iedvtool.dll
接着在 IE 中打开开发者工具,调试器中断下来。查看其堆栈:
ChildEBP RetAddr
02fda46c 77465c34 ntdll!KiFastSystemCallRet
02fda470 7748060d ntdll!NtMapViewOfSection+0xc
02fda4c4 774806ea ntdll!LdrpMapViewOfSection+0xc7
02fda55c 7747fb51 ntdll!LdrpFindOrMapDll+0x303
02fda6dc 774822b2 ntdll!LdrpLoadDll+0x2b2
02fda710 757a8b51 ntdll!LdrLoadDll+0x92
02fda74c 76079d43 KERNELBASE!LoadLibraryExW+0x1d3
02fda768 76079cc7 ole32!LoadLibraryWithLogging+0x16
02fda78c 76079bb6 ole32!CClassCache::CDllPathEntry::LoadDll+0xa9
02fda7bc 760790be ole32!CClassCache::CDllPathEntry::Create_rl+0x37
02fdaa08 76078f93 ole32!CClassCache::CClassEntry::CreateDllClassEntry_rl+0xd4
02fdaa50 76078e99 ole32!CClassCache::GetClassObjectActivator+0x224
02fdaa88 76078c57 ole32!CClassCache::GetClassObject+0x30
02fdab04 76093170 ole32!CServerContextActivator::CreateInstance+0x110
02fdab44 76078dca ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108
02fdab98 76078d3f ole32!CApartmentActivator::CreateInstance+0x112
02fdabb8 76078ac2 ole32!CProcessActivator::CCICallback+0x6d
02fdabd8 76078a73 ole32!CProcessActivator::AttemptActivation+0x2c
02fdac14 76078e2d ole32!CProcessActivator::ActivateByContext+0x4f
02fdac3c 76093170 ole32!CProcessActivator::CreateInstance+0x49
02fdac7c 76092ef4 ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108
02fdaedc 76093170 ole32!CClientContextActivator::CreateInstance+0xb0
02fdaf1c 76093098 ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108
02fdb6f4 76099e25 ole32!ICoCreateInstanceEx+0x404
02fdb754 76099d86 ole32!CComActivator::DoCreateInstance+0xd9
02fdb778 76099d3f ole32!CoCreateInstanceEx+0x38
02fdb7a8 6bebe0d5 ole32!CoCreateInstance+0x37
运行至 CoCreateInstance 即将退出的代码行,查看各个参数:
0:005> dd ebp
02fdb7a8 02fdb7cc 6bebe0d5 6bf07ebc 00000000
02fdb7b8 00000001 6bfad788 0069e488 6bf07ecc
能得到开发者工具的 CLSID 和 IID:
0:005> dt _GUID 6bf07ebc
ntdll!_GUID
{1a6fe369-f28c-4ad9-a3e6-2bcb50807cf1}
+0x000 Data1 : 0x1a6fe369
+0x004 Data2 : 0xf28c
+0x006 Data3 : 0x4ad9
+0x008 Data4 : [8] "???"
0:005> dt _GUID 6bfad788
ntdll!_GUID
{059055df-6bb0-402a-ba48-58bfa343719c}
+0x000 Data1 : 0x59055df
+0x004 Data2 : 0x6bb0
+0x006 Data3 : 0x402a
+0x008 Data4 : [8] "???"
然后用 IDA 拆开 iedvtool.dll,可以得到开发者工具接口的虚表:
最后将其整理成易懂的格式:
class IIEDevToolsExplorerBar : public IUnknown
{
public:
STDMETHOD(SetDevToolSite)(IEDevToolsSite *site) PURE;
STDMETHOD(ShowDevTools)(BOOL b) PURE;
STDMETHOD(JITShowDevTools)(int) PURE;
STDMETHOD(CloseDevTools)(void) PURE;
STDMETHOD(IsVisible)(BOOL *) PURE;
STDMETHOD(GetPinState)(BOOL *) PURE;
STDMETHOD(SetPinState)(BOOL bPin) PURE;
STDMETHOD(IsMinimized)(BOOL *) PURE;
STDMETHOD(DevToolsReady)(void) PURE;
};
static const CLSID CLSID_IEDTExplorerBar = {
0x1a6fe369, 0xf28c, 0x4ad9, { 0xa3, 0xe6, 0x2b, 0xcb, 0x50, 0x80, 0x7c, 0xf1 }
};
static const IID IID_IEDTExplorerBar = {
0x059055df, 0x6bb0, 0x402a, { 0xba, 0x48, 0x58, 0xbf, 0xa3, 0x43, 0x71, 0x9c }
};
末了补充一点。IE11 之中引入了新的开发者工具组件 F12Tools.dll,这个组件和 IE 的耦合度非常大,我至今未能找出如何成功调用它的方法。若已有看官知其奥秘还请不吝赐教,拜谢。