描述
- 拦截messagebox函数,调用自己的MyMessageBox,然后再调用原函数
原理
- 本文进行了针对程序输入表的address hook,通过GetProcAddress获取原messagebox的地址,通过比对IAT内的地址,找到存放messagebox的项,将其替换为MyMessageBox的地址
- 将MyMessageBox实现的代码放到dll中,注入到目标程序中使用,在MyMessageBox函数的最后调用了原messagebox,实现Detour
步骤
- 编写dll,这里随便加了一个导出函数MyTestFunc,用于注入
#include <windows.h>
#include <cstdio>
typedef int (WINAPI* PfnMsgA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
PfnMsgA g_OldPfnMsgA = nullptr;
int WINAPI MyMessageBox(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
char sz1[] = "检测到原来的输出为:";
char sz2[] = "\n将输出修改为:进入游戏失败哈哈!";
strcat(sz1, (char*)lpText);
strcat(sz1, sz2);
if (g_OldPfnMsgA != nullptr)
{
return g_OldPfnMsgA(hWnd, sz1, lpCaption, uType);
}
return 0;
}
void SetIatHook()
{
MessageBoxA(NULL, "开始进行HOOK", "提示", NULL);
PVOID pHookAddress = nullptr;
pHookAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
if (nullptr == pHookAddress)
{
OutputDebugString(TEXT("获取函数地址失败"));
MessageBoxA(NULL, "获取函数地址失败HOOK", NULL, NULL);
return;
}
printf("msgbox函数地址为:%llx", pHookAddress);
g_OldPfnMsgA = (PfnMsgA)pHookAddress;
HMODULE hModImageBase = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(DWORD_PTR)hModImageBase;
DWORD_PTR dwTemp = (DWORD_PTR)pDosHead + (DWORD_PTR)pDosHead->e_lfanew;
PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)dwTemp;
PIMAGE_FILE_HEADER pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;
DWORD_PTR dwExportLocal = pOptHead->DataDirectory[1].VirtualAddress;
dwTemp = (DWORD_PTR)GetModuleHandle(NULL) + dwExportLocal;
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)dwTemp;
PIMAGE_IMPORT_DESCRIPTOR pCurrent = pImport;
DWORD_PTR* pFirstThunk;
while (pCurrent->Characteristics && pCurrent->FirstThunk != NULL)
{
dwTemp = pCurrent->FirstThunk + (DWORD_PTR)GetModuleHandle(NULL);
pFirstThunk = (DWORD_PTR*)dwTemp;
while (*(DWORD_PTR*)pFirstThunk != NULL)
{
if (*(DWORD_PTR*)pFirstThunk == (DWORD_PTR)g_OldPfnMsgA)
{
DWORD oldProtected;
VirtualProtect(pFirstThunk, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtected);
dwTemp = (DWORD_PTR)MyMessageBox;
memcpy(pFirstThunk, (DWORD_PTR*)&dwTemp, 8);
VirtualProtect(pFirstThunk, 0x1000, oldProtected, &oldProtected);
MessageBoxA(NULL, "修改函数完毕!", "提示", NULL);
}
pFirstThunk++;
}
pCurrent++;
}
}
void UnIatHook()
{
MessageBoxA(NULL, "开始进行HOOK", NULL, NULL);
PVOID64 pHookAddress = nullptr;
pHookAddress = MyMessageBox;
if (nullptr == pHookAddress)
{
OutputDebugString(TEXT("获取函数地址失败"));
MessageBoxA(NULL, "恢复函数地址失败HOOK", NULL, NULL);
return;
}
HMODULE hModImageBase = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(DWORD)hModImageBase;
DWORD dwTemp = (DWORD)pDosHead + (DWORD)pDosHead->e_lfanew;
PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)dwTemp;
PIMAGE_FILE_HEADER pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;
DWORD dwExportLocal = pOptHead->DataDirectory[1].VirtualAddress;
dwTemp = (DWORD)GetModuleHandle(NULL) + dwExportLocal;
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)dwTemp;
PIMAGE_IMPORT_DESCRIPTOR pCurrent = pImport;
DWORD* pFirstThunk;
while (pCurrent->Characteristics && pCurrent->FirstThunk != NULL)
{
dwTemp = pCurrent->FirstThunk + (DWORD)GetModuleHandle(NULL);
pFirstThunk = (DWORD*)dwTemp;
while (*(DWORD*)pFirstThunk != NULL)
{
if (*(DWORD*)pFirstThunk == (DWORD)MyMessageBox)
{
DWORD oldProtected;
VirtualProtect(pFirstThunk, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtected);
dwTemp = (DWORD)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
memcpy(pFirstThunk, (DWORD*)&dwTemp, 4);
VirtualProtect(pFirstThunk, 0x1000, oldProtected, &oldProtected);
}
pFirstThunk++;
}
pCurrent++;
}
}
extern "C" __declspec(dllexport) int MyTestFunc(int a, int b)
{
return a + b;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
SetIatHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
- 通过PE Tools修改原程序输入表,注入dll

效果
- 将HookMsg.dll放到原程序目录下,运行原程序,成功拦截原messagebox调用

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库