恶意代码分析系列-几种常用技术(2)
字数 1291 2025-08-15 21:31:07

Windows进程注入技术详解

一、概述

进程注入是一种常见的技术,用于在目标进程空间中执行自定义代码,通常用于修改目标进程行为或使用目标进程身份执行操作。本文将详细介绍四种常用的Windows进程注入技术。

二、全局钩子注入

1. 原理

Windows应用程序基于消息机制运行,全局钩子可以截获和监视整个系统的消息。全局钩子需要使用DLL文件,在DLL中实现钩子函数。

2. 关键API

SetWindowsHookEx()

HHOOK WINAPI SetWindowsHookExA(
    _In_ int idHook,          // 钩子类型(WH_KEYBOARD, WH_MOUSE)
    _In_ HOOKPROC lpfn,       // 钩子过程指针
    _In_opt_ HINSTANCE hmod,  // 包含钩子过程的DLL句柄
    _In_ DWORD dwThreadId     // 关联的线程ID(0表示所有GUI线程)
);

UnhookWindowsHookEx()

BOOL UnhookWindowsHookEx(
    HHOOK hhk  // 要卸载的钩子句柄
);

钩子回调函数

LRESULT WINAPI CallNextHookEx(
    _In_opt_ HHOOK hhk,
    _In_ int nCode,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
);

3. 实现步骤

  1. 创建DLL,实现钩子过程函数
  2. 使用SetWindowsHookEx安装全局钩子
  3. 系统将DLL注入到所有符合条件的进程中
  4. 通过UnhookWindowsHookEx卸载钩子

三、远程线程注入

1. 原理

在目标进程中创建线程执行自定义代码,是最经典的注入技术。

2. 关键API

OpenProcess()

HANDLE WINAPI OpenProcess(
    _In_ DWORD dwDesiredAccess,  // 访问权限(PROCESS_ALL_ACCESS)
    _In_ BOOL bInheritHandle,    // 是否可继承
    _In_ DWORD dwProcessId       // 目标进程PID
);

VirtualAllocEx()

LPVOID WINAPI VirtualAllocEx(
    _In_ HANDLE hProcess,        // 目标进程句柄
    _In_opt_ LPVOID lpAddress,   // 分配地址(NULL表示自动分配)
    _In_ SIZE_T dwSize,          // 分配大小
    _In_ DWORD flAllocationType, // 分配类型(MEM_COMMIT等)
    _In_ DWORD flProtect         // 内存保护(PAGE_EXECUTE_READWRITE等)
);

WriteProcessMemory()

BOOL WINAPI WriteProcessMemory(
    _In_ HANDLE hProcess,        // 目标进程句柄
    _In_ LPVOID lpBaseAddress,   // 写入基址
    _In_reads_bytes_(nSize) LPCVOID lpBuffer, // 数据缓冲区
    _In_ SIZE_T nSize,           // 写入大小
    _Out_opt_ SIZE_T* lpNumberOfBytesWritten // 实际写入大小
);

CreateRemoteThread()

HANDLE WINAPI CreateRemoteThread(
    _In_ HANDLE hProcess,                   // 目标进程句柄
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性
    _In_ SIZE_T dwStackSize,                // 堆栈大小(0表示默认)
    _In_ LPTHREAD_START_ROUTINE lpStartAddress, // 线程起始地址
    _In_opt_ LPVOID lpParameter,            // 线程参数
    _In_ DWORD dwCreationFlags,             // 创建标志(0表示立即运行)
    _Out_opt_ LPDWORD lpThreadId            // 接收线程ID
);

3. 实现步骤

  1. 使用OpenProcess打开目标进程
  2. 使用VirtualAllocEx在目标进程中分配内存
  3. 使用WriteProcessMemory将Shellcode或DLL路径写入目标进程
  4. 使用CreateRemoteThread创建远程线程执行代码

4. 注意事项

  • 对于系统服务(SESSION 0隔离),需使用ZwCreateThreadEx替代CreateRemoteThread
  • 需要确保目标进程内存区域可访问

四、APC队列注入

1. 原理

利用异步过程调用(APC)机制,当线程处于可通知状态时执行APC队列中的函数。

2. 关键API

QueueUserAPC()

DWORD WINAPI QueueUserAPC(
    _In_ PAPCFUNC pfnAPC,    // APC函数指针
    _In_ HANDLE hThread,     // 目标线程句柄
    _In_ ULONG_PTR dwData    // 传递给APC函数的数据
);

3. 实现步骤

  1. 枚举目标进程的所有线程
  2. 向每个线程插入APC(通常指向LoadLibrary)
  3. 当线程进入可通知状态时执行APC

4. 特点

  • 成功率与线程状态相关
  • 可向多个线程插入APC增加成功率
  • 常用于DLL注入

五、自定义HOOK技术

1. Inline Hook

原理

通过修改目标函数的前几个字节为JMP指令,跳转到自定义函数。

实现步骤

  1. 获取目标函数地址
  2. 保存原始字节
  3. 修改内存保护属性为可写
  4. 计算跳转偏移并写入JMP指令
  5. 恢复内存保护属性

示例代码

void OnHook() {
    // 获取函数地址
    HMODULE Module = GetModuleHandleA("kernel32.dll");
    LPVOID func = GetProcAddress(Module, "OpenProcess");
    
    // 保存原始5字节
    memcpy(g_oldCode, func, 5);
    
    // 修改内存属性
    DWORD dwProtect;
    VirtualProtect(func, 5, PAGE_EXECUTE_READWRITE, &dwProtect);
    
    // 计算跳转偏移并写入
    *(DWORD*)&g_newCode[1] = (DWORD)MyOpenProcess - (DWORD)func - 5;
    memcpy(func, g_newCode, 5);
    
    // 恢复内存属性
    VirtualProtect(func, 5, dwProtect, &dwProtect);
}

2. IAT Hook

原理

通过修改导入地址表(IAT)中的函数地址实现Hook。

实现步骤

  1. 解析PE文件结构,定位IAT表
  2. 查找目标DLL和函数在IAT中的位置
  3. 修改IAT中的函数地址为自定义函数地址

关键代码

DWORD* GetIatAddress(const char* dllName, const char* funName) {
    // 获取DOS头
    auto DosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
    
    // 获取NT头
    auto NtHeader = (PIMAGE_NT_HEADERS)(DosHeader->e_lfanew + (DWORD)DosHeader);
    
    // 获取导入表RVA
    DWORD ImpRVA = NtHeader->OptionalHeader.DataDirectory[1].VirtualAddress;
    
    // 获取导入表
    auto ImpTable = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)DosHeader + ImpRVA);
    
    // 遍历导入表
    while (ImpTable->Name) {
        CHAR* Name = (CHAR*)(ImpTable->Name + (DWORD)DosHeader);
        
        if (!_stricmp(Name, dllName)) {
            // 获取INT和IAT表
            DWORD* IntTable = (DWORD*)((DWORD)DosHeader + ImpTable->OriginalFirstThunk);
            DWORD* IatTable = (DWORD*)((DWORD)DosHeader + ImpTable->FirstThunk);
            
            // 遍历函数
            for (int i = 0; IntTable[i] != 0; ++i) {
                if ((IntTable[i] & 0x80000000) == 0) {
                    auto Name = (PIMAGE_IMPORT_BY_NAME)((DWORD)DosHeader + IntTable[i]);
                    if (!strcmp(funName, Name->Name)) {
                        return &IatTable[i];
                    }
                }
            }
        }
        ImpTable++;
    }
    return 0;
}

六、总结

  1. 全局钩子注入:通过SetWindowsHookEx实现,需要DLL文件
  2. 远程线程注入:经典方法,通过CreateRemoteThread实现
  3. APC注入:利用线程APC队列,适合DLL注入
  4. 自定义HOOK
    • Inline Hook:直接修改函数代码
    • IAT Hook:修改导入表函数地址

在分析恶意程序时,应特别关注这些敏感API的组合使用,这些技术常被用于实现恶意功能。

Windows进程注入技术详解 一、概述 进程注入是一种常见的技术,用于在目标进程空间中执行自定义代码,通常用于修改目标进程行为或使用目标进程身份执行操作。本文将详细介绍四种常用的Windows进程注入技术。 二、全局钩子注入 1. 原理 Windows应用程序基于消息机制运行,全局钩子可以截获和监视整个系统的消息。全局钩子需要使用DLL文件,在DLL中实现钩子函数。 2. 关键API SetWindowsHookEx() UnhookWindowsHookEx() 钩子回调函数 3. 实现步骤 创建DLL,实现钩子过程函数 使用SetWindowsHookEx安装全局钩子 系统将DLL注入到所有符合条件的进程中 通过UnhookWindowsHookEx卸载钩子 三、远程线程注入 1. 原理 在目标进程中创建线程执行自定义代码,是最经典的注入技术。 2. 关键API OpenProcess() VirtualAllocEx() WriteProcessMemory() CreateRemoteThread() 3. 实现步骤 使用OpenProcess打开目标进程 使用VirtualAllocEx在目标进程中分配内存 使用WriteProcessMemory将Shellcode或DLL路径写入目标进程 使用CreateRemoteThread创建远程线程执行代码 4. 注意事项 对于系统服务(SESSION 0隔离),需使用ZwCreateThreadEx替代CreateRemoteThread 需要确保目标进程内存区域可访问 四、APC队列注入 1. 原理 利用异步过程调用(APC)机制,当线程处于可通知状态时执行APC队列中的函数。 2. 关键API QueueUserAPC() 3. 实现步骤 枚举目标进程的所有线程 向每个线程插入APC(通常指向LoadLibrary) 当线程进入可通知状态时执行APC 4. 特点 成功率与线程状态相关 可向多个线程插入APC增加成功率 常用于DLL注入 五、自定义HOOK技术 1. Inline Hook 原理 通过修改目标函数的前几个字节为JMP指令,跳转到自定义函数。 实现步骤 获取目标函数地址 保存原始字节 修改内存保护属性为可写 计算跳转偏移并写入JMP指令 恢复内存保护属性 示例代码 2. IAT Hook 原理 通过修改导入地址表(IAT)中的函数地址实现Hook。 实现步骤 解析PE文件结构,定位IAT表 查找目标DLL和函数在IAT中的位置 修改IAT中的函数地址为自定义函数地址 关键代码 六、总结 全局钩子注入 :通过SetWindowsHookEx实现,需要DLL文件 远程线程注入 :经典方法,通过CreateRemoteThread实现 APC注入 :利用线程APC队列,适合DLL注入 自定义HOOK : Inline Hook:直接修改函数代码 IAT Hook:修改导入表函数地址 在分析恶意程序时,应特别关注这些敏感API的组合使用,这些技术常被用于实现恶意功能。