收到标题后,我顺着“远程木马”和“傀儡进程”这两个核心关键词,把整个技术链路和排查思路重新梳理了一遍。这篇文章没有停留在某一个样本的IOC(入侵指标)罗列上,而是从“远程木马为什么偏爱傀儡进程”这个根本问题出发,完整拆解了进程镂空(Process Hollowing)的底层实现、实弹分析流程、以及攻防演练中从告警到还原的完整排查链路。内容偏向蓝队视角的恶意代码分析,也兼顾了刚入门样本分析方向的新手。
1. 远程木马为什么偏爱“傀儡进程”这套玩法
先说结论:远程木马选择傀儡进程技术,本质上是在解决“生存”问题。杀毒软件和EDR(终端检测与响应)产品盯得最紧的,是那些直接由恶意加载器启动的进程。只要一个新出现的进程带有可疑命令行参数、无签名、路径又在临时目录下,挂掉的概率极高。而傀儡进程的思路完全不同——它不创建新的恶意进程,而是把一段恶意代码塞进一个正常的、甚至是受信任的系统进程体内,让它“借壳运行”。
我这里说的“傀儡进程”,指的安全社区最常见的进程镂空技术。攻击者先用CreateProcessA拉起一个正常的进程,比如svchost.exe或RuntimeBroker.exe,映像处于挂起状态,进程主线程不会执行。接下来把这块合法映像从内存中卸载掉,把木马自身的PE文件或Shellcode写入这个进程的内存空间,修改线程上下文,最后恢复线程。从任务管理器和大多数进程监控工具的角度看,系统里确实多了一个正常的svchost.exe进程,但实际上它跑的是攻击者的代码。
远程木马尤其青睐这种手法,还有一个现实原因:网络侧的行为更难被关联。木马的控制端流量可以隐藏在HTTPS或DNS隧道里,流量分析设备只能看到“某台主机上的svchost.exe在访问外部IP”,这种流量在庞大的企业内网里非常不起眼。而如果是powershell.exe或rundll32.exe直接外联,告警规则很容易命中。傀儡进程相当于把网络行为的“噪声底”直接抬高了一截。
从防御和检测的角度看,理解傀儡进程的意义不只是为了看懂某一个恶意样本,而是为了理解一套完整的对抗逻辑。远程木马的作者在选型时,一定会把“能否规避静态查杀”和“能否规避行为检测”放在首位,傀儡进程技术在这两项上都占据明显优势。这也是为什么从2017年前后开始,各种商业远控和开源木马框架都把进程镂空作为标配能力。
2. 傀儡进程的底层实现:从CreateProcess到ResumeThread的完整链路
想要真正分析傀儡进程,第一步必须把它的完整API调用链背下来。这条链路不复杂,核心就五个环节,但每一个环节都有一些容易被忽视的技术细节。
// 经典傀儡进程实现的核心步骤 // Step 1: 以挂起方式创建宿主进程 BOOL bSuccess = CreateProcessA(szHostProcess, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); // Step 2: 读取目标进程的基址(通过NtQueryInformationProcess查PEB) // Step 3: 卸载宿主进程的原始映像(NtUnmapViewOfSection) // Step 4: 在宿主进程内分配内存并写入恶意PE映像 // Step 5: 修改宿主进程入口点(SetThreadContext) // Step 6: 恢复主线程(ResumeThread),恶意代码开始执行2.1 关键点一:为什么使用CREATE_SUSPENDED挂起标志
CREATE_SUSPENDED标志让新进程的主线程暂停执行。此时系统已完成PE映像映射、DLL加载、PEB初始化等操作,但进程的主线程还没有跑起来。攻击者选择在这个时间窗口动手,是因为所有必要的进程初始化已完成,直接改内存和线程上下文不会导致宿主进程崩溃。
从分析角度讲,这个标志本身就是一个很好的行为检测点。当一个常见进程以CREATE_SUSPENDED方式被创建,随后短时间内又有跨进程写入和线程上下文修改行为,行为序列的“可疑程度”非常高。
2.2 关键点二:卸载映像与重新分配内存的“身份落差”
第二步和第三步是傀儡进程最核心的两个操作。NtUnmapViewOfSection卸载的是宿主进程的原始映像,这会让宿主进程的基址(通常为0x140000000)变为空闲状态。随后木马通过VirtualAllocEx从宿主进程内存空间申请一块新区域,写入恶意PE。攻击者通常会选择在同样的基址处重新分配内存,这样恶意PE的基址重定位逻辑能直接命中原本的ImageBase,省去了处理重定位表的麻烦。
Windows内核和Ring3之间在这里存在一个信息差:从Windows任务管理器看,这个进程的路径和名称仍然是原来的,但它的内存内容已经被偷换。这个特征会体现在修改后的内存映像与磁盘映像不一致,这也是EDR和内存扫描工具的重要检测依据。
2.3 关键点三:SetThreadContext把执行流指向恶意入口点
SetThreadContext操作针对的是宿主进程主线程CONTEXT结构中的RIP/EIP寄存器。这一步要把执行流指向恶意PE的入口点。这里有个容易迷惑人的地方:不只是入口点需要改,宿主进程原始映像的主线程栈上还残留着很多DLL加载器相关的状态。如果攻击者只是简单改RIP,有些恶意代码会崩溃,所以他们往往会同时修改线程栈或利用APC注入等技术先把执行流带到一段Shellcode,再由Shellcode完成更精细的初始化。
分析时可以借助调试器观察Thread环境块(TEB)和线程栈的变化。恶意代码接管执行流后,栈上的返回地址链往往是断的、非法的,这也是人肉判断“这个进程已被熔铸成傀儡”的静态信号之一。
2.4 为什么这项技术能绕过一部分防御
很多杀软对跨进程操作的检测集中在WriteProcessMemory和CreateRemoteThread上。CreateRemoteThread是一个极其高调的信号,几乎所有安全产品都会拦截,而傀儡进程的巧妙之处在于它根本不用CreateRemoteThread,它使用的是SetThreadContext+ResumeThread。这两个API本身是合法的线程管理API,并不是危险函数。
这种“合法API组合完成恶意行为”的模式,是大量高级攻击能绕过传统杀软的原因。这也决定了防守方不能只看单个API,要看整条API调用链的组合特征和进程间的访问关系。
3. 拿到样本后的初判:静态分析阶段的高效路径
真正开始分析一个远程木马样本时,不要急着上调试器。我的习惯是先用最快的路径完成粗判——这个样本是否套壳、用什么语言写的、导入表有什么异常、有没有明显的混淆特征。五到十分钟基本可以建立初步判断,再决定后续投入多少精力。
3.1 不加壳的快速定位技巧
拿到一个未加壳的PE文件时,直接看导入表基本能锁定方向。远程木马调用傀儡进程技术,导入表里典型API非常醒目:CreateProcessA、VirtualAllocEx、WriteProcessMemory、SetThreadContext、ResumeThread,以及NtUnmapViewOfSection这类NTDLL导出。 如果一个文件同时导入这些API,基本可以判定它包含进程镂空能力。尤其NtUnmapViewOfSection这个API在正常业务代码中几乎不会出现。
建议用DIE(Detect It Easy)先看编译器和加壳信息,再用PE-bear看导入表。这里分享一个实操技巧:很多远程木马会把傀儡进程的这部分实现封装在独立函数中,通过导入表找到调用点之后,在反汇编代码里向上追溯,很容易看到字符串资源——比如宿主进程的路径。有的样本会用GetSystemDirectoryA动态拼接C:\Windows\System32\svchost.exe,这样字符串表里就没有明文路径,可以绕过一些简单的字符串匹配规则。
3.2 字符串与资源节的分析要点
远程木马的C2地址和密钥往往藏在字符串和资源节里。早期很多样本直接用明文IP或域名作为C2,但现在大多数会用Base64加密或通过简单异或隐藏起来。分析字符串时,建议重点关注这些特征:
- 与系统常用路径相似的字符串,但存在细微差别(如system32和System32混用)
- 出现“config”“key”“pass”等配置文件相关字段
- 密钥初始化向量或轮换时间戳,这类数据往往暗示流量是加密的
如果样本是带数字签名的,还需要关注签名证书的信息。虽然很多恶意样本用的是盗来的证书或自签名证书,但数字签名的详细信息可以用于建立威胁情报关联。我经常通过证书的序列号和主体信息去关联同一攻击者使用的其他样本,这个思路在应急响应里非常有效。
3.3 静态分析时容易被忽视的四个细节
3.3.1 重定位表是否被处理过
有些木马为了减少内存写入的痕迹,会把恶意PE的ImageBase改成和宿主进程一致,这样VirtualAllocEx分配内存后不需要处理重定位表。如果看到样本ImageBase是0x140000000或0x400000,且加载配置表里ImageBase偏高,可以作为“它准备嵌入其他进程”的辅助判断依据。
3.3.2 节表权限异常
正常的可执行文件,代码节一般是可读可执行,数据节是可读可写。恶意样本常见的做法是把代码节设置成RWX或者把数据节设置成可执行。使用CFF Explorer查看节表时,如果发现.text或.rdata节带可写权限、.data节带可执行权限,强烈提示这些数据会在运行时作为代码使用。
3.3.3 入口点是否偏向代码段中段
正常编译的PE入口点往往在节开头偏移处,恶意样本通过入口点混淆或反调试时,入口点可能落在代码段深处。这里提醒一点:运行时通过修改OEP(原始入口点)的样本也很多,静态看到的入口点不一定是真实入口。
3.3.4 导入表里存在敏感字符串或特定DLL
远程木马往往会加载Advapi32.dll、Netapi32.dll做权限持久化,或加载Wininet.dll、Ws2_32.dll做网络通信。导入这些DLL本身不算异常,但如果导入表中同时出现WSAStartup和CreateProcessA、WriteProcessMemory,组合的可疑程度就上了一个台阶。
4. 动态分析阶段:用调试器和监控工具拆穿傀儡外衣
静态分析确认目标具备进程镂空能力之后,就到了动态分析阶段。这一步的目标是拿到完整的“进程创建→内存写入→线程恢复→网络外联”证据链,形成可复现的检测规则。
4.1 分析环境的构建要点
动态分析傀儡进程,建议使用Windows 10或Windows Server虚拟机,配置至少2核4GB内存。关键是要安装完整的调试工具集:x64dbg、Process Monitor、Process Explorer、Wireshark,以及一个API监控工具。对样本分析来说,API Monitor这类工具尤其重要,它可以直接记录CreateProcessA、WriteProcessMemory、SetThreadContext等调用的详细参数。
需要注意,远程木马往往带有反虚拟机检测逻辑,常见的手法包括检测CPU指令特征、检测虚拟机设备名、检测调试器是否存在。遇到这种情况,要么先修改样本绕过反调试,要么用更隐蔽的分析环境。实操中最简单的规避方式是使用在物理机裸机环境加硬件断点,或者配合内核调试器双机调试。
4.2 用Process Monitor观测进程树与文件操作
Process Monitor可以按进程名过滤,观察目标进程创建子进程的事件。傀儡进程技术最大的特征就是“宿主进程被创建后,紧接着出现了大量跨进程内存操作”。Process Monitor虽然没有直接显示NtUnmapViewOfSection的图形化字段,但Operation列会显示WriteProcessMemory等关键操作。
同时观察宿主进程的命令行和父进程关系,如果父子进程关系异常(比如一个文档进程启动了一个svchost.exe),结合进程目录路径,攻击链就清晰了。
4.3 x64dbg下的中断思路:在SetThreadContext处下断
我喜欢用x64dbg直接下断在SetThreadContext上,这样能拿到完整的上下文信息。当断点命中时,调试器会显示CONTEXT结构里的RIP值,这个值指向的就是恶意PE的入口。直接在内存窗口中跳转到这个地址,大概率能看到MZ头和PE头。
模块窗口在ResumeThread之前会显示多个可疑模块加载;如果宿主进程原本是svchost.exe,ResumeThread后模块列表会新增一个没有文件路径的模块,或模块名显示为内存映射。这个“无文件模块”特征很关键,它是进程镂空后的内存PE典型表现。
在x64dbg里,有一个常用套路是:
- 在CreateProcessW和ResumeThread上下断,确保能暂停在第一个线程恢复前。
- 执行到ResumeThread前,用“内存布局”视图检查宿主进程内存映像。
- 如果发现0x400000或0x140000000基址处内容与磁盘文件明显不一致(大小、节区数量都不对),基本等于确认了傀儡进程。
4.4 网络行为捕获的时机把握
恶意代码通常在ResumeThread后几分钟内就会尝试连接C2。分析机的Wireshark需要提前开启抓包,并设置好过滤器只保留HTTP、DNS、TLS流量。DNS请求可能会收到一个少见域名的解析结果,那就是C2域名的最直接证据。
有些远程木马的C2通信采用HTTPS,证书是随机生成的自签名证书。 这种细节可以让流量特征在检测规则中发挥作用——内网环境中,一个系统进程访问自签名外部地址,是高风险事件。
5. 攻防演练中的真实复盘:从告警到事件链条还原
只讲技术本身还不够。远程木马的傀儡进程技术,最终检验它是“真实威胁”还是“理论概念”的,是实战环境中的告警响应完整过程。下面用一个虚构但完全来自实操经验的案例来串联全过程。
5.1 告警信号的起点:一个不合理的svchost.exe
某金融机构内网的一次攻防演练中,流量监控平台发出告警:一台办公终端上的svchost.exe持续向位于境外的IP发送加密数据,间隔约30秒一次。从名字看,svchost.exe是Windows系统核心进程,出现外联不算特别异常,但流量监控平台依据“终端的svchost.exe在过去7天内未出现外联行为”这一基线偏差,发出了中级告警。
安全工程师登录终端后,用Process Explorer查看这个svchost.exe的详细信息,发现了两个反常:路径显示为C:\Windows\System32\svchost.exe,但“验证签名”状态是“无法验证”;进程的启动时间与系统开机时间不一致。随后查看该进程的内存字符串,发现了多个疑似C2地址的IP。
5.2 顺着进程树逆向追踪:谁是放毒者
沿着进程树向上回溯,发现这个svchost.exe的父进程是一个文档阅读器进程,该进程的打开时间是当天早上。进一步检查文件系统的下载记录,发现用户曾打开一个携带恶意宏的文档。宏释放了一个可执行文件到%AppData%目录,再通过WMI远程调用启动傀儡进程。
这一步是整个排查的关键转折点。很多分析人员看到“svchost.exe外联”时,容易直接判定为系统服务被入侵,忽略了傀儡进程的“宿主”属性。实际上svchost.exe只是被利用的空壳,真正的恶意载荷是从文档宏脚本中释放出来的。
5.3 内存取证还原恶意代码真实行为
在确认傀儡进程后,安全团队对主机进行了内存镜像采集,并使用开源内存取证工具分析了svchost.exe进程的内存区域。取证结果显示,宿主进程的原始内存映像已被替换,内存中存在的PE文件与磁盘上任何已知系统文件都不匹配。对恶意PE进行静态提取后,发现其内部实现了键盘记录、屏幕截图、剪贴板窃取和自删除功能,并具备多级C2地址。
这个案例最有价值的教训是:不要被“父子进程关系”迷惑。正常业务的父子进程关系往往稳定,而傀儡进程领域,父子关系只是表象,内存内容的真实性才是判断关键。
5.4 复盘:如果当时检测配置更完善
事后复盘时,安全团队检查了EDR的进程监控策略,发现了几个可优化的点:
- 未开启映像加载回调(Image Load Callback)监控,导致进程模块加载无告警
- 未对跨进程写入单独设置高敏感告警
- 对系统进程外联行为缺乏动态基线学习
这个复盘思路值得每个防守团队参考。傀儡进程攻击的检测,从网络侧看是系统进程外联,从主机侧看是内存映像异常和API行为序列异常。两者结合,才有机会在攻击真正造成数据泄露前拦截住。
6. 检测与防护手段:把对抗经验固化成规则
分析完原理、走完排查流程,最后要落地的是防御侧的检测规则和防护思路。以下是一些经过实践检验的检测与加固方案。
6.1 基于API调用链的行为检测规则
傀儡进程技术的核心是API调用序列,因此行为检测规则应该围绕这个序列建立。以Sysmon为例,可以配置同时监控以下事件:
- 进程创建事件(Event ID 1):关注父进程与子进程的路径是否异常,如文档阅读器进程启动svchost.exe
- 进程访问事件(Event ID 10):关注进程打开其他进程句柄时是否请求了PROCESS_ALL_ACCESS,且目标进程是系统进程
- 映像加载事件(Event ID 7):关注系统进程中是否加载了异常模块
规则建议这样设计:CreateProcessA(CREATE_SUSPENDED标志)→ NtUnmapViewOfSection → VirtualAllocEx → WriteProcessMemory → SetThreadContext → ResumeThread的组合在30秒内出现,直接判定为高危。 市场上成熟的EDR产品大多内置了类似规则,但自建规则可以覆盖更多个性化的场景。
6.2 内存扫描与凭据保护的边界
傀儡进程的内存映像与磁盘文件不一致,这是内存扫描的天然检测点。 常见的内存扫描工具会对关键进程(svchost.exe、lsass.exe、explorer.exe)做周期性扫描,比较内存中的PE头、节区大小和磁盘映像的差异。
同时建议启用Credential Guard和受保护进程轻量级(PPL)机制。PPL机制能防止恶意代码打开lsass.exe进程句柄,这对键盘记录和凭据窃取类木马有直接抑制作用。但需要注意,PPL不能阻止傀儡进程攻击本身,它只是提高攻击门槛。
6.3 终端加固优先级清单
- 启用应用程序控制,默认禁止从用户目录启动程序
- 对Office宏执行策略做白名单管理
- 配置Windows Defende的受控文件夹访问,保护%AppData%目录
- 配置防火墙出站规则,系统进程默认禁止访问非标准端口
- 对域内终端强制实施LAPS本地管理员密码管理
从实际效果来看,第1条和第4条的防御价值最大。很多远程木马依赖本地文件释放,应用程序控制直接卡住释放文件这个环节,木马根本没有机会进入进程镂空阶段。出站规则对C2通信有抑制作用,即使木马运行成功,外联行为也会触发网络侧告警。
6.4 长期对抗需要的三件事
傀儡进程技术的对抗,不是一次性投入就能持续见效的,需要三件事建立长效机制:
- 定期复盘EDR告警,把漏报和误报案例沉淀成规则优化依据
- 建立内部威胁情报库,记录攻击者的TTP(战术、技术和流程),而不只是IOC
- 每隔一段时间做一次红蓝对抗验证,确认检测规则没有被绕过
我个人在实战中感受到,最容易被忽视的是第三点。规则在部署时是有效的,但随着攻击者技术迭代,规则可能逐步失效。定期用最新的攻击工具和手法去检验检测体系的时效性,投入产出比极高。
7. 写在最后的一点建议
分析傀儡进程技术越深入,我越觉得防御的核心不是“识别恶意文件”,而是“识别恶意行为”。互联网上可以很容易找到成千上万个恶意样本,同一个样本的哈希可能几天就更换一次,但进程镂空这个技术行为在几年内都不会消失。无论是做检测规则还是做应急响应,把注意力集中在“行为序列”而不是“单一签名”上,胜率会高很多。
如果你想系统练习傀儡进程分析,建议在受控环境里自己动手写一个最小的进程镂空Demo,然后再去分析真实样本。自己写过一遍之后,对API调用链和内存布局的理解会完全不同。这个领域没有捷径,多写多调,才能形成手感和直觉。