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