最近在学习C++虚函数表的Hook,这里简单上传一个小例子,是64位32位通用的
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include <windows.h>
#include <stdio.h>
/// <param name="__vfptr">虚表指针的地址</param>
/// <param name="pHookFunc">fake函数地址</param>
/// <param name="IndexInVT">欲Hook函数的引索</param>
/// <param name="pOldFunc">保存原函数地址</param>
BOOL HookVT(IN PVOID __vfptr, IN PVOID pHookFunc, IN DWORD IndexInVT,OUT ULONG_PTR* pOldFunc);
#define UnHookVT(vtptr,pOldFunc,Index) HookVT(vtptr,pOldFunc,Index,NULL)
class MyClass
{
public:
virtual void printdata();
MyClass();
~MyClass();
};
void MyClass::printdata()
{
}
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
class Son : public MyClass
{
public:
void printdata()
{
printf("s\n");
};
};
void FakePrintdata()
{
printf("FAKE\n");
}
int main()
{
Son* myclass = new Son();
myclass->printdata(); //未Hook之前
ULONG_PTR pOldFunc = NULL; //保存原函数地址
HookVT(&myclass,FakePrintdata, 0, &pOldFunc);//虚表指针就在对象的开头4/8字节
myclass->printdata(); //Hook之后
UnHookVT(&myclass, (PVOID)pOldFunc, 0);
myclass->printdata();//UnHook之后
Son myclass02;
myclass02.printdata(); //不用指针的形式调用,编译器将解释为Son::printdata绕过虚表
return 0;
}
BOOL HookVT(IN PVOID __vfptr, IN PVOID pHookFunc, IN DWORD IndexInVT, OUT ULONG_PTR* pOldFunc)
{
auto Hooked = FALSE;
auto Vtable =(ULONG_PTR*) (*(ULONG_PTR *)(*(ULONG_PTR*)__vfptr)); //*虚表指针地址->*虚表指针->*虚表地址
DWORD Flags = PAGE_READWRITE;
DWORD oldFlags = 0;
if (VirtualProtect(Vtable, sizeof(ULONG_PTR), Flags, &oldFlags))
{
if (!pOldFunc == NULL)
{
*pOldFunc = Vtable[IndexInVT];
}
Vtable[IndexInVT] = (ULONG_PTR)pHookFunc;
Hooked = TRUE;
return Hooked;
VirtualProtect(Vtable, sizeof(ULONG_PTR), oldFlags, &Flags); //恢复原保护属性
}
return Hooked;
}
运行结果