MinHook是一个轻量级的Hooking库,可以在运行时劫持函数调用。它支持钩子API函数和普通函数,并且可以运行在32位和64位Windows操作系统上。其特点包括易于使用、高性能和低内存占用。MinHook使用纯汇编语言实现,在安装和卸载钩子时只需要短暂地锁定目标线程,因此对目标线程的影响非常小。
读者可自行下载对应的库文件,本节所使用的是MinHook_133_lib
版本,并配置好对应的包含文件以及库目录,如下图所示;
实现修改弹窗提示
如下一段代码其作用是hook MessageBoxA
函数,当程序调用MessageBoxA
时,会调用MyMessageBoxA
函数代替原来的MessageBoxA
函数进行处理,而MyMessageBoxA
函数会将调用信息改成Hook Inject
。
示例中的SetHook
函数用于创建并启用hook
,使用MH_Initialize
进行MinHook
库初始化,然后使用MH_CreateHook
创建钩子并保存MessageBoxA
原函数指针到fpMessageBoxA
中,最后使用MH_EnableHook
启用hook
。而UnHook
函数用于禁用和释放hook
,使用MH_DisableHook
禁用钩子,然后使用MH_Uninitialize
释放MinHook
库资源。
在DllMain
函数中,如果是DLL
进程附加事件,则执行SetHook
函数,如果是DLL
进程分离事件,则执行UnHook
函数禁用和释放钩子。
#include <Windows.h> #include <MinHook.h>
#pragma comment(lib,"libMinHook-x86-v120-md.lib")
typedef int (WINAPI *OldMessageBox)(HWND, LPCSTR, LPCSTR, UINT);
OldMessageBox fpMessageBoxA = NULL;
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { int ret = fpMessageBoxA(hWnd, "Hook Inject hello lyshark", lpCaption, uType); return ret; }
void SetHook() { if (MH_Initialize() == MB_OK) { MH_CreateHook(&MessageBoxA, &MyMessageBoxA, reinterpret_cast<void**>(&fpMessageBoxA)); MH_EnableHook(&MessageBoxA); } }
void UnHook() { if (MH_DisableHook(&MessageBoxA) == MB_OK) { MH_Uninitialize(); } }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: SetHook(); break; case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; }
|
编译上述代码,使用注入器将hook.dll
注入到特定进程内,此时点击弹窗提示会发现弹窗内容已经被替代了,如下图所示;
实现修改窗口标题
一般来说程序中的修改标题功能都是调用SetWindowTextA
来实现的,我们可以Hook这个函数对其进行处理后返回新标题即可,当然也可以钩挂住GetWindowTextA
函数,同样可以实现标题的修改。
如下代码通过对SetWindowTextA
函数进行挂钩,当读者点击设置标题是则触发自定义fpSetWindowTextA
函数,该函数内部通过调用自定义标题修改函数实现了将当前软件标题替换为破解版本
,并返回给用户。
#include <Windows.h> #include <MinHook.h>
#pragma comment(lib,"libMinHook-x86-v120-md.lib")
typedef BOOL(WINAPI *OldSetWindowTextA)(HWND, LPCSTR);
OldSetWindowTextA fpSetWindowTextA = NULL;
BOOL WINAPI MySetWindowTextA(HWND hWnd, LPCSTR lpString) { BOOL ret = fpSetWindowTextA(hWnd, "破解版本"); return ret; }
void SetHook() { if (MH_Initialize() == MB_OK) { MH_CreateHook(&SetWindowTextA, &MySetWindowTextA, reinterpret_cast<void**>(&fpSetWindowTextA)); MH_EnableHook(&SetWindowTextA); } }
void UnHook() { if (MH_DisableHook(&SetWindowTextA) == MB_OK) { MH_Uninitialize(); } }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: SetHook(); break; case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; }
|
当读者将hook.dll
注入到程序中后,我们再次点击设置标题按钮,此时标题将被修改为破解版本,如下图所示;
实现监控进程创建
要实现监控进程创建,我们可以通过MinHook
库来钩住explorer.exe
程序,通过劫持程序内的CreateProcessW
函数,在Windows
操作系统中,大部分进程都是由 explorer.exe
进程派生出来的。explorer.exe 是Windows
资源管理器的主进程,负责启动和管理用户界面、任务栏、桌面等。
当用户登录到系统后,explorer.exe 进程会自动启动,并成为用户交互的主要界面。在用户打开应用程序、文件夹或执行其他操作时,explorer.exe 进程会根据用户的请求创建新的进程来运行相应的应用程序或执行相应的任务。
通过对该进程进行挂钩,即可实现监控应用层其他进程创建或销毁的目的,读者可自行使用64位库编译下方代码,并注入到explorer.exe
进程中,即可实现监控进程的创建功能。
#include <Windows.h> #include <MinHook.h>
#pragma comment(lib,"libMinHook-x64-v120-md.lib")
typedef int (WINAPI *OldCreateProcessW)(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
OldCreateProcessW fpCreateProcessW = NULL;
int WINAPI MyCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { MessageBoxW(0, lpApplicationName, 0, 0);
int nRetn = fpCreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); return nRetn; }
void SetHook() { if (MH_Initialize() == MB_OK) { MH_CreateHook(&CreateProcessW, &MyCreateProcessW, reinterpret_cast<void**>(&fpCreateProcessW)); MH_EnableHook(&CreateProcessW); } }
void UnHook() { if (MH_DisableHook(&CreateProcessW) == MB_OK) { MH_Uninitialize(); } }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: SetHook(); break; case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; }
|
读者可使用x64
模式编译上方代码,并将其注入到explorer.exe
文件中,至此当有新进程被加载时则会弹出该进程的详细路径信息,如下图所示;