hook模板x86/x64通用版(3)--CHook.h说明

因为注释比较齐全,所以不多说别的了。

Hook.h:

#pragma once

#ifdef _UNICODE
#define _T(x)      L ## x
#else
#define _T(x)      x
#endif

#ifdef _WIN64
#define WriteCall      WriteCall_x64
#define WriteJMP       WriteJMP_x64
#else
#define WriteCall      WriteCall_x86
#define WriteJMP       WriteJMP_x86
#endif

#ifdef _WIN64
//普通hook的shellcode大小
#define TRANSFER_FUNC_SIZE	0xcd
//API hook的shellcode大小
#define TRANSFER_FUNC_FOR_CALL_SIZE	0x193
//64位下跳转指令需要的空间大小
#define JMP_CODE_LEN	0xe
//参数结构
struct ST_PARAMS 
{
	//ST_REGISTER结构中RSP后面的5个寄存器还有0x20的保护空间,一共9个,用不到也别修改 
	const DWORD64 no_use[9]; //不包含返回地址,返回地址会先pop掉
	DWORD64 pdwParams[]; //非API头的hook不要使用该结构
};
//保存hook现场的结构,一般x64的前四个参数是按顺序安排在RCX,RDX,R8,R9
struct ST_REGISTER
{
	DWORD64 dw64_R15;
	DWORD64 dw64_R14;
	DWORD64 dw64_R13;
	DWORD64 dw64_R12;
	DWORD64 dw64_R11;
	DWORD64 dw64_R10;
	union
	{
		DWORD64 dw64_R9;
		DWORD64 dw64_Param3;
	};
	union
	{
		DWORD64 dw64_R8;
		DWORD64 dw64_Param2;
	};
	DWORD64 dw64_Rdi;
	DWORD64 dw64_Rsi;
	union
	{
		DWORD64 dw64_Rsp;
		ST_PARAMS* pstMoreParams;
	};
	DWORD64 dw64_Rbp;
	DWORD64 dw64_Rbx;
	union
	{
		DWORD64 dw64_Rdx;
		DWORD64 dw64_Param1;
	};
	union
	{
		DWORD64 dw64_Rcx;
		DWORD64 dw64_Param0;
	};
	DWORD64 dw64_Rax;
};

#else
//普通hook的shellcode大小
#define TRANSFER_FUNC_SIZE	0x49
//API hook的shellcode大小
#define TRANSFER_FUNC_FOR_CALL_SIZE	0x7d
//32位下跳转指令需要的空间大小
#define JMP_CODE_LEN	5
//保存hook现场的结构
struct ST_REGISTER
{
	DWORD dw_edi;
	DWORD dw_esi;
	DWORD dw_ebp;
	union
	{
		DWORD dw_esp;
		DWORD* pParamsOfCall;//API头的hook使用该结构可以修改参数数值
	};
	DWORD dw_ebx;
	DWORD dw_edx;
	DWORD dw_ecx;
	DWORD dw_eax;
};

#endif

class CHook
{
public:
	//一个类只hook一个地址,所以在构造函数这里进行hook防止用户多次调用
	CHook(void* pOriginAdr , void* pNewHook);
	CHook(void* pOriginAdr , void* pNewHook , void* pHookAfterCall);
	~CHook(void);

	//移除hook的函数,未作测试=。=
	BOOL RemoveHook();
	//直接移除hook的函数,在本hook的用户函数中调用的话会出大事,所以名字加了unsafe。
	//在其他地方调用的话要确保没有运行到该hook的代码,所以最好还是调用上面那个函数
	BOOL RemoveHook_unsafe();
	//获取hook点现场
	ST_REGISTER* GetRegOnHookPoint();

private:
	//初始化,然而并没有初始化多少东西
	void Init();
	//给某地址写跳转指令
	void WriteJMP_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo);
	void WriteJMP_x64(DWORD_PTR dwFrom , DWORD_PTR dwTo);
	//给某地址写一个call指令
	void WriteCall_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo);
	void WriteCall_x64(DWORD_PTR dwFrom , DWORD_PTR dwTo);

	//在地址pOriginAdr设置普通hook,用户定义回调函数pNewHook
	BOOL SetHook(void* pOriginAdr , void* pNewHook);
	//在函数头pOriginAdr设置hook,用户定义回调函数pNewHook在函数执行前运行,用于拦截和修改参数;
	//pHookAfterCall在函数执行后运行,用于拦截和修改函数返回。pNewHook和pHookAfterCall不可同时为空
	BOOL SetHook(void* pOriginAdr , void* pNewHook , void* pHookAfterCall);

	//迁移、保存hook点被破坏的代码
	int TransplantCode( void* pOriginAdr , BYTE* pDestAdr);

	//保存hook现场的Tls索引
	DWORD m_dwTlsIndexForRegister;
	//保存API头hook保存函数返回地址的Tls索引
	DWORD m_dwTlsIndexForRetAdr;

	//保存hook点地址
	void* m_pOrigin_Adr;
	//保存hook点被破坏的指令长度
	int m_nOrigin_CodeLen;
	//hook点被破坏的指令迁移到的地址
	BYTE* m_pOldCode;

	//每个CHook类初始化时会申请一块内存,把shellcode复制进去并修正一些偏移,作为中转函数
	BYTE* m_szMyTransfer;

	//单纯c3返回的函数,用于API hook时候某个用户定义的函数为空的时候直接调用这个函数
	//在修正shellcode的时候能简化一点操作
	static BYTE* m_szRet;
	//普通hook的shellcode模板
	static BYTE m_szTransferFunction[TRANSFER_FUNC_SIZE];
	//API hook的shellcode模板
	static BYTE m_szTransferFunction_ForCall[TRANSFER_FUNC_FOR_CALL_SIZE];
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值