徐上一篇文章APIHOOK详解后,这篇文章我们写一个简单的Demo作为练习,一个Hook类,可以Hook当前进程下的所有API!
代码思路比上篇文章要清晰,简洁,这里就不做介绍了,因为上一篇文章已经介绍的很仔细了,本demo完全依照上一篇文章里的代码搬运而来
#include <windows.h>
/*
Hook类的实现
*/
#define HOOK_THIS 0 //hook自身
//异常,Hook类,Windows下专用工具
#define PTR_NULL 0 //参数指针为NULL
#define MALLOC_PTR_NULL 1 //分配内存出错
#define NO_MOUDEHANDE 2 //没有找到模块句柄
#define NO_API 3 //没有API
#define ADM_ERROR 4 //获取内存页权限失败
#define READ_MOME 5 //读取内存页数据失败
#define DATA_NO 6 //上一次HOOK的data为空无法恢复
#define PTR_NO 7 //上一次HOOK的API地址为空
#define PRID_NO 8 //无法获取进程ID
#define USER_NO 9 //无法获取进程权限
#define PRID_NOMALLOC 10 //进程空间无法分配内存
#define NO_Kernel32 11
#define NO_CreateFCCO 12
class Hook {
public:
//构造
Hook(){
Ini();
}
//析构
~Hook() {
Relese();
}
//初始化
BOOL Ini() {
//Hook自身,获取进程句柄
My_HookHandle = GetCurrentProcess();
if (My_HookHandle == NULL) {
return NULL;
}
//初始化
My_DllName = NULL;
My_ApiName = NULL;
My_ErrorState = 0;
My_ApiPtr = 0;
memset(My_Data, 0, 5);
My_hInstance = 0;
//获取模块句柄
HMODULE hModule = NULL;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCSTR)&My_HookHandle, //可以是任何函数,全局变量等的地址
&hModule);
My_hInstance = hModule;
return TRUE;
}
//释放所使用的空间
BOOL Relese() {
My_HookHandle = NULL;
if (My_DllName != NULL) {
free(My_DllName);
My_DllName = NULL;
}
if (My_ApiName != NULL) {
free(My_ApiName);
My_ApiName = NULL;
}
My_ErrorState = 100;
My_ApiPtr = NULL;
memset(My_Data, 0, 5);
My_hInstance = 0;
return TRUE;
}
//HookAPI
BOOL HookApi(const char* DllName,const char *ApiName,ULONG JumpApiPtr) {
//判断下空指针
if (My_HookHandle == NULL || DllName == NULL || ApiName == NULL) {
My_ErrorState = PTR_NULL;
return FALSE;
}
//保留DllName和ApiName
if (My_DllName != NULL) {
free(My_DllName);
My_DllName = NULL;
}
My_DllName = (TCHAR *)malloc(strlen(DllName)+1);
if (My_DllName == NULL) {
My_ErrorState = MALLOC_PTR_NULL;
return FALSE;
}
memset(My_DllName, 0, strlen(DllName) + 1);
strcpy(My_DllName, DllName);
//--Apiname
if (My_ApiName != NULL) {
free(My_ApiName);
My_ApiName = NULL;
}
My_ApiName = (TCHAR *)malloc(strlen(ApiName) + 1);
if (My_ApiName == NULL) {
My_ErrorState = MALLOC_PTR_NULL;
return FALSE;
}
memset(My_ApiName, 0, strlen(ApiName) + 1);
strcpy(My_ApiName, ApiName);
//获取模块句柄
HMODULE hDll = GetModuleHandle(My_DllName);
if (hDll == NULL) {
My_ErrorState = NO_MOUDEHANDE;
return FALSE;
}
//获取API接口地址
FARPROC Api = GetProcAddress(hDll, ApiName
);
if (Api == NULL) {
My_ErrorState = NO_API;
return FALSE;
}
My_ApiPtr = Api;
//获取权限
DWORD dwOldProtect; //用于存储之前的权限
if (NULL == VirtualProtectEx(My_HookHandle, Api, 5, PAGE_READWRITE, &dwOldProtect)) {
My_ErrorState = ADM_ERROR;
return FALSE;
}
//保留原数据
if (FALSE == ReadProcessMemory(My_HookHandle, Api, My_Data, 5, NULL)) {
My_ErrorState = READ_MOME;
return FALSE;
}
//地址转换
ULONG Api_MoPtr = JumpApiPtr - (ULONG)&Api;
Api_MoPtr = Api_MoPtr - 5;
//将地址写入到操作码的后四位
char My_FuncPtr[5] = { 0 };
_asm
{
mov eax, Api_MoPtr //获取刚刚获得的地址
mov dword ptr[My_FuncPtr + 1], eax //将算出的地址保存到Arr后面4个字节
//注:一个函数地址占4个字节
}
My_FuncPtr[0] = 0xe9; //jump
//地址写入
DWORD dwOldProtectwrite;
WriteProcessMemory(My_HookHandle, Api, &My_FuncPtr, 5, &dwOldProtectwrite);
//权限恢复
DWORD dwTemp;
VirtualProtectEx(My_HookHandle, Api, 5, dwOldProtect, &dwTemp);
My_ErrorState = 100; //执行正常
return TRUE;
}
//恢复
BOOL HookApiRecoVery() {
//判断
if (strlen(My_Data) == 0) {
My_ErrorState = DATA_NO;
return FALSE;
}
if (My_ApiPtr == NULL) {
My_ErrorState = PTR_NO;
return FALSE;
}
//获取权限
DWORD dwOldProtect; //用于存储之前的权限
if (NULL == VirtualProtectEx(My_HookHandle, My_ApiPtr, 5, PAGE_READWRITE, &dwOldProtect)) {
My_ErrorState = ADM_ERROR;
return FALSE;
}
//地址写入
DWORD dwOldProtectwrite;
WriteProcessMemory(My_HookHandle, My_ApiPtr, &My_Data, 5, &dwOldProtectwrite);
//权限恢复
DWORD dwTemp;
VirtualProtectEx(My_HookHandle, My_ApiPtr, 5, dwOldProtect, &dwTemp);
My_ErrorState = 100; //执行正常
return TRUE;
}
//获取异常
INT OpenSerErrorMessage() {
return My_ErrorState;
printf("%d", My_ErrorState);
}
private:
HANDLE My_HookHandle; //进程句柄
TCHAR * My_DllName; //模块名
TCHAR * My_ApiName; //ApiName
UINT My_ErrorState; //异常错误码
FARPROC My_ApiPtr; //Hook的ApiPtr
TCHAR My_Data[5]; //Hook Api里的数据
HMODULE My_hInstance; //当前模块句柄
};