C++ 更改外部类的VTable
在谷歌搜索之后,我找到了一种修改类的VTable的方法,但在我的例子中,我只有一个指向我的类的指针和一个将其转换到的接口。我需要将其中一个函数(在DLL中;没有源代码)重定向到我的一个函数。问题是我不知道该函数在哪个索引上,所以为了找到它,我尝试扫描VTable以查找指向该函数的指针 有没有办法做到这一点 以下是我目前的代码:C++ 更改外部类的VTable,c++,class,vtable,C++,Class,Vtable,在谷歌搜索之后,我找到了一种修改类的VTable的方法,但在我的例子中,我只有一个指向我的类的指针和一个将其转换到的接口。我需要将其中一个函数(在DLL中;没有源代码)重定向到我的一个函数。问题是我不知道该函数在哪个索引上,所以为了找到它,我尝试扫描VTable以查找指向该函数的指针 有没有办法做到这一点 以下是我目前的代码: typedef DWORD (__thiscall *CW_FUNC)(); class ClassWriter { public: PVOID m_hObj;
typedef DWORD (__thiscall *CW_FUNC)();
class ClassWriter
{
public:
PVOID m_hObj;
PVOID *__vfptr;
PVOID m_old[256];
void SetObj(PVOID hObj)
{
m_hObj = hObj;
__vfptr = *(PVOID **)hObj;
}
void AddOverride(int offset, PVOID newfunc)
{
DWORD dwNull;
m_old[offset] = __vfptr[offset];
VirtualProtect(__vfptr + offset * 4, 4, PAGE_EXECUTE_READWRITE, &dwNull);
__vfptr[offset] = newfunc;
}
int GetOffset(PVOID func)
{
for (int i = 0; __vfptr[i] != NULL; i++)
{
if (func == __vfptr[i]) return i;
}
}
CW_FUNC GetFunc(int offset)
{
return (CW_FUNC)m_old[offset];
}
};
void WINAPI ChangeFunc()
{
ClassWriter cw;
HMODULE hMod = GetModuleHandle("dll_to_change.dll");
IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyClass")();
cw.SetObj(myObj);
int d = cw.GetOffset(myObj->MyFunction);
cw.AddOverride(d, OverrideFunction);
}
因此,对于所有认为这个问题但现在不知道如何解决的人: 我正在使用ollydbg,但您可以使用任何其他调试器/转储程序 最好的方法是将代码放入dll中。确保执行您的函数,否则编译器将不会编译它(至少对我而言) 现在,要么执行代码直到MessageBox()出现并在调试器中打开该地址,要么如果编译器创建了导出函数,则只需转到dll.OverrideFunction即可 查找下面的一行,类似这样(如果编译器检测到名称) 接下来的
调用
应该是您的类函数,在我的例子中:
CALL DWORD PTR DS:[EAX+34]
偏移量为0x34,即52(请记住始终计算十六进制数)。要获得VTable中的索引,必须除以4(指针的大小),在我的例子中是13
void __fastcall NewFunc(IMyInterface *myObj, int null, (additional params)) // fastcall stores the first 2 params int ECX and EDX, thiscall stores the this-object in ECX
{
// Your code
}
void OverrideFunction()
{
DWORD dwNull;
HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary()
IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object
PVOID *vtable = *(PVOID**)myObj; // The first int in your object is a pointer to the vtable
// OldFunc = vtable[13]; // You might want to call your old function again, so save the pointer
VirtualProtect(&vtable[13], 4, PAGE_EXECUTE_READWRITE, &dwNull); // Always unprotect the memory
vtable[13] = NewFunc;
}
现在,每次MyObject调用MyFunction时,都会执行NewFunc,而不是您没有该外部类的源代码吗?不,我只有一个接口,函数的DLLScan应该可以工作。当然,它确实假设它实际上是一个虚拟函数[在您关心的地方,它被称为虚拟函数,而不是直接调用]。问题是我无法创建指向myObj->MyFunction“can't”的指针,意思是什么?
CALL DWORD PTR [YourDll._imp__MessageBoxA]
CALL DWORD PTR DS:[EAX+34]
void __fastcall NewFunc(IMyInterface *myObj, int null, (additional params)) // fastcall stores the first 2 params int ECX and EDX, thiscall stores the this-object in ECX
{
// Your code
}
void OverrideFunction()
{
DWORD dwNull;
HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary()
IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object
PVOID *vtable = *(PVOID**)myObj; // The first int in your object is a pointer to the vtable
// OldFunc = vtable[13]; // You might want to call your old function again, so save the pointer
VirtualProtect(&vtable[13], 4, PAGE_EXECUTE_READWRITE, &dwNull); // Always unprotect the memory
vtable[13] = NewFunc;
}