补——HOOK API函数

HOOKAPI的意思就是,给系统函数API挂钩,让系统调用API的时候,先执行我们自己设定的程序,之后再决定是不是执行具体的API函数的功能。
HOOK API的原理:
如下图:
在这里插入图片描述
至于是否执行完整API函数的完整代码则无所谓
大概思路:
1、 要hook MessageBox这个API,首先要获取到这个API的地址,这个API是User32.dll的导出函数,所以要先获得这个模块的地址
2、 获取到user32.dll模块的句柄之后,需要加载这个dll
3、 加载这个dll之后,需要遍历导出表找到这个MessageBox这个函数
4、 找到这个函数之后,开始修改我们的指令
下边是整个HOOK过程的代码:

#include <iostream>
#include <windows.h>
using namespace std;
int MyFunc()
{
	int a = 1;
	int b = 2;
	int c = a + b;
	cout << "MessageBoxA等于" << c << endl;
	return c;
}
int main()
{
	HMODULE Hmoudle = LoadLibraryA("user32.dll");
	FARPROC oldAPI = GetProcAddress(Hmoudle,"MessageBoxA");
	int(*NewAPI)();
	NewAPI = MyFunc;
	BYTE OldCode[5];
	BYTE NewCode[5];
	_asm
	{
		lea edi,OldCode
		mov esi,oldAPI
		cld
		movsd
		movsb
	}
	NewCode[0] = 0xe9;
	_asm
	{
		lea eax,NewAPI//获取要存储JMP指令的数组的地址
		mov edx,oldAPI//将存储源MessageBox前5个字节的数组的地址给edx
		sub [eax],edx//eax里边存储着我们自家函数的地址
		sub [eax],5//减去我们要修改的5个字节
		mov ebx,[eax]//将要修改的5个字节的地址给ebx
		mov dword ptr [NewCode+1],ebx//将要修改的5个字节写过去
	}
	//修改源API函数的前5个字节
	DWORD dwpid = GetCurrentProcessId();
	DWORD dwOldProtect;
	HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwpid);
	VirtualProtectEx(Handle,oldAPI,5,0x40,&dwOldProtect);
	WriteProcessMemory(Handle, oldAPI, NewCode,5,NULL);
	VirtualProtectEx(Handle, oldAPI, 5,NULL, &dwOldProtect);
	MessageBoxA(NULL,"在吗","干嘛呢",MB_OK);
}

这里实现的是在调用MessageBox的时候,让函数去执行一个简单的加法,然后输出 MessageBoxA等于3

接下来对整个HOOK过程进行详细的讲解,讲解过程采用OD动态调试的方式来进行。

我们在使用OD进行动态调试的时候,附加项目生成的release版的,附加Debug版的会报错,我是在虚拟机里进行调试的,没有环境。

HOOK的主要过程已经解释过,下边对其中的主要代码进行解释。当然整个过程的主要代码块就是命令替换的过程。

调试过程:
主要解释整个命令的替换过程:

	HMODULE Hmoudle = LoadLibraryA("user32.dll");   //加载user32.dll
	FARPROC oldAPI = GetProcAddress(Hmoudle,"MessageBoxA");//获取函数地址
	int(*NewAPI)();//声明一个函数指针
	NewAPI = MyFunc;//函数指针指向我们定义的自己的函数,这个函数就是我们HOOK之后要执行的内容
BYTE OldCode[5];//存储原API的命令
BYTE NewCode[5];//存储要替换的命令
_asm
	{
		lea edi,OldCode //获取存储源API函数命令的数组的地址
		mov esi,oldAPI //将MessageBox函数的地址存放在esi地址中
		cld
		movsd//将MessageBox函数的前4个字节存放在OldCode
		movsb//将MessageBox函数的第5个字节复制过去
	}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

NewCode[0] = 0xe9;

将要修改的数组的第一个字节的数据修改为0xe9,0xe9其实就是JMP指令。所以该数组里边的剩下4个字节就要设置成为适当的地址来跳转到我们自己的函数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
之后要完成的任务就是,将我们获取到的JMP指令,修改到原来的MessageBox地址的前5个字节。在这之前还需要注意,修改MessageBox函数地址处的属性,将之设置为可写,之后将数据修改过去,再把属性修改回来就好。

//修改源API函数的前5个字节
	DWORD dwpid = GetCurrentProcessId();
	DWORD dwOldProtect;
	HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwpid);
	VirtualProtectEx(Handle,oldAPI,5,0x40,&dwOldProtect);
	WriteProcessMemory(Handle, oldAPI, NewCode,5,NULL);
	VirtualProtectEx(Handle, oldAPI, 5,NULL, &dwOldProtect);

最后再调用MessageBoxA让程序去执行我们的函数,也可以进行成果验证。

运行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值