免杀基础-hook
字数 1033 2025-08-22 12:23:18

Hook技术详解:从基础到实践

1. Hook技术概述

Hook(挂钩)是一种用于拦截函数执行过程的技术,主要目的是获取或修改函数执行时的数据,或者更改程序的执行流程。Hook技术主要分为两大类:

  1. 修改函数代码:如Inline Hook
  2. 修改函数地址:如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

实现步骤

  1. 保存原始字节
  2. 构造跳转代码
  3. 修改内存保护属性
  4. 写入跳转代码

示例代码

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 实现步骤

  1. 获取目标模块的IAT
  2. 查找目标函数在IAT中的位置
  3. 修改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 实现步骤

  1. 获取SSDT表
  2. 查找目标系统服务的索引
  3. 修改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. 注意事项

  1. 线程安全:Hook操作需要考虑多线程环境下的安全性
  2. 内存保护:修改代码前需要调整内存保护属性
  3. 恢复机制:确保能够正确恢复原始函数
  4. 性能影响:频繁的Hook/Unhook操作可能影响性能
  5. 稳定性:内核Hook可能导致系统不稳定,需谨慎使用

7. 应用场景

  1. 安全防护:监控敏感API调用
  2. 行为分析:分析恶意软件行为
  3. 功能扩展:扩展系统功能
  4. 调试辅助:辅助调试复杂系统

8. 总结

Hook技术是二进制安全领域的重要技术,掌握各种Hook方法对于安全研究、逆向工程和软件开发都有重要意义。在实际应用中,需要根据具体场景选择合适的Hook方式,并注意稳定性、性能和兼容性问题。

Hook技术详解:从基础到实践 1. Hook技术概述 Hook(挂钩)是一种用于拦截函数执行过程的技术,主要目的是获取或修改函数执行时的数据,或者更改程序的执行流程。Hook技术主要分为两大类: 修改函数代码 :如Inline Hook 修改函数地址 :如IAT Hook、SSDT Hook 2. Inline Hook技术 2.1 基本原理 Inline Hook的特点是直接修改目标函数的代码,通常在函数入口处插入跳转指令,将控制流引导至自定义的处理逻辑。 2.2 32位实现 代码修改方式 在32位系统下,通常patch目标函数前7个字节: 实现步骤 保存原始字节 构造跳转代码 修改内存保护属性 写入跳转代码 示例代码 2.3 64位实现 64位实现与32位类似,但需要修改13个字节: 示例代码 3. IAT Hook技术 3.1 基本原理 IAT(Import Address Table) Hook通过修改导入地址表中的函数地址来实现Hook。当程序调用API时,会通过IAT查找函数地址,修改IAT即可改变程序行为。 3.2 实现步骤 获取目标模块的IAT 查找目标函数在IAT中的位置 修改IAT中的函数地址 3.3 示例代码 4. SSDT Hook技术 4.1 基本原理 SSDT(System Service Descriptor Table) Hook通过修改系统服务描述符表中的函数指针来实现内核级别的Hook。 4.2 实现步骤 获取SSDT表 查找目标系统服务的索引 修改SSDT表中的函数指针 4.3 示例代码 5. 使用Detours库实现Hook Detours是微软开源的Hook库,使用简单方便。 5.1 示例代码 6. 注意事项 线程安全 :Hook操作需要考虑多线程环境下的安全性 内存保护 :修改代码前需要调整内存保护属性 恢复机制 :确保能够正确恢复原始函数 性能影响 :频繁的Hook/Unhook操作可能影响性能 稳定性 :内核Hook可能导致系统不稳定,需谨慎使用 7. 应用场景 安全防护 :监控敏感API调用 行为分析 :分析恶意软件行为 功能扩展 :扩展系统功能 调试辅助 :辅助调试复杂系统 8. 总结 Hook技术是二进制安全领域的重要技术,掌握各种Hook方法对于安全研究、逆向工程和软件开发都有重要意义。在实际应用中,需要根据具体场景选择合适的Hook方式,并注意稳定性、性能和兼容性问题。