MinHook是一個輕量級的Hooking庫,可以在運行時劫持函數調用。它支持鉤子API函數和普通函數,並且可以運行在32位和64位Windows操作系統上。其特點包括易於使用、高性能和低內存佔用。MinHook使用純彙編語言實現,在安裝和卸載鉤子時只需要短暫地鎖定目標線程,因此對目標線程的影響非常小。
- GitHub地址: https://github.com/TsudaKageyu/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
文件中,至此當有新進程被加載時則會彈出該進程的詳細路徑信息,如下圖所示;
本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/c425464c.html
版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!