C/C++:Windows编程—Inline Hook内联钩子(下)

本文详细介绍了使用7字节InlineHook技术修改被Hook函数的执行流程,通过实例展示了如何利用C++实现这一技术,包括钩子的安装、卸载和重新安装过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

上节中介绍了 InlineHook 钩子函数,主要是通过jmp 目标地址(转为机器码E9 偏移量) 来实现的,是修改被Hook函数首地址处的 5个字节的内容。这里再介绍另一种方法,修改被Hook函数首地址处的7字节的内容。我们看下图的汇编指令
在这里插入图片描述
之前是jmp 目标地址(5字节),这次是将目标地址放到 eax寄存器中 这里是2条汇编指令(00B417E4-00B417DF = 5字节 + JMP EAX占2字节 = 7字节)。他们有什么不一样呢?

mov eax,78563412
jmp eax
;上面的汇编指令 转为机器码为:
;B8 12345678 
;FFE0

这里可以看出 B8为mov指令的机器码,jmp eax 对应的机器码为:FFE0,中间的机器码为目标地址了。这里刚好7个字节开头和结尾的 机器码 是固定的,变化的唯有中间4字节的 目标地址。故此我们可以修改 被Hook函数地址处的 7个字节即可,这样就不必计算偏移量了

示例效果

卸载钩子后

在这里插入图片描述
下钩子后
在这里插入图片描述
在这里插入图片描述

代码实现

InlineHook7.h

#pragma once

#include <Windows.h>

class CInlineHook7
{
public:
	CInlineHook7(void);
	~CInlineHook7(void);

	bool Hook(LPSTR strModuleName,LPSTR strHookFnName,FARPROC strHookCallFnName);

	bool UnHook();
	bool ReHook();
private:
	
	FARPROC m_pFnOrign; // 要Hook的函数地址
	BYTE m_bOld[7]; // 要Hook的函数 前7个字节
	BYTE m_bNew[7]; // 要Hook的函数 修改后的7个字节
};


InlineHook7.cpp

#include "StdAfx.h"
#include "InlineHook7.h"


CInlineHook7::CInlineHook7(void)
{

	m_pFnOrign = NULL;
	memset(m_bOld,0,7);
	memset(m_bNew,0,7);
}


CInlineHook7::~CInlineHook7(void)
{
	UnHook();
}

bool CInlineHook7::Hook(LPSTR strModuleName,LPSTR strHookFnName,FARPROC strTargetFnAddr)
{
	bool ret = false;
	HMODULE hModule = GetModuleHandleA(strModuleName);
	if( hModule == NULL )
		goto end;
	m_pFnOrign = (FARPROC)GetProcAddress(hModule,strHookFnName);
	if( m_pFnOrign == NULL )
		goto end;

	SIZE_T numByte;
	// 保存被Hook函数的前7个字节
	if( ReadProcessMemory(GetCurrentProcess(),m_pFnOrign,m_bOld,7,&numByte) == 0 )
		goto end;

	// 构造jmp指令:mov eax,jmp 目标地址,对应的机器码:B8 4字节的目标地址 FFE0
	m_bNew[0] = 0xB8,m_bNew[5] = 0xFF,m_bNew[6] = 0xE0;
	// 中间4字节 放目标地址
	* (DWORD*)(&m_bNew[0]+1) = (DWORD)strTargetFnAddr;
	
	// 修改被Hook函数的前7个字节 改变其执行流程
	if( WriteProcessMemory(GetCurrentProcess(),m_pFnOrign,m_bNew,7,&numByte) == 0 ) 
		goto end;

	ret = true;
end:
	return ret;
}

bool CInlineHook7::UnHook()
{
	bool ret = false;
	// 卸载钩子,实际上即是将更改的7个字节还原
	SIZE_T numByte;
	if( m_pFnOrign != NULL && WriteProcessMemory(GetCurrentProcess(),m_pFnOrign,m_bOld,7,&numByte) != 0)
		ret = true;
	return ret;
}

bool CInlineHook7::ReHook()
{
	bool ret = false;
	// 再次装钩子,更改要Hook的函数的前7字节 让其跳转到目标函数
	SIZE_T numByte;
	if( m_pFnOrign != NULL && WriteProcessMemory(GetCurrentProcess(),m_pFnOrign,m_bNew,7,&numByte) != 0)
		ret = true;
	return ret;
}

目标函数代码

// WINAPI 一定要声明,指明函数调用方式,这里和MessageBox保持一致
int WINAPI MyMessageBox7(HWND   hWnd,LPCSTR lpText,	LPCSTR lpCaption,UINT   uType)
{
	g_inlineHookObj7.UnHook(); // 必须先卸载钩子 再才可以再次调用被Hook的函数,不然会进入死循环
	::MessageBoxA(hWnd ,"进入MyMessageBox7了","被Hook了,7字节InlineHook",MB_OK);
	::MessageBoxA(hWnd ,lpText,lpCaption,MB_OK);
	g_inlineHookObj7.ReHook();
	return 0;
}

完整项目

完整项目下载请在这里下载,没分也可以在这里github下载最新代码,如果可以的话,帮忙点个星星哟 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值