Inline Hook 鈎子編寫技巧


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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM