免杀基础-hook
字数 1033 2025-08-22 12:23:18
Hook技术详解:从基础到实践
1. Hook技术概述
Hook(挂钩)是一种用于拦截函数执行过程的技术,主要目的是获取或修改函数执行时的数据,或者更改程序的执行流程。Hook技术主要分为两大类:
- 修改函数代码:如Inline Hook
- 修改函数地址:如IAT Hook、SSDT Hook
2. Inline Hook技术
2.1 基本原理
Inline Hook的特点是直接修改目标函数的代码,通常在函数入口处插入跳转指令,将控制流引导至自定义的处理逻辑。
2.2 32位实现
代码修改方式
在32位系统下,通常patch目标函数前7个字节:
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpMem
0xFF, 0xE0 // jmp eax
实现步骤
- 保存原始字节
- 构造跳转代码
- 修改内存保护属性
- 写入跳转代码
示例代码
int myMessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption, _In_ UINT uType) {
printf("111111111\n");
memcpy(Hookedfunc, originalBytes, 7); // 解除hook防止无限循环
int res = MessageBoxW(hWnd, lpText, lpCaption, uType);
installHook(Hookedfunc, myMessageBoxW); // 重新挂钩
return res;
};
void installHook(LPVOID Hookedfunc, LPVOID targetFunc) {
DWORD oldProtection;
char code[] = {
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpMem
0xFF, 0xE0 // jmp eax
};
memcpy(originalBytes, Hookedfunc, 7);
DWORD_PTR lpMem = (DWORD_PTR)targetFunc;
memcpy(&code[1], &lpMem, sizeof(lpMem));
VirtualProtect(Hookedfunc, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy(Hookedfunc, code, sizeof(code));
}
2.3 64位实现
64位实现与32位类似,但需要修改13个字节:
0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, lpMem
0x41, 0xFF, 0xE2 // jmp r10
示例代码
int myMessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption, _In_ UINT uType) {
printf("111111111\n");
memcpy(Hookedfunc, originalBytes, 13);
int res = MessageBoxW(hWnd, lpText, lpCaption, uType);
installHook(Hookedfunc, myMessageBoxW);
return res;
};
void installHook(LPVOID Hookedfunc, LPVOID targetFunc) {
DWORD oldProtection;
char code[] = {
0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, lpMem
0x41, 0xFF, 0xE2 // jmp r10
};
memcpy(originalBytes, Hookedfunc, 13);
DWORD_PTR lpMem = (DWORD_PTR)targetFunc;
memcpy(&code[2], &lpMem, sizeof(lpMem));
VirtualProtect(Hookedfunc, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy(Hookedfunc, code, sizeof(code));
}
3. IAT Hook技术
3.1 基本原理
IAT(Import Address Table) Hook通过修改导入地址表中的函数地址来实现Hook。当程序调用API时,会通过IAT查找函数地址,修改IAT即可改变程序行为。
3.2 实现步骤
- 获取目标模块的IAT
- 查找目标函数在IAT中的位置
- 修改IAT中的函数地址
3.3 示例代码
// 获取IAT并查找目标函数
HMODULE hModule = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + pDosHeader->e_lfanew);
PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)&pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR pimport = (PIMAGE_IMPORT_DESCRIPTOR)(pDataDir->VirtualAddress + (DWORD_PTR)hModule);
FARPROC funcAddr = NULL;
while(pimport->Name != 0) {
PIMAGE_THUNK_DATA pOriginalThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)hModule + pimport->OriginalFirstThunk);
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)hModule + pimport->FirstThunk);
while(pOriginalThunk->u1.AddressOfData != 0) {
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)hModule + pOriginalThunk->u1.AddressOfData);
if(_stricmp(pImportByName->Name, "MessageBoxW") == 0) {
funcAddr = (FARPROC)pThunk->u1.Function;
break;
}
pOriginalThunk++;
pThunk++;
}
pimport++;
}
// 定义替换函数
PVOID oldMessageBox = MessageBoxW;
typedef int(WINAPI* pMessageBoxW)(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption, _In_ UINT uType);
int myMessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption, _In_ UINT uType) {
printf("111111111\n");
pMessageBoxW MsgBox = (pMessageBoxW)oldMessageBox;
return MsgBox(hWnd, lpText, lpCaption, uType);
};
// 修改IAT
DWORD oldProtect;
VirtualProtect(&pThunk->u1.Function, 8, PAGE_READWRITE, &oldProtect);
pThunk->u1.Function = (DWORD_PTR)myMessageBoxW;
VirtualProtect(&pThunk->u1.Function, 8, oldProtect, &oldProtect);
4. SSDT Hook技术
4.1 基本原理
SSDT(System Service Descriptor Table) Hook通过修改系统服务描述符表中的函数指针来实现内核级别的Hook。
4.2 实现步骤
- 获取SSDT表
- 查找目标系统服务的索引
- 修改SSDT表中的函数指针
4.3 示例代码
// 定义SSDT结构
typedef struct _ServiceDescriptorTable {
PVOID pSSDTBase;
PVOID pServiceCounterTable;
ULONG ulNumberOfServices;
PVOID pParamTableBase;
} ServiceDescriptorTable, *PServiceDescriptorTable;
extern PServiceDescriptorTable KeServiceDescriptorTable;
// Hook NtAllocateVirtualMemory (调用号13)
__try {
PVOID serviceTableBase = KeServiceDescriptorTable->pSSDTBase;
PVOID NtAllocateVirtualMemoryBase = (DWORD_PTR)serviceTableBase + (0x13 * sizeof(void*));
DbgPrint("0x%p\n", NtAllocateVirtualMemoryBase);
// 保存原始函数并替换
oriNtAllocateVirtualMemoryProc = *(PVOID*)NtAllocateVirtualMemoryBase;
*(PVOID*)NtAllocateVirtualMemoryBase = myNtAllocateVirtualMemory;
DbgPrint("Hooked!\n");
} __except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
// 定义替换函数
PVOID NtAllocateVirtualMemoryBase = NULL;
PVOID oriNtAllocateVirtualMemoryProc = NULL;
NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(
_In_ HANDLE ProcessHandle,
_Inout_ _At_(*BaseAddress, _Readable_bytes_(*RegionSize) _Writable_bytes_(*RegionSize) _Post_readable_byte_size_(*RegionSize)) PVOID* BaseAddress,
_In_ ULONG_PTR ZeroBits,
_Inout_ PSIZE_T RegionSize,
_In_ ULONG AllocationType,
_In_ ULONG Protect);
NTSTATUS NTAPI myNtAllocateVirtualMemory(
_In_ HANDLE ProcessHandle,
_Inout_ PVOID* BaseAddress,
_In_ ULONG_PTR ZeroBits,
_Inout_ PSIZE_T RegionSize,
_In_ ULONG AllocationType,
_In_ ULONG Protect) {
HANDLE currentProcess = PsGetCurrentProcess();
PCHAR currentProcessName = PsGetProcessImageFileName(currentProcess);
DbgPrint("%s\n", currentProcessName);
if(_stricmp(currentProcessName, "Console.") == 0) {
DbgPrint("111111\n");
}
pNtAllocateVirtualMemory oriNtAllocateVirtualMemory = (pNtAllocateVirtualMemory)oriNtAllocateVirtualMemoryProc;
return oriNtAllocateVirtualMemory(ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect);
}
// 卸载时恢复
NTSTATUS UnloadDriver(PDRIVER_OBJECT DriverObject) {
*(PVOID*)NtAllocateVirtualMemoryBase = oriNtAllocateVirtualMemoryProc;
DbgPrint("Unload!");
}
5. 使用Detours库实现Hook
Detours是微软开源的Hook库,使用简单方便。
5.1 示例代码
#include <Windows.h>
#include <iostream>
#include <detours.h>
int WINAPI MyMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption, _In_ UINT uType) {
std::cout << "Hooked!" << std::endl;
return 0;
}
int main() {
auto msgbox = (void*)MessageBoxA;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&msgbox, MyMessageBoxA);
DetourTransactionCommit();
MessageBoxA(0, 0, 0, 0);
getchar();
}
6. 注意事项
- 线程安全:Hook操作需要考虑多线程环境下的安全性
- 内存保护:修改代码前需要调整内存保护属性
- 恢复机制:确保能够正确恢复原始函数
- 性能影响:频繁的Hook/Unhook操作可能影响性能
- 稳定性:内核Hook可能导致系统不稳定,需谨慎使用
7. 应用场景
- 安全防护:监控敏感API调用
- 行为分析:分析恶意软件行为
- 功能扩展:扩展系统功能
- 调试辅助:辅助调试复杂系统
8. 总结
Hook技术是二进制安全领域的重要技术,掌握各种Hook方法对于安全研究、逆向工程和软件开发都有重要意义。在实际应用中,需要根据具体场景选择合适的Hook方式,并注意稳定性、性能和兼容性问题。