Pregunta

Estoy tratando de modificar el comportamiento de una interfaz IDispatch ya presente en el sistema. Para hacer esto a mi plan era enganchar en la tabla v objetos en tiempo de ejecución y modificar los punteros para que apunte a un método personalizado en lugar de gancho.

Si puedo conseguir que esto funcione puedo añadir nuevos métodos y propiedades a los objetos ya existentes. Niza.

En primer lugar he intentado enganchar en la tabla v para IUnknown (de la que hereda de IDispatch) y que funcionaba bien. Sin embargo tratando de entires cambio en IDispatch no funciona en absoluto. No pasa nada en absoluto, el código funciona tal como lo hizo sin el gancho.

Este es el código, es muy sencilla por lo que no debería haber ningún problema para entender

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

}

Gracias de antemano!

¿Fue útil?

Solución

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

este acturely enganchó el QueryInterface de IUnknown.

Tras invocar encaminará a su typecount

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

Otros consejos

Creo que debe recodificar que esto es portable entre 32 bits y 64 bits

Original:

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

Portátil:

   // 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));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top