windowscomhookidispatchiunknown

Hook IDispatch v-table in C++


I'm trying to modify the behavior of an IDispatch interface already present in the system. To do this my plan was to hook into the objects v-table during runtime and modify the pointers so it points to a custom hook method instead.

If I can get this to work I can add new methods and properties to already existing objects. Nice.

First I tried hooking into the v-table for IUnknown (from which IDispatch inherits from) and that worked fine. However trying to change entries in IDispatch doesn't work at all. Nothing happens at all, the code works just as it did without the hook.

Here's the code, it's very simple so it shouldn't be any problems to understand

#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); 
*/

}

Solution

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

    this acturely hooked the QueryInterface of IUnknown.

    Following invoke will route to your typecount

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