发布于7小时前7小时 背景与场景本文记录一次授权内网排查中的 Windows 远控木马分析流程。终端告警显示某台办公主机周期性连接外部地址 192.0.2.45,进程来源为用户目录下的 updatehelper.exe。该地址属于文档示例网段,文中的文件名、域名和特征均已脱敏。分析目标不是直接运行样本“观察一下”,而是回答四个具体问题:样本如何启动、远控配置存放在哪里、是否存在进程注入或凭据访问、哪些日志可以用于横向排查。样本必须放在断网或 Host-Only 网络的隔离虚拟机中分析,并保留原始文件副本、哈希、采集时间和来源路径。不要在生产终端上直接双击验证。一、证据固定与初步定位先对文件做只读复制并记录基本属性。除 SHA256 外,还应检查数字签名、备用数据流和原始路径。Zone.Identifier 能帮助判断文件是否经浏览器、邮件或压缩包落地。$sample = 'D:\case\updatehelper.exe' Get-FileHash $sample -Algorithm SHA256 Get-AuthenticodeSignature $sample | Format-List Status,StatusMessage,SignerCertificate Get-Item $sample -Stream * Get-Content $sample -Stream Zone.Identifier -ErrorAction SilentlyContinue sigcheck64.exe -accepteula -nobanner -h -i -m $sample diec.exe $sample capa.exe $sample需要重点记录以下异常:签名缺失、签名无效,或签名主体与文件描述明显不一致。编译时间早于 PE 格式版本、晚于文件落地时间,或者时间戳为 0。导入表极少,但包含 VirtualAlloc、VirtualProtect、LoadLibrary、GetProcAddress 等动态解析相关 API。节区名称异常、可写可执行节区同时存在,或某个节区熵值接近 8,提示加壳或加密数据。capa 命中 HTTP 通信、注册表持久化、屏幕捕获、键盘输入监控或进程注入能力。加壳判断不能只依赖熵值。正常安装程序、压缩资源和 .NET 单文件程序同样可能具有高熵节区,应结合入口点、节区权限、导入数量和运行时行为确认。二、静态逆向:定位启动逻辑与远控配置将样本导入 Ghidra、IDA 或 Binary Ninja 后,先确认它是原生 PE 还是 .NET 程序。.NET 样本可优先使用 dnSpyEx 或 ILSpy;原生样本则从入口点向下追踪 CRT 初始化,直到进入实际业务函数。本例在字符串和交叉引用中发现以下线索:互斥体前缀 Global\UpdateHelper-,用于避免重复运行。注册表路径 Software\Microsoft\Windows\CurrentVersion\Run。URI /api/v2/checkin,以及固定的 User-Agent。WinHttpOpen、WinHttpConnect、WinHttpSendRequest、WinHttpReceiveResponse 调用链。配置标记 CFG0,后接四字节长度、单字节密钥和加密内容。追踪 CFG0 的交叉引用后,可以看到解码循环对每个字节执行异或操作,随后将结果交给 JSON 解析函数。以下脚本用于离线提取这种样本特定格式,不执行 PE 文件本身:from pathlib import Path import json import struct path = Path('updatehelper.exe') data = path.read_bytes() marker = b'CFG0' off = data.find(marker) if off < 0: raise SystemExit('CFG0 marker not found') # 布局:CFG0 | uint32_le length | uint8 key | encrypted_data length = struct.unpack_from('<I', data, off + 4)[0] key = data[off + 8] start = off + 9 end = start + length if length > 0x10000 or end > len(data): raise SystemExit('invalid config length') plain = bytes(value ^ key for value in data[start:end]) config = json.loads(plain.decode('utf-8')) # 避免把令牌直接输出到共享终端 for name in ('token', 'campaign_id'): if name in config: config[name] = '[redacted]' print(json.dumps(config, ensure_ascii=False, indent=2))提取结果中通常值得关注的字段包括 C2 主机、端口、URI、休眠间隔、抖动比例、活动时间段、互斥体和安装路径。配置中的域名与 IP 应先作为待验证 IOC,不能仅凭字符串存在就直接封禁,因为未使用的测试地址或旧配置也可能残留在样本中。三、动态分析:确认真实行为动态分析环境建议使用快照虚拟机、Host-Only 网卡、FakeNet-NG 或 INetSim,并确认虚拟机无法访问生产 DNS、代理和共享目录。分析前启动 Procmon、Process Explorer、Sysmon 和网络抓包。# 在隔离分析机中启动网络模拟 fakenet.exe # 采集系统事件,时间范围按实际样本运行窗口调整 $start = (Get-Date).AddMinutes(-20) Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-Sysmon/Operational' Id = 1,3,7,8,10,11,12,13,22 StartTime = $start } | Select-Object TimeCreated,Id,Message | Out-File .\sysmon-timeline.txt # 检查常见用户级持久化位置 reg query 'HKCU\Software\Microsoft\Windows\CurrentVersion\Run' reg query 'HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce' schtasks /query /fo LIST /v > scheduled-tasks.txtSysmon 事件可以按以下关系串联:事件 1:确认父进程、命令行、当前目录、文件哈希和完整性级别。事件 11:观察样本是否复制到 AppData、ProgramData 或临时目录。事件 12、13:确认 Run 键、服务配置或其他注册表持久化。事件 3、22:关联 DNS 查询、目标地址和发起网络连接的进程。事件 7:检查异常 DLL 加载路径,特别是用户可写目录。事件 8、10:排查远程线程创建和跨进程访问。单条事件不足以证明注入,应结合源进程、目标进程、访问权限和调用栈判断。本例运行后先复制自身至 %APPDATA%\UpdateHelper\update.exe,再写入当前用户 Run 键。网络侧每 60 秒发起一次 POST,请求间隔存在约 20% 抖动。FakeNet-NG 返回模拟响应后,样本继续请求任务 URI,说明该地址是实际通信路径而不是未引用字符串。如果样本使用 HTTPS,不建议为了“看明文”而让隔离机访问真实 C2。可以从 SNI、证书、目标地址、报文长度和周期性建立关联;若需要解析协议,应在本地模拟服务端,或在调试器中于加密前的请求缓冲区下断点。四、识别进程注入与权限边界远控木马常把通信或插件代码放入其他进程。逆向时可重点寻找 OpenProcess、VirtualAllocEx、WriteProcessMemory、NtWriteVirtualMemory、CreateRemoteThread、NtCreateThreadEx、QueueUserAPC 等组合,但不要把单个 API 当作确定结论。判断注入是否成功,至少需要同时满足若干证据:源进程对另一进程申请了包含写入或创建线程能力的句柄。目标进程出现无文件映射的可执行内存区域,或私有内存中的 PE 头。目标进程随后发起与其业务不符的外联。线程起始地址不属于已加载模块,调用栈落在匿名内存区域。权限边界也应单独记录。如果样本仅写入 HKCU Run 且保持中完整性,说明它获得的是用户级持久化;若创建服务、写入 HKLM、修改系统目录或访问 LSASS,则通常涉及管理员权限、提权利用或错误配置。修复时不能把“删除 Run 键”等同于完成处置。五、构建样本特定检测规则检测规则应选择多个相对稳定的特征组合,避免只使用文件名、IP 或单个字符串。下面的 YARA 规则基于本例的配置标记、URI 和互斥体,仅适合初步搜索,部署前必须用正常软件样本集测试误报。rule RAT_UpdateHelper_Config_Family { meta: description = "Detects the analyzed UpdateHelper RAT family" scope = "sample-specific" strings: $cfg = "CFG0" ascii $uri = "/api/v2/checkin" ascii $mutex = "Global\\UpdateHelper-" ascii wide $run = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" ascii wide condition: uint16(0) == 0x5A4D and filesize < 5MB and $cfg and 2 of ($uri, $mutex, $run) }主机侧还可以围绕行为建立检测:用户目录中的未签名程序创建 Run 键后,在短时间内周期性外联;办公软件或压缩软件启动后,出现落地 PE、注册表持久化和网络连接的连续事件。这类行为规则通常比固定哈希更能覆盖重编译变种。六、影响范围排查完成单机逆向后,应把静态和动态结果转成可检索条件,在 EDR、Sysmon、DNS、代理、防火墙和身份日志中做范围确认:搜索 SHA256、原始文件名、落地路径、互斥体和注册表值数据。查询相同域名、目标 IP、URI、User-Agent 和固定周期外联。检查样本父进程是否为邮件客户端、浏览器、Office 或脚本解释器。检查受影响账户在样本首次执行后的远程登录、文件共享、计划任务和服务创建记录。如果存在进程注入或凭据访问迹象,扩大到同账号登录过的其他主机,不要只处理告警终端。七、风险处置与修复建议先隔离主机,再采集内存、样本、事件日志、计划任务、服务、网络连接和自启动项。直接删除文件会破坏时间线。在完成取证后移除 Run 键、恶意计划任务、服务和落地文件,并检查同目录下的配置、插件与更新副本。如果确认存在代码注入、凭据读取、内核驱动或无法解释的高权限行为,优先重装或恢复可信镜像,不建议只做手工清理。从干净设备重置受影响账户的密码、会话令牌和相关密钥。仅修改本机密码不能使已签发的云端会话失效。在出口策略中限制普通终端直接访问公网,统一经过可审计代理,并启用 DNS、进程创建、网络连接和 PowerShell 日志。修复完成后复核原持久化位置、异常外联、内存注入迹象和账号登录记录,至少覆盖一个完整的原始回连周期。总结远控木马逆向分析的价值不只是得到一个 C2 地址,而是把样本内部逻辑、终端行为和现有日志连接起来。静态分析用于定位配置和关键函数,隔离动态分析用于验证真实执行路径,Sysmon、EDR 与网络日志用于确认影响范围。最终处置应围绕权限边界和证据闭环展开,避免仅删除样本后就判断事件结束。 逆向分析、样本行为与调试流程示意 服务器、云资产与权限边界梳理示意
6小时前6小时 这类样本建议把“持久化、配置、通信、日志”按时间线串起来分析,单独看某个注册表键很容易误判。尤其要注意:有些远控木马首次运行只创建计划任务或服务,后续进程才解密 C2 配置。 我一般会先做一份基线,再启动样本: reg.exe export HKCU\Software\Microsoft\Windows\CurrentVersion\Run before.reg schtasks /query /fo LIST /v > tasks-before.txt sc.exe query type= service state= all > services-before.txt wmic startup get Caption,Command,Location,User > startup-before.txt 样本运行后再次执行并对比,重点看任务的 Actions、Triggers 和服务的 ImagePath,不要只看名称。若命令行包含 rundll32、regsvr32、mshta 或临时目录路径,建议沿着实际加载模块继续跟踪。 配置提取方面,比直接在字符串窗口搜索域名更可靠的是在网络 API 入口截获明文参数。x64 下可以在 WinHttpConnect、WinHttpOpenRequest、InternetConnectW、WSAConnect 处下断点;如果使用自定义加密,则在加密函数返回后、发送函数调用前检查缓冲区。动态调试时记录以下字段即可形成可复现样本: 时间 进程 PID / 线程 ID 目标地址与端口 解密后配置缓冲区地址和长度 发送前数据摘要(SHA-256) 持久化写入的路径或注册表键 日志闭环建议同时采集进程创建、文件落地、注册表修改和网络连接,单靠样本自身日志可能被清理。Windows 侧可以先用 Sysmon 关注 Event ID 1、3、11、12/13、19-21,再把 PID 和时间戳对齐;如果发现网络连接早于配置落地,通常说明配置来自资源段、环境变量或二阶段下载,而不是本地配置文件。 另外,分析持久化时最好验证重启后的实际触发链:入口程序 → 解密/解包 → 子进程 → 网络模块。很多样本创建的任务只是启动器,真正的 C2 配置和通信代码在子进程中,若只对首个进程下断点,容易漏掉关键行为。
创建帐户或登录后发表意见