2010-01-02 19 views
2

J'essaie de modifier le comportement d'une interface IDispatch déjà présente dans le système. Pour ce faire, mon plan était de se connecter à la table v d'objets pendant l'exécution et de modifier les pointeurs afin qu'il pointe vers une méthode de hook personnalisée à la place.Hook IDispatch v-table en C++

Si je peux obtenir ceci pour fonctionner je peux ajouter de nouvelles méthodes et propriétés aux objets déjà existants. Agréable.

J'ai d'abord essayé de m'intégrer dans la v-table pour IUnknown (dont IDispatch hérite) et cela a bien fonctionné. Cependant, essayer de changer les adresses dans IDispatch ne fonctionne pas du tout. Rien ne se passe du tout, le code fonctionne comme il l'a fait sans le crochet.

est ici le code, il est très simple donc il ne devrait pas y avoir de problèmes à comprendre

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

} 

Merci à l'avance!

Répondre

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

cet accroché acturely la QueryInterface de IUnknown.

Après Invoke acheminera à votre typecount

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

Doh! J'ai accidentellement tapé iunknown_vtable au lieu de idispatch_vtable. Merci pour les yeux clairs! – monoceres

1

Je pense que vous devriez recoder que ce soit portable entre 32 bits et 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); 

Portable:

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