MFC_DLL 实现动态HOOK

Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会收到系统的通知,这时程序就能在第一时间对该事件做出响应。

自己理解的原理

image.png
解释:HOOK通过在HOOK点进行修改,是原先的代码执行到HOOK点后,跳转到自己的代码上执行,得到数据或者进行自己的操作后,返回到原先的代码继续执行(自己理解,若有不足或错误,欢迎指正)

使用MFC的动态链接库,实现动态HOOK

  • 测试程序(自己写的取和计算)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fyVQBFi6-1589989765101)(https://i.loli.net/2020/05/20/FAzDbHC5qliLKr4.png)]

在没HOOK 前,是实现的简单加法运算,并且打印和

  • HOOK 后展示
    image.png

将a + b 转换为a + 2 * b 并且在编辑框打印a 和b 的值

代码实现

HOOK
  1. 找到HOOK 点

这里主要是实现对函数的修改,及让程序执行自己的函数,执行完成后跳会原先的代码,继续执行,下面是原先的代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-coOQ4jOp-1589989765106)(https://i.loli.net/2020/05/20/2CvZEbdGFpxz76U.png)]
这里我们只需要修改CALL后面的地址,及将

call 0x00401000

修改为

CALL 自定义函数地址
  1. 新建项目MFC_DLL
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4IW7vTZF-1589989765109)(https://i.loli.net/2020/05/20/VcUoQpZriKqCwSL.png)]

  2. 新建的MFC DLL 没有窗口,所以先添加窗口
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNyOtKVm-1589989765113)(https://i.loli.net/2020/05/20/Y4HJrksRmOtMgPq.png)]

  3. 双击新建的界面,新建窗口类,在初始化方法添加窗口显示代码

// CMFCDLLDyncHookApp 初始化
#include "CDlgPageOne.h"
CDlgPageOne cpg1;

DWORD WINAPI ShowDlgProc(
	LPVOID lpParameter   // thread data
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	// 通过模态方式实现(阻塞),所以子线程执行
	cpg1.DoModal();
	// 卸载DLL 
	FreeLibraryAndExitThread(theApp.m_hInstance, 1);

}


BOOL CMFCDLLDyncHookApp::InitInstance()
{
	CWinApp::InitInstance();
	::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ShowDlgProc, 0, 0, 0);
	return TRUE;
}

  1. 定义函数
void MyAddFunc(int a, int b)
{
	int c = a + b + a * b;
	printf("结果 = %d\r\n", c);
	return;
}
  1. HOOK
int Hook()
{
	// 求函数地址偏移
	DWORD funcAddr = (DWORD)MyAddFunc;
	DWORD offset = funcAddr - 0x5 - 0x401081;  // 00401081 | E8 7AFFFFFF | call hook-test.401000 | 修改call 后的目标地址,使他跳转到自定义函数上

	// 修改页面属性
	DWORD oldProtect = 0;
	VirtualProtect((LPVOID)0x00401081, 20, PAGE_EXECUTE_READWRITE/*可写可读*/, &oldProtect);
	// 写入目标地址
	DWORD *_offset = (DWORD*)0x401082;  // hook 的地址
	*_offset = offset;

	// 恢复原先页面属性
	VirtualProtect((LPVOID)0x00401081, 20, oldProtect, &oldProtect);
	return 0;
}
  1. UNHOOK

与HOOK 类似,将原先的代码重新修改回去

int UnHook()
{
	
	// 修改页面属性
	DWORD oldProtect = 0;
	VirtualProtect((LPVOID)0x00401081, 20, PAGE_EXECUTE_READWRITE, &oldProtect);
	// 写入目标地址
	DWORD *_offset = (DWORD*)0x401082;
	*_offset = 0xFFFFFF7A;

	// 恢复页面属性
	VirtualProtect((LPVOID)0x00401081, 20, oldProtect, &oldProtect);
	return 0;
}


到这里,实现了动态HOOK,可以实现对原有代码的修改,但是还不能再窗口上实时打印参数的值,这里还需要修改一些代码
  1. 实现数据的实时打印
  • 修改自定义函数
void MyAddFunc(int a, int b)
{
	int c = a + b + a * b;
	printf("结果 = %d\r\n", c);

    // 将参数赋值给EDIT 控件绑定的参数m_ValueStr
	cpg1.m_ValueStr.Format("a = %d, b = %d", a, b);

    // 因为当前函数是执行在HOOK_Test(被hook exe)上的,而非MFC 上,二者不在同一个线程,直接更新数据会造成数
    // 据不同步,而出现程序崩溃,所以这里使用消息发送的方式,进行数据更新
	cpg1.SendMessage(WM_USER + 1, 222, 111);

	return;
}
  1. 接受MyAddFunc 函数来的消息,重写WindowProc 函数
LRESULT CDlgPageOne::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	// TODO: 在此添加专用代码和/或调用基类

	if (message == WM_USER + 1)
	{
		UpdateData(FALSE);
	}

	return CDialogEx::WindowProc(message, wParam, lParam);
}


经过上述操作,即可实现动态HOOK,并且同步获取数据进行显示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值