代码注入之CreateProcess注入
字数 1895 2025-08-29 22:41:01
CreateProcess代码注入技术详解
一、概述
CreateProcess注入是一种通过主动创建目标进程来实现代码植入的技术,其主要优势在于注入时机较早,能够在目标进程的防护和检测机制启动前完成注入。这种技术在游戏外挂和红队渗透测试中有广泛应用。
二、核心环节
CreateProcess注入可分为三个关键环节:
- 创建挂起进程:使用
CREATE_SUSPENDED标志创建目标进程 - 注入代码并构造执行时机:在挂起进程内存中写入shellcode并设置执行方式
- 恢复进程执行:使目标进程恢复执行,触发shellcode
三、具体实现框架
基本实现框架如下:
-
创建挂起进程:
CreateProcess(NULL, "target.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); -
分配内存:
VirtualAllocEx(pi.hProcess, NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); -
写入shellcode:
WriteProcessMemory(pi.hProcess, allocatedMem, shellcode, shellcodeSize, NULL); -
构建执行时机(具体方法见下文)
-
恢复主线程:
ResumeThread(pi.hThread);
四、执行时机构建方法
4.1 创建远线程注入
原理:虽然主线程被挂起,但仍可创建新线程执行shellcode。
实现步骤:
- 将DLL路径写入目标进程内存
- 以
LoadLibraryA为线程函数创建远线程 - 线程参数设为DLL路径地址
代码示例:
CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, dllPathAddr, 0, NULL);
4.2 APC注入(Early Bird注入)
原理:利用APC(异步过程调用)机制,在主线程恢复时执行shellcode。
关键点:
- 线程初始化时会检查APC队列
- 如果APC队列不为空,会执行APC函数
LoadLibraryA参数与APC函数兼容(__stdcall调用约定)
实现步骤:
- 将DLL路径写入目标进程内存
- 使用
QueueUserAPC将LoadLibraryA加入主线程APC队列
代码示例:
QueueUserAPC((PAPCFUNC)LoadLibraryA, pi.hThread, (ULONG_PTR)dllPathAddr);
4.3 Hook IP寄存器注入
原理:修改主线程的指令指针(IP)寄存器指向shellcode。
关键点:
- 挂起状态下,IP指向
RtlUserThreadStart - 修改CONTEXT结构中的EIP寄存器值
- shellcode执行后需跳回原EIP
实现步骤:
- 获取线程上下文
- 修改EIP指向shellcode
- 设置上下文
代码示例:
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &context);
context.Eip = (DWORD)shellcodeAddr;
SetThreadContext(pi.hThread, &context);
4.4 Hook入口点注入
原理:修改目标进程exe模块的入口点指向shellcode。
实现方法:
方法一:直接修改PE头入口点
- 通过PEB获取exe模块基址
- 解析PE头找到入口点地址
- 修改入口点(实际测试发现可能无效)
方法二:Hook EAX寄存器
- 挂起状态下,EAX寄存器保存了exe入口点地址
- 修改CONTEXT中的EAX值指向shellcode
代码示例:
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &context);
context.Eax = (DWORD)shellcodeAddr;
SetThreadContext(pi.hThread, &context);
五、检测与对抗方案
5.1 基于注入结果的检测
方法:
- 扫描进程中的可疑模块或shellcode
- 使用特征码或签名进行恶意判定
对抗:
- 更新特征码
- 隐藏模块/shellcode
5.2 基于注入条件的防御
双进程保护:
- 第一进程启动后创建第二进程
- 第一进程退出,第二进程执行实际功能
- 第一进程在创建第二进程前启动防护驱动
对抗:
- CreateProcess连环注:Hook第一进程的CreateProcess函数
5.3 基于注入时机的检测
检测方法:
-
远线程注入检测:
- 在DllMain中记录初始线程ID
- 比较执行到exe入口时的线程ID
-
APC注入检测:
- Hook
KiUserApcDispatcher - 检查exe入口前是否有APC执行
- Hook
-
Hook入口点检测:
- 对比入口点指令与文件原始指令
- 检查EAX寄存器是否指向预期入口点
-
Hook主线程IP检测:
- Hook
RtlUserThreadStart - 检查栈上是否有保存的寄存器痕迹(pushad/popad)
- Hook
六、技术要点总结
-
时机优势:CreateProcess注入的最大优势在于能够在目标进程防护机制启动前完成注入
-
方法选择:
- 远线程注入:实现简单,但容易被检测
- APC注入:隐蔽性较好,依赖线程状态
- Hook寄存器:无需修改代码,隐蔽性高
- Hook入口点:实现复杂,可能被防护机制拦截
-
对抗演进:注入与检测技术是持续对抗的过程,需要根据目标环境选择合适方法
-
注意事项:
- shellcode执行后需正确恢复原执行流程
- 需要考虑内存权限设置(PAGE_EXECUTE_READWRITE)
- 注入操作可能触发杀软行为检测
七、参考实现建议
实际实现时应注意:
- 错误处理:检查每个API调用的返回值
- 权限提升:可能需要调整进程权限
- 兼容性:考虑不同Windows版本的行为差异
- 隐蔽性:结合其他技术如API调用混淆
通过深入理解这些技术原理和对抗方法,可以更有效地应用或防御CreateProcess注入技术。