Hook Idispatch V-Table في C ++
سؤال
أحاول تعديل سلوك واجهة idispatch الموجودة بالفعل في النظام. للقيام بذلك ، كانت خطتي هي ربط الكائنات V Table أثناء وقت التشغيل وتعديل المؤشرات بحيث تشير إلى طريقة ربط مخصصة بدلاً من ذلك.
إذا كان بإمكاني الحصول على هذا العمل ، فيمكنني إضافة طرق وخصائص جديدة إلى الكائنات الموجودة بالفعل. لطيف.
أولاً ، حاولت التثبيت في جدول V لـ Iunknown (الذي يرث منه Idispatch) والذي عمل بشكل جيد. ومع ذلك ، فإن محاولة التغيير في Idispatch لا تعمل على الإطلاق. لا شيء يحدث على الإطلاق ، فإن الكود يعمل تمامًا كما حدث بدون خطاف.
إليك الكود ، إنه بسيط للغاية لذلك لا ينبغي أن يكون أي مشاكل لفهمها
#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;
هذا مدمن مخدرات QueryInterface
من IUnknown
.
اتباع الاحتجاج سوف تسير إلى الخاص بك typecount
//obj->GetTypeInfoCount(&num);
LPVOID dummy;
obj->QueryInterface(IID_NULL, &dummy);
نصائح أخرى
أعتقد أنه يجب عليك إعادة ترميز هذا لتكون محمولة بين 32 بت و 64 بت
أصلي:
// There are three entries in IUnknown, therefore add 12 to go to IDispatch
void* idispatch_vtable = (void*)(((unsigned int)iunknown_vtable)+12);
المحمول:
// 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));