Hook 技術通常被稱為鈎子技術,Hook技術是Windows系統用於替代中斷機制的具體實現,鈎子的含義就是在程序還沒有調用系統函數之前,鈎子捕獲調用消息並獲得控制權,在執行系統調用之前執行自身程序,簡單來說就是函數劫持,本筆記將具體介紹應用層Hook的實現機制。
X86 手動完成 HOOK
首先我們來實現一個小功能,這里有一個小程序,當我們點擊彈窗時會自動的彈出一個MessageBox提示,我們的目標是通過注入DLL的方式Hook來實現去除這個彈窗,先來看一下Hook的思路:
1.調用 GetModuleHandle 來獲取到模塊的基址(user32.dll)
2.調用 GetProcAddress 獲取到MessageBoxA彈窗的基址
3.調用 VirtualProtect 來修改MsgBox前5個字節內存屬性
4.計算 Dest - MsgBox - 5 重定位跳轉地址,並Jmp跳轉
5.計算 Dest + Offset + 5 = MsgBox +5 跳轉回來的位置
1.首先我們載入這個程序,輸入MessageBoxA 找到我們需要Hook的地方,如下我們只需要在函數開頭寫入【jmp xxxx】該指令占用5字節,我們還需要記下被覆蓋的這三條指令,在我們自己的中轉函數中補齊它否則會導致堆棧不平衡。
我們還需要計算出程序的返回地址,只需要用【772A1f8A - 772A1F70 = 1A】返回地址就是基址加上1A
直接附上代碼:
#include <Windows.h>
#include <stdio.h>
DWORD jump = 0;
__declspec(naked) void Transfer(){
__asm{
mov edi, edi
push ebp
mov ebp, esp
mov ebx, jump
jmp ebx
}
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
HMODULE hwnd = GetModuleHandle(TEXT("user32.dll"));
DWORD base = (DWORD)GetProcAddress(hwnd, "MessageBoxA");
DWORD oldProtect = 0;
if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, &oldProtect))
{
DWORD value = (DWORD)Transfer - base - 5;
jump = base + 0x1a;
__asm{
mov eax, base
mov byte ptr[eax], 0xe9
inc eax
mov ebx, value
mov dword ptr[eax], ebx
}
VirtualProtect((LPVOID)base, 5, oldProtect, &oldProtect);
}
return true;
}
編譯上方代碼,然后使用注入工具注入到程序中,當我們點擊彈窗時,已經Hook成功。
Hook改標題: 通常情況下,程序設置標題會調用 SetWindowTextA 這個API函數,我們可以攔截這個函數,並傳進不同的窗口名稱,從而實現修改指定窗口的標題,其實先代碼只是在上面代碼的基礎上稍微改一下就能實現效果。
#include <Windows.h>
#include <stdio.h>
DWORD jump = 0;
__declspec(naked) bool _stdcall Transfer(HWND hwnd, LPCSTR lpString){
__asm{
mov edi, edi
push ebp
mov ebp, esp
mov ebx, jump
jmp ebx
}
}
bool __stdcall MySetWindowTextA(HWND hwnd, LPCSTR lpString){
char * lpText = "LyShark 破解版";
return Transfer(hwnd, lpText);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
HMODULE hwnd = GetModuleHandle(TEXT("user32.dll"));
DWORD base = (DWORD)GetProcAddress(hwnd, "SetWindowTextA");
DWORD oldProtect = 0;
if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, &oldProtect))
{
DWORD value = (DWORD)MySetWindowTextA - base - 5;
jump = base + 5;
__asm{
mov eax, base
mov byte ptr[eax], 0xe9
inc eax
mov ebx, value
mov dword ptr[eax], ebx
}
VirtualProtect((LPVOID)base, 5, oldProtect, &oldProtect);
}
return true;
}
X64 手動完成 Hook
64位與32位系統之間無論從尋址方式,還是語法規則都與x86架構有着本質的不同,所以上面的使用技巧只適用於32位程序,注入32位進程使用,下面的內容則是64位下手動完成hook掛鈎的一些騷操作,由於64位編譯器無法直接內嵌匯編代碼,導致我們只能調用C庫函數來實現Hook的中轉。
簡單的HookAPI例子:
#include <stdio.h>
#include <Windows.h>
#define HOOK_LEN 0xC
void HookMessageBox();
BYTE Ori_Code[HOOK_LEN] = { 0x00 };
BYTE HookCode[HOOK_LEN] = { 0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0 };
/*
MOV RAX, 0x9090909090909090
JMP RAX
*/
static int (WINAPI *OldMessageBoxW)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = MessageBoxW;
int WINAPI MyMessageBoxW(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
memcpy(OldMessageBoxW, &Ori_Code, sizeof(HookCode)); // 恢復hook原始代碼
int ret = OldMessageBoxW(hWnd, TEXT("hello lyshark"), lpCaption, uType); // 調用原函數
HookMessageBox(); // 繼續hook
return ret;
}
VOID HookMessageBox()
{
DWORD OldProtect;
if (VirtualProtect(OldMessageBoxW, HOOK_LEN, PAGE_EXECUTE_READWRITE, &OldProtect))
{
memcpy(Ori_Code, OldMessageBoxW, HOOK_LEN); // 拷貝原始機器碼指令
*(PINT64)(HookCode + 2) = (INT64)&MyMessageBoxW; // 填充90為指定跳轉地址
}
memcpy(OldMessageBoxW, &HookCode, sizeof(HookCode)); // 拷貝Hook機器指令
}
int main()
{
HookMessageBox();
MessageBoxW(NULL, TEXT("hello"), TEXT("標題"), MB_OK);
return 0;
}
應用於DLL注入的Hook
#include <stdio.h>
#include <Windows.h>
BYTE OldCode[12] = { 0x00 };
BYTE HookCode[12] = { 0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0 };
DWORD_PTR base;
int WINAPI MyMessageBoxW(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
return 1;
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
HMODULE hwnd = GetModuleHandle(TEXT("user32.dll"));
DWORD_PTR base = (DWORD_PTR)GetProcAddress(hwnd, "MessageBoxW");
DWORD OldProtect;
if (VirtualProtect((LPVOID)base, 12, PAGE_EXECUTE_READWRITE, &OldProtect))
{
memcpy(OldCode, (LPVOID)base, 12); // 拷貝原始機器碼指令
*(PINT64)(HookCode + 2) = (INT64)&MyMessageBoxW; // 填充90為指定跳轉地址
}
memcpy((LPVOID)base, &HookCode, sizeof(HookCode)); // 拷貝Hook機器指令
return true;
}
完善這個Hook代碼: 經過本人的不斷嘗試,最終寫出了完整的注入代碼,不容易啊,蒼天鴨!
// By: lyshark
// http://blib.cn
#include <stdio.h>
#include <Windows.h>
BYTE OldCode[12] = { 0x00 };
BYTE HookCode[12] = { 0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0 };
void HookFunction64(LPCWSTR lpModule, LPCSTR lpFuncName, LPVOID lpFunction)
{
DWORD_PTR FuncAddress = (UINT64)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
DWORD OldProtect = 0;
if (VirtualProtect((LPVOID)FuncAddress, 12, PAGE_EXECUTE_READWRITE, &OldProtect))
{
memcpy(OldCode, (LPVOID)FuncAddress, 12); // 拷貝原始機器碼指令
*(PINT64)(HookCode + 2) = (UINT64)lpFunction; // 填充90為指定跳轉地址
}
memcpy((LPVOID)FuncAddress, &HookCode, sizeof(HookCode)); // 拷貝Hook機器指令
VirtualProtect((LPVOID)FuncAddress, 12, OldProtect, &OldProtect);
}
void UnHookFunction64(LPCWSTR lpModule, LPCSTR lpFuncName)
{
DWORD OldProtect = 0;
UINT64 FuncAddress = (UINT64)GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
if (VirtualProtect((LPVOID)FuncAddress, 12, PAGE_EXECUTE_READWRITE, &OldProtect))
{
memcpy((LPVOID)FuncAddress, OldCode, sizeof(OldCode));
}
VirtualProtect((LPVOID)FuncAddress, 12, OldProtect, &OldProtect);
}
int WINAPI MyMessageBoxW(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
UnHookFunction64(L"user32.dll", "MessageBoxW");
int ret = MessageBoxW(0, L"hello lyshark", lpCaption, uType);
HookFunction64(L"user32.dll", "MessageBoxW", (PROC)MyMessageBoxW);
return ret;
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
switch (dword)
{
case DLL_PROCESS_ATTACH:
HookFunction64(L"user32.dll", "MessageBoxW", (PROC)MyMessageBoxW);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_DETACH:
break;
}
return true;
}
Detours 庫的使用(32位)
前面的內容我們是自己實現的Hook代碼,在生產環境中一般都會使用Hook庫,常用的Hook庫有免費開源的MinHook和商業的Detours Hook 這里我就默認使用Detours來測試32位下的Hook掛鈎,Detours的64位是商業版,這里我們只用他的32位。
Detours 庫在4.x開始就已經基於MIT許可開源了,GitHub地址: https://github.com/Microsoft/Detours
首先在Git上下載,下載好以后直接解壓到指定磁盤,然后使用VS的命令行工具並進入Detours目錄,直接數據命令 nmak
等待編譯完成,然后配置VS項目,在【調試】->【屬性】->【VC目錄】將include和lib目錄包含到項目中。
修改彈窗: 實現Hook MsgBox彈窗,該庫的原理與我們上面手動實現的方式是相同的,不過它這個庫更加的健壯。
#include <Windows.h>
#include <detours.h>
#pragma comment(lib,"detours.lib")
static int(WINAPI *OldMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT) = MessageBoxA;
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
return OldMessageBoxA(hWnd, TEXT("hello lyshark"), lpCaption, uType);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread()); // 執行線程准備
DetourAttach(&(PVOID&)OldMessageBoxA, MyMessageBoxA); // 掛鈎
DetourTransactionCommit();
}
return true;
}
簡單實現修改標題: 修改窗體標題,也可以使用這個庫,代碼非常簡潔,如下:
#include <Windows.h>
#include <detours.h>
#include <stdio.h>
#pragma comment(lib,"detours.lib")
static BOOL(WINAPI* Old_SetWindowTextA)(HWND hWnd, LPCSTR lpString) = SetWindowTextA;
BOOL WINAPI MySetWindowTextA(HWND hWnd, LPCSTR lpString){
return Old_SetWindowTextA(hWnd, "已破解");
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Old_SetWindowTextA, MySetWindowTextA);
DetourTransactionCommit();
}
return true;
}
實現攔截文件創建: 文件的創建離不開CreateFileA函數,我們可以Hook這個函數,來攔截程序創建文件,此方法可用於對抗惡意代碼,一些殺軟也會通過Hook的方式監控文件的創建。
#include <Windows.h>
#include <detours.h>
#include <stdio.h>
#pragma comment(lib,"detours.lib")
static HANDLE(WINAPI* Old_CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) = CreateFileA;
HANDLE WINAPI MyCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
char *temp = "c://test.txt";
if (strcmp(lpFileName, temp)){
MessageBoxA(0, TEXT("攔截到創建文件請求"), 0, 0);
lpFileName = "";
return Old_CreateFileA(lpFileName, dwDesiredAccess,dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes,hTemplateFile);
}
return Old_CreateFileA(lpFileName, dwDesiredAccess,
dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes,hTemplateFile);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Old_CreateFileA, MyCreateFileA);
DetourTransactionCommit();
}
return true;
}
實現Hook多個API:
#include <Windows.h>
#include <detours.h>
#include <stdio.h>
#pragma comment(lib,"detours.lib")
static BOOL(WINAPI* Old_SetWindowTextA)(HWND hWnd, LPCSTR lpString) = SetWindowTextA;
static int(WINAPI* Old_MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)=MessageBoxA;
BOOL WINAPI MySetWindowTextA(HWND hWnd, LPCSTR lpString){
return Old_SetWindowTextA(hWnd, "已破解");
}
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
return Old_MessageBoxA(hWnd, TEXT("彈窗已被重定向"), lpCaption, uType);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Old_SetWindowTextA, MySetWindowTextA);
DetourAttach(&(PVOID&)Old_MessageBoxA, MyMessageBoxA);
DetourTransactionCommit();
}
return true;
}
獲取程序OEP:
#include <Windows.h>
#include <detours.h>
#pragma comment(lib,"detours.lib")
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
DWORD ep = (DWORD)DetourGetEntryPoint(GetModuleHandle(0));
char str[10];
itoa(ep, str, 10);
MessageBoxA(0, str, 0, 0);
return true;
}
攔截DLL注入: 當本DLL被加載后,我們就無法向程序中注入DLL了,起到了簡單保護進程的目的。
#include <Windows.h>
#include <detours.h>
#include <stdio.h>
#pragma comment(lib,"detours.lib")
static HMODULE(WINAPI* Old_LoadLibraryA)(LPCSTR lpFileName) = LoadLibraryA;
static FARPROC(WINAPI* Old_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) = GetProcAddress;
HMODULE WINAPI MyLoadLibraryA(LPCSTR lpFileName){
return Old_LoadLibraryA("");
}
FARPROC WINAPI MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName){
return Old_GetProcAddress(0, "");
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Old_LoadLibraryA, MyLoadLibraryA);
DetourAttach(&(PVOID&)Old_GetProcAddress, MyGetProcAddress);
DetourTransactionCommit();
}
return true;
}
自定義Hook函數: 有時候我們需要自定義Hook對象,這時候我們就可以使用本方法,直接在最后寫上我們需要Hook的地址即可。
#include <Windows.h>
#include <detours.h>
#pragma comment(lib,"detours.lib")
static int(WINAPI* Old_MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) = (int(WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))0x755A1F70;
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
return Old_MessageBoxA(hWnd, lpText, lpCaption, uType);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
int Error = DetourTransactionBegin();
if (Error == NO_ERROR)
{
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(LPVOID&)Old_MessageBoxA, MyMessageBoxA);
DetourTransactionCommit();
}
return true;
}
MinHook 庫的使用(64位)
由於Detours hook庫的X64版本是商業版無法直接使用,想要X64掛鈎這里推薦使用MinHook,該Hook庫是完全開源免費的,使用起來也非常的簡單。
MinHook的GitHub地址:https://github.com/TsudaKageyu/minhook
首先在Git上下載,下載好以后直接解壓到指定磁盤,然后會看到一下目錄結構,選擇對應的版本,進行編譯即可。
編譯好后,會生成以下文件,拷貝這兩個文件,然后配合頭文件使用即可。
MinHook入門: 同樣是Hook MessageBox 用庫就這么簡單,自己寫很麻煩!
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x64.lib")
typedef int (WINAPI *MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);
MESSAGEBOXW fpMessageBoxW = NULL;
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
return fpMessageBoxW(hWnd, L"hello lyshark", lpCaption, uType);
}
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
switch (dword)
{
case DLL_PROCESS_ATTACH:
MH_Initialize();
MH_CreateHook(&MessageBoxW, &MyMessageBoxW, reinterpret_cast<void**>(&fpMessageBoxW));
MH_EnableHook(&MessageBoxW);
break;
case DLL_PROCESS_DETACH:
MH_DisableHook(&MessageBoxW);
MH_Uninitialize();
break;
}
return true;
}
監控系統進程創建: 將下方DLL注入到explorer.exe進程中,即可監控系統的進程創建,在其中可以做查殺檢測等,即可實現簡單的主動防御。
#include <Windows.h>
#include <stdio.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x64.lib")
typedef int (WINAPI *CREATEPROCESSW)(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES,
LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
CREATEPROCESSW pfnCreateProcessW = 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)
{
int nRetn = pfnCreateProcessW(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
MessageBoxW(0, lpApplicationName, 0, 0);
return nRetn;
}
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
if (MH_Initialize() == MH_OK)
{
OutputDebugStringW(L"MH_Initialize success");
}
if (MH_CreateHook(&CreateProcessW, &MyCreateProcessW, reinterpret_cast<void **>(&pfnCreateProcessW)) == MH_OK)
{
OutputDebugStringW(L"MH_CreateHook success");
}
if (MH_EnableHook(&CreateProcessW) == MH_OK)
{
OutputDebugStringW(L"MH_Initialize success");
}
return TRUE;
}
實現禁止結束進程: 通過將DLL注入到系統的任務管理器中,實現禁止QQ進程被強制結束。
#include <Windows.h>
#include <stdio.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x64.lib")
typedef HANDLE(WINAPI *OPENPROCESS)(DWORD, BOOL, DWORD);
OPENPROCESS pfnOpenProcess = NULL;
HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
HWND myhwnd = 0;
myhwnd = FindWindowW(L"TXGuiFoundation", L"QQ");
if (myhwnd != NULL)
{
HANDLE Retn = pfnOpenProcess(dwDesiredAccess, bInheritHandle, 0);
return Retn;
}
HANDLE Retn = pfnOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
return Retn;
}
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
MH_Initialize();
MH_CreateHook(&OpenProcess, &MyOpenProcess, reinterpret_cast<void **>(&pfnOpenProcess));
MH_EnableHook(&OpenProcess);
return TRUE;
}
上方代碼需要注意:任務管理器終止進程其實是調用了TerminateProcess
函數來執行強殺進程的,正常情況下應該hook該函數,但此處我們Hook了OpenProcess
這個打開進程的API,這是因為在我們結束進程時,系統會先打開進程來獲取到進程句柄,然后才會調用TerminateProcess
並傳遞句柄來強制殺掉進程,我們只需要讓打開進程失效,此時TerminateProcess函數將得不到正確的句柄,從而無法完成結束進程。
32/64 Min Hook (更多案例)
Hook 實現修改彈窗: 實現Hook MsgBox
彈窗,該庫的原理與我們上面手動實現的方式是相同的.
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x86.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", 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 實現修改標題:
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x86.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 實現攔截文件創建: 文件的創建離不開CreateFileA函數,我們可以Hook這個函數,來攔截程序創建文件,此方法可用於對抗惡意代碼,一些殺軟也會通過Hook的方式監控文件的創建。
#include <Windows.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x86.lib")
typedef HANDLE(WINAPI *OldCreateFileA)(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
OldCreateFileA fpCreateFileA = NULL;
// 定義個性化的CreateFileA 並實現過濾功能
HANDLE WINAPI MyCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
char *path = "c://test.txt";
if (strcmp(lpFileName, path))
{
MessageBoxA(NULL, lpFileName, "MsgBox", NULL);
MessageBoxA(0, TEXT("攔截到創建文件請求"), 0, 0);
lpFileName = "";
}
return fpCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
void SetHook()
{
if (MH_Initialize() == MB_OK)
{
// 參數一: 函數名稱 參數二: 自定義函數 參數三: 原始函數指針
MH_CreateHook(&CreateFileA, &MyCreateFileA, reinterpret_cast<void**>(&fpCreateFileA));
MH_EnableHook(&CreateFileA);
}
}
void UnHook()
{
if (MH_DisableHook(&CreateFileA) == 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注入到explorer.exe
進程中,即可監控系統的進程創建,在其中可以做查殺檢測等,即可實現簡單的主動防御.
#include <Windows.h>
#include <stdio.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x64.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;
}
Hook 實現禁止結束進程: 通過將DLL注入到系統的任務管理器中,實現禁止結束某個進程,任務管理器通過調用TerminateProcess()
函數來執行強殺進程,我們只需要Hook系統中的OpenProcess()
打開進程並讓其返回假,那么TerminateProcess()
拿不到句柄也就無法完成結束進程了.
#include <Windows.h>
#include <stdio.h>
#include <MinHook.h>
#pragma comment(lib,"libMinHook.x64.lib")
typedef HANDLE(WINAPI *OldOpenProcess)(DWORD, BOOL, DWORD);
OldOpenProcess fpOpenProcess = NULL;
HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
HWND handle = NULL;
handle = FindWindow(L"TXGuiFoundation", L"QQ");
if (handle != NULL)
{
HANDLE Retn = fpOpenProcess(dwDesiredAccess, bInheritHandle, 0);
return Retn;
}
HANDLE Retn = fpOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
return Retn;
}
void SetHook()
{
if (MH_Initialize() == MB_OK)
{
// 參數一: 函數名稱 參數二: 自定義函數 參數三: 原始函數指針
MH_CreateHook(&OpenProcess, &MyOpenProcess, reinterpret_cast<void**>(&MyOpenProcess));
MH_EnableHook(&OpenProcess);
}
}
void UnHook()
{
if (MH_DisableHook(&OpenProcess) == 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;
}