恶意代码分析系列-几种常用技术(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. 实现步骤
- 创建DLL,实现钩子过程函数
- 使用SetWindowsHookEx安装全局钩子
- 系统将DLL注入到所有符合条件的进程中
- 通过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. 实现步骤
- 使用OpenProcess打开目标进程
- 使用VirtualAllocEx在目标进程中分配内存
- 使用WriteProcessMemory将Shellcode或DLL路径写入目标进程
- 使用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. 实现步骤
- 枚举目标进程的所有线程
- 向每个线程插入APC(通常指向LoadLibrary)
- 当线程进入可通知状态时执行APC
4. 特点
- 成功率与线程状态相关
- 可向多个线程插入APC增加成功率
- 常用于DLL注入
五、自定义HOOK技术
1. Inline Hook
原理
通过修改目标函数的前几个字节为JMP指令,跳转到自定义函数。
实现步骤
- 获取目标函数地址
- 保存原始字节
- 修改内存保护属性为可写
- 计算跳转偏移并写入JMP指令
- 恢复内存保护属性
示例代码
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。
实现步骤
- 解析PE文件结构,定位IAT表
- 查找目标DLL和函数在IAT中的位置
- 修改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;
}
六、总结
- 全局钩子注入:通过SetWindowsHookEx实现,需要DLL文件
- 远程线程注入:经典方法,通过CreateRemoteThread实现
- APC注入:利用线程APC队列,适合DLL注入
- 自定义HOOK:
- Inline Hook:直接修改函数代码
- IAT Hook:修改导入表函数地址
在分析恶意程序时,应特别关注这些敏感API的组合使用,这些技术常被用于实现恶意功能。