跳转到帖子

一次授权内网排查中远控样本的配置提取与留痕定位

精选回复

发布于

背景

最近在一次授权内网渗透复盘中,甲方 EDR 对一台办公网终端报出异常外联:进程名为 svchost.exe,但路径位于用户目录下的 %APPDATA%\Microsoft\Windows\,并且周期性访问一个非常规端口。该主机此前被用于邮件附件验证,怀疑存在远控木马落地。

这类样本不适合只看进程名和端口下结论,重点是确认三件事:样本是否具备远控行为、C2 配置如何保存、主机侧有哪些持久化和横向痕迹。下面记录一次比较完整的分析流程,偏向逆向木马远控板块的实战排查,不展开泛泛科普。

问题定位

现场拿到的信息如下:

  • 异常进程:C:\Users\user\AppData\Roaming\Microsoft\Windows\svchost.exe
  • 父进程:explorer.exe
  • 外联地址:185.x.x.x:443,SNI 为空,TLS 指纹异常
  • 落地时间:与用户打开压缩包附件时间接近
  • 启动项:注册表 Run 项存在可疑值

第一步不是直接删除,而是做证据保全:样本、内存、网络连接、注册表持久化、计划任务、日志都要留一份,避免后续无法还原攻击链。

技术分析

样本为 64 位 PE,未加壳但做了字符串轻度混淆。导入表中能看到以下 API 组合,基本符合远控木马常见行为:

  • WinHttpOpen、WinHttpConnect、WinHttpSendRequest:用于 C2 通信
  • RegSetValueExW:写入启动项
  • CreateToolhelp32Snapshot、Process32FirstW、Process32NextW:枚举进程
  • GetAsyncKeyState:疑似键盘记录能力
  • CreateProcessW、ReadFile、WriteFile:命令执行与结果回传

在 x64dbg 中跟到网络初始化逻辑,发现 C2 配置并非明文保存,而是以异或后的字节数组存在 .rdata 区。解密函数特征比较明显:循环读取数组,每个字节与固定 key 做异或,直到遇到 0x00。

伪代码逻辑:

for (i = 0; enc[i] != 0; i++) {
    dec[i] = enc[i] ^ 0x37;
}
dec[i] = 0;

解密后得到:
/api/checkin
185.x.x.x
443
Windows Update Service

这里需要注意:很多远控样本会把真实 C2、URI、互斥体、服务名、注册表项统一放在配置块里。配置提取比单纯查字符串更可靠,尤其是在样本做了字符串加密或分段拼接的情况下。

操作步骤

建议按以下顺序处理,避免漏掉关键证据。

1. 主机侧快速留痕

rem 查看异常进程及命令行
wmic process where "name='svchost.exe'" get ProcessId,ParentProcessId,ExecutablePath,CommandLine

rem 查看网络连接与 PID 对应关系
netstat -ano | findstr ESTABLISHED

rem 查询当前用户 Run 项
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"

rem 查询全局 Run 项
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"

rem 导出可疑 Run 项所在注册表
reg export "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" run_hkcu.reg

rem 查看计划任务中最近创建的任务
schtasks /query /fo LIST /v | findstr /i "TaskName Task To Run Author"

如果条件允许,优先拉取完整内存或至少对可疑进程做 dump。因为部分远控会只在内存中解密 C2 或二阶段模块,磁盘样本不一定包含完整信息。

2. 样本静态检查

  • 使用 Detect It Easy 或 pefile 判断壳和编译信息。
  • 检查节区熵值,重点关注异常高熵节区和可写可执行节区。
  • 查看导入表中网络、注册表、进程、服务、键盘相关 API。
  • 提取 .rdata、.data 中的可疑字节数组。
python 简单提取 PE 节区信息:

import pefile

pe = pefile.PE("svchost.exe")
for s in pe.sections:
    name = s.Name.rstrip(b"\x00").decode(errors="ignore")
    print(name, hex(s.VirtualAddress), hex(s.Misc_VirtualSize), "entropy=", round(s.get_entropy(), 2))

print("Imports:")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
    dll = entry.dll.decode(errors="ignore")
    for imp in entry.imports:
        if imp.name:
            name = imp.name.decode(errors="ignore")
            if name in ["WinHttpOpen", "WinHttpConnect", "RegSetValueExW", "CreateProcessW", "GetAsyncKeyState"]:
                print(dll, name)

3. 配置解密定位

如果字符串窗口只能看到零散乱码,可以在调试器里从以下位置切入:

  • 对 WinHttpConnect、WinHttpOpenRequest 下断点,观察传入的 host、URI。
  • 对 RegSetValueExW 下断点,观察写入的启动项路径和值名。
  • 对 CreateMutexW 下断点,记录互斥体名称,后续可用于批量排查。
  • 对 Sleep 下断点或修改返回,缩短心跳等待时间。
x64dbg 常用断点:

bp winhttp.WinHttpConnect
bp winhttp.WinHttpOpenRequest
bp advapi32.RegSetValueExW
bp kernel32.CreateMutexW
bp kernel32.CreateProcessW
bp kernel32.Sleep

本次样本在调用 WinHttpConnect 前,RCX 指向会话句柄,RDX 指向解密后的 C2 域名或 IP,R8 为端口。命中断点后查看 RDX 指向的 Unicode 字符串即可拿到真实配置。

4. 行为验证

在隔离环境中运行样本,使用 FakeNet-NG 或 INetSim 承接网络请求。样本启动后会先创建互斥体,随后写入 Run 项,再发起心跳包。

行为观察结果风险判断
互斥体Global\WinUpdSvc_2024避免重复运行,可作为排查 IOC
持久化HKCU\...\Run\Windows Update Service用户登录后自启动
外联POST /api/checkin远控心跳与任务拉取
命令执行调用 CreateProcessW 启动 cmd.exe /c具备远程命令执行能力

日志留痕排查

Windows 侧建议重点查以下日志:

  • Security 4688:进程创建,关注异常路径下的 svchost.exe、cmd.exe /c、powershell.exe。
  • Sysmon Event ID 1:进程创建,能看到哈希、父子进程关系。
  • Sysmon Event ID 3:网络连接,定位 C2 IP、端口、进程路径。
  • Sysmon Event ID 11:文件创建,定位落地路径。
  • Sysmon Event ID 13:注册表值修改,定位 Run 项持久化。
PowerShell 查询可疑 Run 项和异常进程:

Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" |
  Format-List

Get-CimInstance Win32_Process |
  Where-Object { $_.ExecutablePath -like "*AppData*" -and $_.Name -eq "svchost.exe" } |
  Select-Object ProcessId, ParentProcessId, ExecutablePath, CommandLine

Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=3} |
  Where-Object { $_.Message -match '185\.' } |
  Select-Object TimeCreated, Message

风险与修复建议

  • 先隔离主机,不建议立即关机。若进程仍在运行,优先采集内存、进程 dump、网络连接和注册表。
  • 删除持久化项前,记录键值名称、路径、时间戳,便于后续横向排查。
  • 对同网段终端批量检索互斥体名称、样本哈希、Run 项名称、异常路径。
  • 在出口设备上封禁 C2 IP、域名、URI 特征,同时回溯历史连接。
  • 检查被控主机上的凭据暴露风险,尤其是浏览器保存密码、RDP 凭据、VPN 客户端配置。
  • 若样本具备命令执行能力,需要继续排查是否执行过信息收集、凭据抓取、横向移动命令。
可用于批量检索的 IOC 示例:

FilePath:
C:\Users\*\AppData\Roaming\Microsoft\Windows\svchost.exe

Registry:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Windows Update Service

Mutex:
Global\WinUpdSvc_2024

Network:
185.x.x.x:443
/api/checkin

总结

逆向远控木马时,不要只停留在“有外联就是木马”的判断。更可靠的做法是把样本配置、持久化位置、C2 通信、命令执行能力和主机日志串起来。这样既能确认远控能力,也能给出可落地的清理和溯源依据。

本次样本的关键点在于:配置经过简单异或隐藏,真实 C2 需要在调用网络 API 前后观察;持久化使用 HKCU Run 项;命令执行通过 CreateProcessW 完成。实际处置时,建议把这些点转成 IOC 和日志检索条件,在全网范围内做一次横向排查。

逆向分析与样本观察示意图
逆向分析、样本行为与调试流程示意
可以补一条我在内网排查远控样本时比较常用的思路:先别急着跑全量杀软,优先把“配置”和“落点链路”固定下来,后面溯源、横向排查会省很多时间。 样本配置提取建议重点看这几类位置: 1. 字符串里找 C2 / mutex / install path 如果样本没有重度混淆,先直接过一遍:
strings -a sample.exe | findstr /i "http https tcp udp mutex key install appdata programdata cmd powershell"
如果是宽字符:
strings -a -el sample.exe | findstr /i "http https .com .cn .top .xyz mutex"
2. 看资源段和 overlay 很多远控会把配置放在资源、末尾 overlay 或简单异或加密区域。可以先确认 PE 结构:
pefile sample.exe
diec sample.exe
sigcheck -m sample.exe
如果怀疑末尾追加配置,可以对比最后一个 section 的 raw size 与文件实际大小,存在 overlay 时单独切出来分析:
python - << "EOF"
import pefile, sys
p="sample.exe"
pe=pefile.PE(p)
last=max(pe.sections, key=lambda s: s.PointerToRawData+s.SizeOfRawData)
end=last.PointerToRawData+last.SizeOfRawData
data=open(p,'rb').read()
print("file size:", len(data), "section end:", end, "overlay:", len(data)-end)
if len(data)>end:
    open("overlay.bin","wb").write(data[end:])
EOF
然后对 overlay 做 strings / 熵值 / XOR 猜测。很多配置是单字节 XOR,先爆破可读字符串命中率就够用。 3. 动态提取配置 如果样本会解密后再联网,可以在沙箱或隔离 VM 里盯几个 API: - WinHttpOpenRequest / WinHttpSendRequest - InternetConnectW / HttpOpenRequestW - connect / send - RegSetValueExW - CreateServiceW - CreateProcessW x64dbg 下可以给这些 API 下断点,重点看参数和返回后的内存。通常能直接拿到 C2、端口、URI、User-Agent、分组名、上线密码之类。 留痕定位上,建议按“启动项、服务、计划任务、WMI、进程注入、网络连接”六条线走,命令可以直接落地:
:: 启动项
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
reg query "HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Run"

:: 服务
wmic service get name,displayname,pathname,startmode,state | findstr /i "appdata programdata temp users"

:: 计划任务
schtasks /query /fo LIST /v | findstr /i "TaskName Task To Run appdata programdata powershell wscript rundll32"

:: WMI 持久化
wmic /namespace:\\root\subscription PATH __EventFilter get Name,Query
wmic /namespace:\\root\subscription PATH CommandLineEventConsumer get Name,CommandLineTemplate
wmic /namespace:\\root\subscription PATH __FilterToConsumerBinding get Filter,Consumer

:: 当前网络连接
netstat -ano | findstr ESTABLISHED
tasklist /svc
如果主机开了 Sysmon,建议重点查这些事件: - Event ID 1:进程创建 - Event ID 3:网络连接 - Event ID 7:模块加载,尤其异常路径 DLL - Event ID 11:文件创建 - Event ID 13:注册表修改 - Event ID 22:DNS 查询 PowerShell 查询示例:
Get-WinEvent -FilterHashtable @{LogName="Microsoft-Windows-Sysmon/Operational"; Id=1,3,11,13,22} |
  Where-Object { $_.TimeCreated -gt (Get-Date).AddDays(-7) } |
  Select-Object TimeCreated, Id, ProviderName, Message |
  Out-File .\sysmon_check.txt -Encoding utf8
还有一点容易漏:远控常见落点不一定在 exe 本体,可能是 rundll32/regsvr32/mshta/powershell 拉起的二阶段。排查时不要只盯样本文件名,建议按异常路径和父子进程关系看,比如: - `C:\Users\*\AppData\Roaming\` - `C:\Users\*\AppData\Local\Temp\` - `C:\ProgramData\` - 用户目录下伪装成系统名的文件,如 `svchost.exe`、`RuntimeBroker.exe` 最后配置提取后,建议把这些字段整理成 IOC 表:C2、端口、URI、User-Agent、mutex、服务名、计划任务名、注册表键、文件 hash、落地路径。内网横向排查时可以直接用这些 IOC 去扫日志和 EDR,比单纯拿 hash 查要稳一些。
补一条留痕侧的做法:配置提取完以后,建议把“样本声明的持久化位置”和“系统真实落点”做一次交叉验证,很多远控会改名落在正常目录里,但注册表/任务计划里的参数能把链路串起来。 可以优先查这几块: 1. 启动项和服务参数
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKLM\SYSTEM\CurrentControlSet\Services" /s | findstr /i "ImagePath DisplayName ObjectName"

wmic service get Name,DisplayName,PathName,StartMode,State | findstr /i "appdata programdata temp powershell rundll32 regsvr32 mshta"
重点看这些特征: - ImagePath 指向 %AppData%、%ProgramData%、%Temp% - 服务名正常但路径异常,比如伪装成 update、audio、driver - 参数里带 -enc、-nop、rundll32 xxx.dll,Start 这类形式 2. 任务计划不要只看名字,要导出 XML 很多远控不会直接暴露在 schtasks /query 的摘要里,动作参数在 XML 里更清楚:
schtasks /query /fo LIST /v

mkdir C:\Temp\tasks_xml
for /f "tokens=*" %i in ('schtasks /query /fo csv ^| findstr /v "TaskName"') do @echo %i

dir /s /b C:\Windows\System32\Tasks > C:\Temp\tasks_list.txt
findstr /s /i "powershell wscript cscript mshta rundll32 regsvr32 appdata programdata temp" C:\Windows\System32\Tasks\* 
如果发现可疑任务,直接看文件内容即可,里面会有 Command 和 Arguments。 3. 用 Amcache / ShimCache / Prefetch 补执行时间线 这一步对定位“谁先落地、谁拉起谁”比较有帮助。尤其是样本已经被删掉时,Amcache 和 Prefetch 经常还能留下痕迹。 可以先收这些文件:
C:\Windows\AppCompat\Programs\Amcache.hve
C:\Windows\Prefetch\*.pf
C:\Windows\System32\config\SYSTEM
C:\Windows\System32\winevt\Logs\Security.evtx
C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx
排查时重点关联: - 可疑 EXE 首次执行时间 - Prefetch 中的运行次数和路径 - PowerShell 4104/4103 事件里是否有下载、解码、反射加载 - Security 4688 如果开启了进程命令行记录,可以直接还原父子进程 4. 网络侧别只看当前连接,查 DNS 缓存和代理日志 远控 C2 如果是域名,机器本地可能还有 DNS 缓存:
ipconfig /displaydns | findstr /i ".top .xyz .icu .shop .cn .com"
netstat -ano | findstr "ESTABLISHED"
tasklist /fi "PID eq 进程PID"
如果内网有 DNS 日志、代理日志或防火墙会话日志,建议拿配置里提取到的 C2、URI、User-Agent、端口去反查,同一时间段命中的主机往往就是横向排查范围。 5. 样本配置建议落成 IOC 表 最后别只记录文件 Hash,最好整理成这种结构,方便后续批量排查:
FileName:
SHA256:
CompileTime:
C2:
Port:
URI:
Mutex:
InstallPath:
ServiceName:
TaskName:
RegistryKey:
UserAgent:
Persistence:
FirstSeenHost:
FirstSeenTime:
实践里比较有效的是:先用配置确定通信特征,再用持久化位置和执行痕迹确定感染链路,最后用网络日志扩散排查范围。这样比单纯全盘查杀更容易把同批落点和二阶段载荷找出来。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。