2010-09-11 31 views
5

Salutations StackOverflowians,API Crochet sur une fonction d'objet COM?

Comme here découvraient, Windows 7 dispose d'un bogue dans lequel l'événement DISPID_BEFORENAVIGATE2 ne se déclenche pas pour les instances de Windows Explorer. Cet événement permet aux extensions shell d'être averties lorsqu'une navigation est sur le point d'avoir lieu, et (surtout pour moi) d'annuler la navigation. Je cherchais une solution de contournement depuis un certain temps, et je pense en avoir trouvé un. Mais, j'aimerais avoir quelques opinions sur la sécurité.

Je jouais beaucoup avec l'API depuis quelques temps, et je l'utilise déjà pour ajouter quelques fonctions à mon extension. J'ai remarqué qu'il y a un function in IShellBrowser qui contrôle la navigation. Au début, je pensais que vous ne pouviez pas accrocher quelque chose comme ça, mais en lisant sur le layout of a COM object je me suis rendu compte qu'il devrait être possible en saisissant le bon pointeur de fonction hors de la vtable de toute instance active. Effectivement, cela fonctionne comme un rêve. Une fois le hook défini, toutes les navigations dans toutes les fenêtres de l'Explorateur s'exécutent directement à travers ma fonction de détour, et je peux décider de les rejeter en fonction de leur cible pidl.

Donc, ma question est, y at-il une raison pour laquelle je ne devrais pas faire cela? Je n'ai jamais entendu parler de l'accrochage API utilisé pour accrocher les fonctions d'objet COM. Y a-t-il des circonstances dans lesquelles cela ne fonctionnerait pas? Est-ce dangereux? (Au moins un hook API normal, au moins)

Le code correspondant est le suivant. J'utilise MinHook, une bibliothèque d'accrochage minimaliste qui utilise la méthode éprouvée des fonctions de trampoline.

typedef HRESULT (WINAPI *BROWSEOBJECT)(IShellBrowser*, PCUIDLIST_RELATIVE, UINT); 
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags); 
BROWSEOBJECT fpBrowseObject = NULL; 
BROWSEOBJECT ShellBrowser_BrowseObject = NULL; 

bool Initialize() { 
    if(MH_Initialize() != MH_OK) { 
     return false; 
    } 

    // Get a reference to an existing IShellBrowser. Any instance will do. 
    // ShellBrowser enum code taken from The Old New Thing 
    IShellWindows *psw; 
    BOOL fFound = FALSE; 
    if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) { 
     VARIANT v; 
     V_VT(&v) = VT_I4; 
     IDispatch *pdisp; 
     for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) { 
      IWebBrowserApp *pwba; 
      if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) { 
       IServiceProvider *psp; 
       if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) { 
        IShellBrowser *psb; 
        if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,IID_IShellBrowser, (void**)&psb))) { 
         fFound = true; 

         // Grab the 11th entry in the VTable, which is BrowseObject 
         void** vtable = (*(void***)(psb)); 
         ShellBrowser_BrowseObject = (BROWSEOBJECT)(vtable[11]); 
         psb->Release(); 
        } 
        psp->Release(); 
       } 
       pwba->Release(); 
      } 
      pdisp->Release(); 
     } 
     psw->Release(); 
    } 

    if(fFound) { 
     if(MH_CreateHook(ShellBrowser_BrowseObject, &DetourBrowseObject, reinterpret_cast<void**>(&fpBrowseObject)) != MH_OK) { 
      return false; 
     } 
     if(MH_EnableHook(ShellBrowser_BrowseObject) != MH_OK) { 
      return false; 
     } 
    } 
    return true; 
} 

HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags) { 
    if(NavigateIsOkay(pidl, wFlags)) { 
     return fpBrowseObject(_this, pidl, wFlags); 
    } 
    else { 
     return S_FALSE; 
    }  
} 

Répondre

2

Je ne l'ai jamais entendu parler de crochetage API utilisé pour accrocher les fonctions de l'objet COM.

Les fonctions membres des objets COM ne sont pas vraiment différentes et peuvent être réellement bien accrochées si vous respectez les directives habituelles pour l'accrochage. Il y a quelques années, j'ai dû connecter les composants COM d'une solution CRM propriétaire pour la connecter à un serveur de base de données. L'application a bien fonctionné et a fonctionné assez stable pendant plusieurs années.

+0

Merci pour le réconfort. =) –

+1

Cette réponse est fausse. L'accrochage COM est très spécial surtout dans Internet Explorer et n'a rien de commun avec l'accrochage API ordinaire! Un objet COM peut être encapsulé dans un objet encapsuleur et finalement vous ne pouvez qu'accrocher le wrapper. Lisez les liens dans cet article: http://stackoverflow.com/questions/1505196/spying-on-com-objects – Elmue