发布于昨天 22:091天前 背景最近在一次授权内网排查中,某 Windows 终端出现异常外联:固定间隔访问境外 VPS 的 443 端口,但流量并非正常 TLS。主机侧用户反馈为“偶发卡顿”,EDR 告警只提示可疑 PowerShell 启动链。后续取证发现落地文件具备典型远控木马特征:开机自启动、配置加密、周期心跳、远程命令执行和文件传输能力。本文以这类远控木马的逆向分析流程为主线,重点放在样本拆解、配置提取、行为确认、日志留痕和修复建议。场景限定在授权渗透测试和蓝队排查,不讨论投放和免杀。问题定位初始线索来自代理网关日志,异常主机为 10.10.23.47,外联目标为 185.x.x.x:443,访问周期约 60 秒。终端侧进一步查看进程树,发现异常链路如下:explorer.exe └── powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File C:\Users\Public\update.ps1 └── rundll32.exe C:\ProgramData\Microsoft\Windows\cache\winupdate.dat,Start几个明显异常点:rundll32.exe 加载的文件扩展名为 .dat,但 PE 头有效。路径伪装成 Windows 更新缓存目录,但目录创建时间与用户登录时间接近。父进程为隐藏 PowerShell,符合脚本落地加载 DLL 的远控启动方式。外联间隔稳定,流量包长度规律,疑似心跳包。样本基础信息对落地文件做静态信息确认:certutil -hashfile C:\ProgramData\Microsoft\Windows\cache\winupdate.dat SHA256 sigcheck64.exe -m C:\ProgramData\Microsoft\Windows\cache\winupdate.dat pefile.exe C:\ProgramData\Microsoft\Windows\cache\winupdate.dat关键信息如下:项目结果文件类型PE32+ DLL导出函数Start、ControlService编译时间异常偏早,疑似伪造签名无有效数字签名导入函数WinHttpOpen、WinHttpConnect、CreateProcessW、RegSetValueExW、CryptUnprotectData导入表已经能看出几个方向:网络通信、进程创建、注册表持久化、可能使用 DPAPI 或 CryptoAPI 处理配置。技术分析1. 持久化方式样本运行后会创建 Run 键,值名伪装成系统更新组件:reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v WindowsUpdateCache现场查到的值如下:WindowsUpdateCache REG_SZ rundll32.exe "C:\ProgramData\Microsoft\Windows\cache\winupdate.dat",Start同时,样本还会写入计划任务作为备用持久化:schtasks /query /fo LIST /v | findstr /i "WindowsUpdateCache winupdate.dat rundll32"对应任务 XML 中可见:<Command>rundll32.exe</Command> <Arguments>"C:\ProgramData\Microsoft\Windows\cache\winupdate.dat",Start</Arguments>这种“双持久化”在远控木马里比较常见:Run 键用于用户登录触发,计划任务用于定时拉起,避免单点清理后失效。2. C2 配置提取静态查看字符串时没有直接出现域名或 IP,只能看到少量类似配置标记:cfg_begin kdf_salt http_post user_agent cfg_end用 Ghidra/IDA 跟踪 Start 导出函数,发现配置读取逻辑大致如下:从资源段读取一段二进制数据。使用固定 XOR key 做第一层解码。再对结果做 RC4 解密。解密后是 JSON 格式配置。下面是用于还原配置的简化 Python 脚本,适合在隔离环境中对样本资源数据做离线解析:import json from pathlib import Path # 从资源段中手工导出的加密配置,不直接运行样本 blob = Path("resource_cfg.bin").read_bytes() xor_key = b"WUCACHE" rc4_key = b"2024_update_client" def xor_decode(data, key): return bytes(b ^ key[i % len(key)] for i, b in enumerate(data)) def rc4(data, key): S = list(range(256)) j = 0 out = [] key = list(key) for i in range(256): j = (j + S[i] + key[i % len(key)]) & 0xff S[i], S[j] = S[j], S[i] i = j = 0 for c in data: i = (i + 1) & 0xff j = (j + S[i]) & 0xff S[i], S[j] = S[j], S[i] k = S[(S[i] + S[j]) & 0xff] out.append(c ^ k) return bytes(out) stage1 = xor_decode(blob, xor_key) plain = rc4(stage1, rc4_key) print(plain.decode("utf-8", errors="replace")) cfg = json.loads(plain) print("C2:", cfg.get("host"), cfg.get("port")) print("URI:", cfg.get("uri")) print("Interval:", cfg.get("sleep"))解出的配置示例:{ "host": "185.x.x.x", "port": 443, "uri": "/api/v1/checkin", "sleep": 60, "jitter": 15, "ua": "Mozilla/5.0 Windows NT 10.0; Win64; x64 UpdateClient/7.6", "id": "{machine_guid}-{user_sid}" }这里需要注意:端口 443 不代表一定是 TLS。本例中样本通过 WinHTTP 发起明文 HTTP POST,只是目标端口使用 443,目的是绕过一些只按端口粗略放行的出口策略。3. 通信特征抓包后能看到典型心跳请求,路径固定,User-Agent 有伪装但不完全像正常浏览器:POST /api/v1/checkin HTTP/1.1 Host: 185.x.x.x:443 User-Agent: Mozilla/5.0 Windows NT 10.0; Win64; x64 UpdateClient/7.6 Content-Type: application/octet-stream Content-Length: 96请求体前 4 字节为长度,后续为 RC4 加密数据。解密后结构类似:{"type":"beacon","host":"PC-047","user":"jzhang","priv":"user","pid":4280}从功能分支看,样本支持的远控指令包括:cmd:通过 cmd.exe /c 执行命令并回传输出。ps:启动 PowerShell 执行脚本片段。upload/download:文件上传下载。shellcode:内存加载一段二进制数据。sleep:调整心跳间隔。排查时不要只盯着样本文件本身。远控真正造成影响的部分通常体现在命令执行痕迹、横向连接、凭据访问和异常文件操作上。操作步骤1. 主机侧快速确认优先确认进程、网络、持久化三类信息::: 查看 rundll32 异常加载 wmic process where "name='rundll32.exe'" get ProcessId,ParentProcessId,CommandLine :: 查看当前外联 netstat -ano | findstr ":443" :: 关联 PID tasklist /fi "PID eq 4280" :: 检查 Run 键 reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" :: 检查计划任务 schtasks /query /fo LIST /v | findstr /i "rundll32 winupdate cache update"2. 日志留痕排查如果环境中开启了 Sysmon,可以重点查以下事件:Event ID 1:进程创建,关注 powershell.exe、rundll32.exe、cmd.exe。Event ID 3:网络连接,关注异常目标 IP、非标准 TLS 的 443 流量。Event ID 7:镜像加载,确认 rundll32.exe 加载的非系统路径 DLL。Event ID 11:文件创建,定位落地文件和临时文件。Event ID 13:注册表值修改,定位 Run 键持久化。Windows 原生日志中也可以补充看:Security 4688:进程创建,前提是开启进程命令行审计。PowerShell 4104:脚本块日志,确认隐藏启动脚本内容。TaskScheduler 106/140:计划任务创建和更新。一个常用的 PowerShell 排查命令:Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1,3,11,13} | Where-Object { $_.Message -match 'winupdate.dat|WindowsUpdateCache|185\.|rundll32.exe|update.ps1' } | Select-Object TimeCreated, Id, ProviderName, Message3. 网络侧检测代理、NDR 或防火墙上建议按以下维度检索:同一主机固定周期访问同一外部 IP。443 端口但无 TLS ClientHello。User-Agent 中出现非标准更新客户端标识。POST 请求体长度稳定且内容高熵。Suricata 规则可以先做临时命中,不建议长期只依赖 IP:alert http $HOME_NET any -> $EXTERNAL_NET 443 ( msg:"Possible RAT beacon over fake HTTPS port"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"/api/v1/checkin"; nocase; http.user_agent; content:"UpdateClient/7.6"; nocase; classtype:trojan-activity; sid:900047; rev:1; )4. YARA 辅助识别在样本族没有大规模变种的情况下,可以用导出函数、伪装路径字符串、配置标记和导入函数组合做命中:rule Win_RAT_WinUpdateCache_ConfigMarker { meta: description = "Detect RAT DLL with fake Windows Update cache config markers" author = "community" scope = "authorized incident response" strings: $s1 = "cfg_begin" ascii $s2 = "kdf_salt" ascii $s3 = "UpdateClient/" ascii $s4 = "WindowsUpdateCache" wide ascii $e1 = "Start" ascii $api1 = "WinHttpOpen" ascii $api2 = "CreateProcessW" ascii $api3 = "RegSetValueExW" ascii condition: uint16(0) == 0x5A4D and 5 of ($s*) and 2 of ($api*) and $e1 }YARA 只是辅助,实战中建议结合 EDR 进程链和网络日志确认,避免因为字符串碰撞误报。风险与修复建议1. 隔离与处置顺序先隔离网络,不要直接关机,避免丢失内存和进程现场。保留样本、脚本、计划任务 XML、注册表导出、相关日志。确认是否存在远程命令执行后的二次落地文件。检查同网段是否有相同 C2、相同 User-Agent、相同持久化键值。2. 清理项:: 删除 Run 键 reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v WindowsUpdateCache /f :: 删除计划任务 schtasks /delete /tn "WindowsUpdateCache" /f :: 删除落地文件,清理前建议先取证备份 del /f /a "C:\ProgramData\Microsoft\Windows\cache\winupdate.dat" del /f /a "C:\Users\Public\update.ps1"如果样本曾以管理员权限运行,还要检查服务项、WMI 事件订阅和启动目录:sc query type= service state= all | findstr /i "update cache win" wmic /namespace:\\root\subscription PATH __EventFilter get Name,Query wmic /namespace:\\root\subscription PATH CommandLineEventConsumer get Name,CommandLineTemplate dir "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"3. 加固建议开启 PowerShell Script Block Logging 和 Module Logging,保留 4104 日志。开启 4688 进程命令行审计,至少覆盖服务器和高价值终端。限制普通用户对 C:\ProgramData 下可疑目录的写入和执行。出口策略不要只按端口放行,建议识别真实 TLS 和 HTTP 协议。对 rundll32.exe、regsvr32.exe、mshta.exe 等 LOLBin 建立基线。对无签名 DLL 从用户目录、公共目录、ProgramData 加载的行为做告警。总结远控木马的逆向分析不应只停留在“样本是什么”这一层,更关键的是把配置、通信、持久化、命令执行和日志证据串起来。本文这个样本的核心特征是:DLL 伪装成更新缓存、通过 rundll32 加载、Run 键和计划任务双持久化、443 端口明文 HTTP 心跳、资源段加密保存 C2 配置。实际处置时建议按“进程链确认 → 配置提取 → 网络侧扩线 → 日志回溯 → 清理和加固”的顺序推进。这样既能控制当前主机风险,也能发现同源感染和后续横向移动痕迹。 逆向分析、样本行为与调试流程示意
昨天 22:581天前 这类样本拆解建议把“行为链”和“证据链”分开记录,否则容易只看到启动项和 C2,遗漏前置投递、权限变化以及清理痕迹。 持久化部分,除了常见的 Run/RunOnce、计划任务、服务和启动目录,建议重点核对: 任务是否通过 COM Handler、WMI 永久事件订阅或注册表 IFEO 实现; 服务的 ImagePath、ServiceDll 是否指向临时目录或用户可写目录; 快捷方式的 Target、Arguments 是否带有隐藏参数; 样本是否先落地 loader,再由 loader 解密或释放真正载荷。 Windows 主机上可以先做一轮基线采集: autorunsc64.exe -accepteula -a * -c -h -s -m > autoruns.csv schtasks /query /fo LIST /v > tasks.txt reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Svchost" /s wevtutil qe Microsoft-Windows-TaskScheduler/Operational /f:text /c:50 C2 配置不要只搜明文 URL。实际样本里常见的是“配置头 + 加密 blob + 运行时拼接”,建议同时关注字符串交叉引用、网络 API 调用参数和内存中的解密结果。静态分析时可重点跟 WinHttpConnect、WinHttpOpenRequest、InternetConnectW、WSAConnect 以及 DNS 查询调用;动态分析时记录 DNS、SNI、HTTP Host、URI、请求头、心跳间隔和失败重连策略。 如果怀疑配置是 XOR/AES 解密后使用,可以在解密函数返回点下断点,而不是只在网络发送函数处抓包。例如 x64dbg 中对 WinHttpSendRequest 设置断点,检查调用前的缓冲区;同时对疑似配置缓冲区下硬件访问断点,通常能定位到解密完成的位置。提取后建议记录以下字段: { "campaign_id": "...", "mutex": "...", "c2": [ {"host": "...", "port": 443, "path": "..."} ], "sleep": 30, "jitter": 20, "user_agent": "...", "transport": "http" } 日志留痕方面,最好把时间线和 IOC 对齐,而不是只罗列日志名称。重点看进程创建、网络连接、持久化创建和文件落地之间的先后关系: Security 4688:异常父子进程、脚本解释器启动、带可疑参数的系统工具; Sysmon 1/3/11/12/13/14:进程、网络、文件创建、注册表修改; PowerShell 4103/4104:编码命令、下载执行和反射加载; TaskScheduler 106/140/141:任务创建、更新和删除; DNS Client 3008 或网络设备日志:首次解析、短周期重复解析和异常域名。 例如可以用 PowerShell 快速把样本进程的网络行为串起来: Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-Sysmon/Operational' Id=1,3,11,12,13,14 } | Where-Object { $_.Message -match 'sample\.exe|powershell|rundll32|regsvr32' } | Select-Object TimeCreated, Id, Message 最后建议在报告中明确区分“样本直接行为”和“环境诱发行为”,并保留哈希、样本路径、命令行、父进程、连接时间、解析 IP 及原始日志。这样后续写 YARA、Sigma 或 EDR 检测规则时,能避免把实验环境中的随机路径、测试域名误写成硬编码 IOC。
创建帐户或登录后发表意见