【问题标题】:Hook IDispatch v-table in C++在 C++ 中挂钩 IDispatch v-table
【发布时间】:2010-12-31 19:34:37
【问题描述】:

我正在尝试修改系统中已经存在的IDispatch 接口的行为。 为此,我的计划是在运行时挂钩到对象 v-table 并修改指针,使其指向自定义挂钩方法。

如果我可以让它工作,我可以向现有的对象添加新的方法和属性。不错。

首先,我尝试连接到 IUnknown 的 v-table(IDispatch 继承自该表)并且效果很好。但是,尝试更改 IDispatch 中的条目根本不起作用。什么都没有发生,代码就像没有钩子一样工作。

这是代码,很简单,理解起来应该没有什么问题

#include <iostream>
#include <windows.h>
#include <Objbase.h>
#pragma comment (lib,"Ole32.lib")
using namespace std;

HRESULT __stdcall typecount(IDispatch *self,UINT*u)
{
    cout << "hook" << endl;
    *u=1;
    return S_OK;
}


int main()
{
    CoInitialize(NULL);

    // Get clsid from name
    CLSID clsid;
    CLSIDFromProgID(L"shell.application",&clsid);

    // Create instance
    IDispatch *obj=NULL;
    CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IDispatch),(void**)&obj);

    // Get vtable and offset in vtable for idispatch
    void* iunknown_vtable= (void*)*((unsigned int*)obj);
    // There are three entries in IUnknown, therefore add 12 to go to IDispatch
    void* idispatch_vtable = (void*)(((unsigned int)iunknown_vtable)+12);

    // Get pointer of first emtry in IDispatch vtable (GetTypeInfoCount)
    unsigned int* v1 = (unsigned int*)iunknown_vtable;

    // Change memory permissions so address can be overwritten
    DWORD old;
    VirtualProtect(v1,4,PAGE_EXECUTE_READWRITE,&old);

    // Override v-table pointer
    *v1 = (unsigned int) typecount;

    // Try calling GetTypeInfo count, should now be hooked. But isn't works as usual
    UINT num=0;
    obj->GetTypeInfoCount(&num);

/*
    HRESULT hresult;
    OLECHAR FAR* szMember = (OLECHAR*)L"MinimizeAll";
    DISPID dispid;
    DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
    hresult = obj->GetIDsOfNames(IID_NULL, &szMember, 1,
    LOCALE_SYSTEM_DEFAULT, &dispid) ;
    hresult = obj->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,&dispparamsNoArgs, NULL, NULL, NULL); 
*/

}

【问题讨论】:

    标签: windows com hook idispatch iunknown


    【解决方案1】:
    // Get pointer of first emtry in IDispatch vtable (GetTypeInfoCount)
    unsigned int* v1 = (unsigned int*)iunknown_vtable;
    

    这确实吸引了IUnknown 的QueryInterface。

    以下调用将路由到您的typecount

    //obj->GetTypeInfoCount(&num);
    LPVOID dummy;
    obj->QueryInterface(IID_NULL, &dummy);
    

    【讨论】:

    • 噢!我不小心输入了 iunknown_vtable 而不是 idispatch_vtable。谢谢你清澈的眼睛!
    【解决方案2】:

    我认为您应该将其重新编码为可在 32 位和 64 位之间移植

    原文:

       // There are three entries in IUnknown, therefore add 12 to go to IDispatch
        void* idispatch_vtable = (void*)(((unsigned int)iunknown_vtable)+12);
    

    便携:

       // There are three entries in IUnknown, therefore add 3 pointers to go to IDispatch
        void* idispatch_vtable = (void*)(((DWORD_PTR)iunknown_vtable) + (sizeof(void *) * 3));
    

    【讨论】:

      猜你喜欢
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 2011-12-25
      • 2016-08-08
      • 2011-05-16
      • 1970-01-01
      相关资源
      最近更新 更多