我最近偶然发现了一款设计精巧的恶意软件,它自称“Torumaline”。
这份 README 是由 Claude 非常友好地撰写的,因为在本仓库创建时我正忙于考试。
利用和解密这款恶意软件占用了我大量原本用于数学备考的时间!
阅读博客文章!
仅供教育和研究目的使用
所有样本均用于恶意软件分析和防御性研究。请勿在沙箱、气隙环境之外执行。
Tourmaline(Tourmaline.exe)是一款复杂、多阶段的 Windows 信息窃取/后门程序,通过 ClickFix 活动分发——一个伪造的 Cloudflare“验证您是真人”浏览器弹窗,诱骗用户手动运行恶意命令或安装程序。
该二进制文件是一个自定义构建的 Inno Setup 6.7.0(修订版 2,64 位偏移) 安装程序,捆绑了完整的 Python 3.11 运行时和两个阶段的混淆 Python 载荷。它建立了一个持久后门,具备:
microsoft.com 查询)tourmaline/
├── README.md # 本文件
├── LICENSE # 研究使用许可
├── .gitignore
│
├── src/ # 提取并反混淆的源代码
│ ├── stage1_loader.py # 阶段 1:原始混淆的 XOR 时间锁加载器(main.py)
│ ├── stage2_backdoor.py # 阶段 2:反混淆的核心后门(来自 QGBdu.dxf)
│ └── decrypt_payload.py # 工具:O(1) 载荷密钥恢复与解密
│
├── iocs/ # 入侵指标
│ ├── indicators.json # 结构化 IOC 数据(IP、哈希、域名、注册表)
│ ├── indicators.csv # 用于 SIEM 导入的扁平 CSV
│ └── rules.yar # YARA 检测规则
│
└── samples/ # 恶意软件样本(密码保护)
├── README.md # 样本归档说明
├── Tourmaline_sample.zip # 密码:infected - 包含 Tourmaline.exe
└── QGBdu.dxf # 原始加密的阶段 2 载荷数据块
该恶意软件通过 ClickFix 分发——一种社会工程学技术,攻击者控制的或被入侵的网站会覆盖一个伪造的 Cloudflare CAPTCHA 或浏览器验证页面。该覆盖层指示受害者:
Win+R粘贴的命令会下载并静默执行 Tourmaline.exe。安装程序以 /VERYSILENT /SUPPRESSMSGBOXES /NORESTART 参数运行。
注意: 原版
innoextract 1.9无法提取此二进制文件——它仅支持修订版 1。修订版 2 使用 64 位偏移,需要自定义解析(参见src/decrypt_payload.py)。
Tourmaline.exe
│
├─ Inno Setup 安装程序静默运行
│ ├─ 将 Python 3.11 运行时解压到 %APPDATA%\Tourmaline\
│ ├─ 解压 main.py(阶段 1 加载器)
│ ├─ 解压 QGBdu.dxf(加密的阶段 2 数据块)
│ ├─ 终止任何现有的 pythonw.exe 实例
│ └─ 注册持久化(任务计划程序 / 注册表)
│ └─ 名称:"TourmalineUpdate" / "Hardware monitoring service"
│
├─ 阶段 1:main.py(XOR 时间锁加载器)
│ ├─ 从 99,999,999 → 0 计数 _n(在慢速 VM 上反沙箱延迟约数小时)
│ ├─ 对每个 _n,构造 33 字节 XOR 密钥:struct.pack('>I', _n) + hardcoded_suffix
│ ├─ 用该密钥测试 QGBdu.dxf 的已知明文头部
│ └─ 匹配时:完全解密 QGBdu.dxf 并 exec() 结果
│ └─ O(1) 绕过:对前 4 字节进行已知明文攻击(见下文)
│
└─ 阶段 2:QGBdu.dxf → Python 后门
├─ 从 HKLM\SOFTWARE\Microsoft\Cryptography 读取 MachineGuid
├─ 派生互斥体 Global\Tourmaline_<hash>
├─ 通过以太坊死信箱(Sepolia 测试网)解析 C2 IP
├─ 建立到 C2 的 DNS 隧道
└─ 轮询执行循环:获取任务,exec() Python,返回输出
加载器(main.py)使用从 99,999,999 开始的倒计时来查找 XOR 解密密钥。在真实机器上这会在几秒内完成(因为 _n 从高位开始,真实值接近 14,511,188)。在时间限制较短的沙箱中,循环永远不会完成。
密钥结构:
full_key = struct.pack('>I', _n) + bytes.fromhex('2b0cffe07b06ac25793b3f00cfaa2dd5881c2d6378165247539dbbdaeb')
由于我们知道明文的前 16 个字节(g1 = lambda l6, ),我们可以通过已知明文 XOR 攻击立即恢复 _n:
key_prefix = bytes(ciphertext[i] ^ known_plaintext[i] for i in range(4))
# 结果:key_prefix = 00dd6c54 → _n = 14,511,188
使用 src/decrypt_payload.py 复现此过程。
该恶意软件调用 Sepolia 测试网上的以太坊智能合约来获取活跃的 C2 IP 地址。这意味着攻击者可以随时通过更新合约来更改 C2 IP——传统的基于 IP 黑名单的 C2 阻断手段将失效。
合约 : 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5
选择器 : 0xeb9fd6fe
网络 : Ethereum Sepolia (chainId 11155111)
RPC : https://ethereum-sepolia-rpc.publicnode.com
结果 : 包含当前 C2 IP 的 ChaCha20 加密数据块
返回的数据使用硬编码的 ChaCha20 密钥解密,以揭示实时 C2 地址。在分析时,解析结果为 158.94.211.185(通过实时 RPC 调用验证)。
所有 C2 流量都作为原始 UDP DNS 查询直接发送到 C2 IP 的 53 端口。查询结构为 <encoded_data>.microsoft.com,绕过基于 DNS 的过滤,并看起来像合法的 Windows 遥测数据。
socket.getaddrinfo 或任何 DNS 库后门实现了一个任意 Python exec() 引擎。任务流程:
exec() 并捕获输出支持的任务类型: Python exec、文件上传/下载、shell 命令、自更新。
| 文件 | SHA256 |
|---|---|
Tourmaline.exe | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
Tourmaline.exe(MD5) | b74ac808dea2de31caf024310694ef0c |
参见 iocs/rules.yar 获取检测规则,涵盖:
如果此恶意软件已在某台机器上执行:
taskkill /F /IM pythonw.exe%APPDATA%\Tourmaline\ 或 %COMMONAPPDATA%\Tourmaline\TourmalineUpdateHKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 中是否有 Tourmaline 或 SystemService158.94.211.185:53/UDP;阻断所有意外的出站 UDP/53ethereum-sepolia-rpc.publicnode.compip install pyOpenSSL cryptography
# 从仓库根目录:
python3 src/decrypt_payload.py samples/QGBdu.dxf decrypted_stage2.py
7z x -pinfected samples/Tourmaline_sample.zip
参见 LICENSE。本仓库仅供教育和防御性研究目的使用。
| 属性 | 值 |
|---|
| 文件名 | Tourmaline.exe |
| 大小 | 11,341,339 字节(约 10.8 MB) |
| MD5 | b74ac808dea2de31caf024310694ef0c |
| SHA256 | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
| 格式 | Inno Setup 6.7.0 Unicode(修订版 2,64 位偏移) |
| PE 类型 | 32 位 PE,11 个节区 |
| 覆盖层大小 | 10,447,387 字节 |
| Inno 魔数偏移 | 0xD9864(890,148 字节) |
| 应用名称 | Tourmaline |
| 应用版本 | 2.63.519 |
| 应用 GUID | {2C25872D-85FC-44C7-9B16-844E39E50A44} |
| 安装路径 | {commonappdata}\Tourmaline |
| 捆绑运行时 | Python 3.11(完整嵌入) |
| 载荷文件 | 36 个文件,位于 solid LZMA2 流中 |
| 参数 | 值 |
|---|
| C2 IP | 158.94.211.185 |
| C2 端口 | 53(UDP) |
| 协议 | 自定义 DNS-over-UDP 隧道 |
| 伪装域名 | microsoft.com |
| ChaCha20 密钥 | 36f555c87f71581f57d83576c88193fdc00a0173f741a3e198e2d7abdc9cda59 |
| 区块链合约 | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5(Sepolia) |
| ECDSA 公钥 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt17l3rGHHR9sYdHEvV8S+JRRCUHQQveSadlGk04xM/8WClDf/67Tyritt2+T18SY8n0xv1TKKl0AgnNFuboEEQ== |
| 服务名称 | SystemService / TourmalineUpdate |
| 互斥体 | Global\Tourmaline_<MachineGuid-hash> |
| 类型 | 值 |
|---|
| C2 IP | 158.94.211.185 |
| C2 端口 | 53/UDP |
| 伪装域名 | *.microsoft.com(自定义 UDP,非真实 DNS) |
| 以太坊 RPC | https://ethereum-sepolia-rpc.publicnode.com |
| 智能合约 | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 |
| 键 | 值 |
|---|
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid | 读取用于受害者指纹识别 |
%APPDATA%\Tourmaline\ | 安装目录 |
| 任务计划程序 | TourmalineUpdate |
| 服务显示名称 | Hardware monitoring service |
| 互斥体 | Global\Tourmaline_<hash> |
| 字段 | 值 |
|---|
| 发现日期 | 2026 年 9 月 |
| 研究员 | Vihaan Pundir (v-pun215) |
| 分发途径 | ClickFix 伪造 Cloudflare CAPTCHA |
| 分类 | 后门 / DNS 隧道 C2 / 区块链死信箱 |
| 平台 | Windows(64 位) |