对于 HOOK IDispatch.Invoke方法相比IDispatchEx要简单很多,查找函数地址也容易一些,毕竟IDispatchEx是IDispatch的扩展,关于IDispatchEx.InvokeEx钩子及代码参看
http://blog.csdn.net/zhoujianhei/archive/2008/01/16/2046320.aspx
现对其代码进行修改以完成对IDispatch.Invoke函数挂钩,修改方法如下:
第一步:
struct DispStr
{
LPDWORD lpVtbl;
};
第二步:
PROC* GetOrgAddr(IDispatch* pDisp)
{
DispStr* pStr = (DispStr*)pDisp;
LPDWORD lpVtabl = pStr->lpVtbl;
PROC* ppfn = (PROC* )(lpVtabl + 6); return ppfn;
}
第三步:
HRESULT __CALLTYPE Hook_Invoke(IDispatch *This, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
if(m_hook.m_pDisp != This)
{
TRACE("Warning:m_pDisp != this !!!/n"); // __cdecl
HRESULT hr = ((pfnInvoke )m_hook.m_pfnOrg)(This, dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
return hr;
}
// ......
HRESULT hr = ((pfnInvoke )m_hook.m_pfnOrg)(This, dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
return hr;
}
注意:
WriteProcessMemory如果失败,使用VirtualProtect将目标地址修改为可读写,如下:
DWORD old = 0;
VirtualProtect(ppfn, sizeof(PROC), PAGE_READWRITE, &old);
WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(PROC), NULL);