作为备记,直接上代码.
#include <windows.h>
//更改地址跳转表
long ExChangeJumpTable(void* vfptr,int index,void* Value){
//虚表函数地址
void * functionJmpAddr = ((void**)vfptr)[index];
//E9 xx xx xx xx
unsigned char *codeAddr = (unsigned char*)functionJmpAddr;
//检查跳转代码
if(*codeAddr == 0xE9 || *codeAddr == 0xEB)
{
//32位和64位均为4字节
int *jmpValue = (int*)(codeAddr+1);
//跳转数
int jmpDistance = *jmpValue;
//真实地址计算公式:当前代码地址 + 跳转距离 + 代码长度
long dRet = (long)codeAddr + jmpDistance + 5;
DWORD oldPro = 0;
BOOL bRet = VirtualProtect(jmpValue,sizeof(int),PAGE_EXECUTE_READWRITE,&oldPro);
*jmpValue = (int)((unsigned char*)Value - codeAddr) - 5;
VirtualProtect(jmpValue,sizeof(int),oldPro,NULL);
return dRet;
}
else if(*codeAddr == 0xEA)
{
//跳转代码
long *jmpValue = (long*)(codeAddr+1);
//跳转数
long jmpAddr = *jmpValue;
DWORD oldPro = 0;
BOOL bRet = VirtualProtect(jmpValue,sizeof(long),PAGE_EXECUTE_READWRITE,&oldPro);
*jmpValue = (long)Value;
VirtualProtect(jmpValue,sizeof(long),oldPro,NULL);
return jmpAddr;
}
else
{
return -1;
}
}
//更改虚表地址
DWORD ExChangeVirtualTable(void* vfptr,int index,void* Value)
{
DWORD oldPro = 0;
BOOL bRet = VirtualProtect(vfptr,sizeof(void*)*(index+1),PAGE_EXECUTE_READWRITE,&oldPro);
void * func = ((void**)vfptr)[index];
((void**)vfptr)[index] = Value;
VirtualProtect(vfptr,sizeof(void*)*(index+1),oldPro,NULL);
return (DWORD)func;
}
class A{
public:
virtual void PutString(const char* value){
printf("A::this:0x%08x\n",this);
printf("Class:A::(%s) %d\n",value,m_nValue);
}
int m_nValue;
};
class C:public A
{
public:
virtual void PutString(const char* value)
{
printf("C::this:0x%08x\n",this);
printf("Class:C::(%s) %d\n",value,m_nValue);
}
};
class D{
public:
virtual void DDD(const char *value){
printf("D::this:0x%08x\n",this);
printf("D:DDD:%s\n",value);
}
};
#ifndef _WIN64
#define VFPTR_FunctionCall(A,func) \
__asm \
{ \
mov ecx,A \
} \
func; \
#endif
//使用C方法调用虚函数
void VFPTR_Test(){
A a;
a.m_nValue = 100;
A * pa= &a;
printf("this:0x%08x\n",pa);
void *pthis=&a;
void **__vfptr = *(void***)pthis;
void * func = __vfptr[0];
typedef void (__stdcall *PPutString)(const char* value);
PPutString ps = (PPutString)func;
#ifndef _WIN64
VFPTR_FunctionCall(pa,ps("444"));
#endif
}
//交换同类虚函数地址
void VirtualTable_Test()
{
A a;
C c;
a.m_nValue = 100;
c.m_nValue = 200;
A *pa= &c;
unsigned int* pthis= (unsigned int*)pa;
void **__vfptr_c = *(void***)pthis;
void * func = __vfptr_c[0];
pa = &a;
pthis= (unsigned int*)pa;
void **__vfptr_a = *(void***)pthis;
func = __vfptr_a[0];
DWORD oldPro = 0;
BOOL bRet = VirtualProtect(__vfptr_a,4,PAGE_EXECUTE_READWRITE,&oldPro);
__vfptr_a[0] = __vfptr_c[0];
VirtualProtect(__vfptr_a,4,oldPro,NULL);
pa = &a;
pa->PutString("aaaa");
bRet = VirtualProtect(__vfptr_c,4,PAGE_EXECUTE_READWRITE,&oldPro);
__vfptr_c[0] = func;
VirtualProtect(__vfptr_c,4,oldPro,NULL);
pa = &c;
pa->PutString("cccc");
}
//更改虚函数调用表地址
void JmpTable_Test(){
C c;
c.m_nValue = 200;
A *pa= &c;
D d;
D * pd = &d;
unsigned int* pthis= (unsigned int*)pa;
void **__vfptr_c = *(void***)pthis;
void * func = __vfptr_c[0];
pthis= (unsigned int*)pd;
void **__vfptr_d = *(void***)pthis;
func = __vfptr_d[0];
//更改虚表,只能针对指针处理
/*DWORD oldPro = 0;
BOOL bRet = VirtualProtect(__vfptr_c,4,PAGE_EXECUTE_READWRITE,&oldPro);
__vfptr_c[0] = __vfptr_d[0];
VirtualProtect(__vfptr_c,4,oldPro,NULL);*/
//ExChangeVirtualTable(__vfptr_c,0,func);
//更改跳转表法,万能HOOK
ExChangeJumpTable(__vfptr_c,0,func);
c.PutString("cccc");
pa->PutString("dddd");
}