虚函数Hook代码

作为备记,直接上代码.

#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");
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
在 C++ 中,虚函数通过虚函数表(vtable)来实现。虚函数表是一个存储了虚函数指针的数组,每个类的对象都有一个指向其对应虚函数表的指针。 要 hook C++ 虚函数表并替换其中的虚函数指针,你可以按照以下步骤进行: 1. 获取要 hook 的类的对象指针。 2. 访问对象的虚函数表指针。 3. 根据虚函数的索引找到要 hook虚函数指针。 4. 替换虚函数指针为你想要调用的函数指针。 以下是一个示例代码,展示了如何 hook C++ 虚函数表并替换其中的虚函数指针: ```cpp #include <iostream> // 假设有一个基类 BaseClass class BaseClass { public: virtual void virtualFunction() { std::cout << "BaseClass::virtualFunction()" << std::endl; } }; // 定义一个替代原始虚函数的函数 void replacementFunction() { std::cout << "Replacement function called" << std::endl; } int main() { // 创建 BaseClass 对象 BaseClass obj; // 获取对象的虚函数表指针 uintptr_t* vtable = *(uintptr_t**)&obj; // 获取要 hook虚函数的索引(假设是第一个虚函数) int virtualFunctionIndex = 0; // 替换虚函数指针为 replacementFunction uintptr_t replacementFunctionPtr = (uintptr_t)&replacementFunction; vtable[virtualFunctionIndex] = replacementFunctionPtr; // 调用虚函数,将会调用替代函数 obj.virtualFunction(); return 0; } ``` 请注意,这个方法可能涉及到一些平台相关的细节,因此在不同的编译器和操作系统上可能会有所不同。在实际应用中,确保了解你所使用的编译器和平台的特定要求和限制是非常重要的。此外,修改虚函数表可能会破坏程序的稳定性和预期行为,谨慎使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值