PhantomSync:npm 加密包隐藏钱包窃取器

PhantomSync:八个加密开发者的 npm 包隐藏了一个延迟的、自持久化的投放器

TL博士

一位 npm 发布者发布了八个小型软件包,这些软件包的名称就像是区块链和钱包开发中常用的构建模块。 base58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helperscrypto-validate-lib每个模块都包含一个可用的实用程序。不过,在这些实用程序之后,还会附加一个自调用代码块,该代码块会在模块被导入时立即运行。

导入后大约 37 秒该代码块解码软件包内伪装成测试工具的有效载荷,将其写入用户主目录下的一个隐藏文件,并注册自身以便在每次重启时重新启动。 login 该功能可在 Windows、macOS 和 Linux 系统上运行,并将解码后的脚本作为独立进程启动。此过程不会在 npm install 期间执行;它会等待代码导入并运行,这比安装过程要安静得多。

有效载荷并非不透明。它以纯 base64 编码形式提供,因此解码“测试装置”即可完整恢复第二阶段:a 加密钱包和密钥窃取器 它会等待机器处于空闲状态,收集私钥和助记词,使用硬编码的 RSA-4096 密钥对找到的每个密钥进行加密,并通过将其固定到公共 IPFS 存储来将其泄露,每 12 小时发送一次信标。

我们跟踪集群 PhantomSync分析时,所有八个软件包都已在 npm 注册表中上线,并发布在同一个帐户下。

生态系统NPM
base58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpers, crypto-validate-lib
目标平台Windows,macOS,Linux
核心行为延迟导入时隐藏的测试工具;安装跨平台持久化
Payload加密钱包和密钥窃取器,RSA-4096 加密,通过公共 IPFS 锁定进行数据窃取

攻击解剖

乍一看,每个包裹都毫不起眼。 base58-utils例如,这是一个几千字节的零依赖 Base58 / Bitcoin-WIF 辅助代码——正如其名称所示。相关代码位于…… 该模块的 模块导出而快速浏览文件顶部的读者不太可能看到:一个使用定时器进行自我调用的函数。

根据软件包源代码重建的操作链如下:

1. Package is required() by the host project
2. A self-invoking function schedules a callback ~37,000 ms later (setTimeout)
3. On fire, the callback reads test/fixtures/keypairs.dat (a base64 blob)
4. It base64-decodes that blob into a Node.js script
5. It writes the script to ~/.cache-db/.node-sync/syncd.js (mode 0o700)
6. It installs login-persistence for that script (see below)
7. It spawns "node syncd.js" as a detached process

两项设计选择尤为突出。

有效载荷作为测试夹具进行运输。 第二阶段的代码并非显而易见的。它存在于…… test/fixtures/keypairs.dat这是一个 base64 文件,其名称与一个声称可以处理密钥对的软件包名称混淆。对于快速浏览 tar 包的人来说,它看起来像是示例数据;而对于附加的代码来说,它是一个需要解码和运行的脚本。投放器本身不包含网络地址——这些地址位于第二阶段——但也没有额外的混淆:该测试用例只有一层 base64 编码,因此解码它(base64 -d)恢复全部 syncd.js 及其网络行为。下一节将详细介绍恢复阶段的功能。

引爆是延迟的,并且与导入有关,而不是与安装有关。 因为触发器是 要求() 此外,该行为还使用了一个约 37 秒的计时器,而不是安装钩子,从而绕过了仅监视的检查。 npm安装 步骤执行完毕后,延迟时间会超过许多短暂的沙箱和持续集成运行周期。等到所有操作都执行完毕时,拉取软件包的安装过程早已完成。

一旦解码后的脚本保存到磁盘上…… ~/.cache-db/.node-sync/syncd.js — 选择与常规缓存目录类似的路径 — 该投放器使其能够在三大主流平台上重启后仍然存在:

  • Linux的: 一个用于重新启动脚本的 cron 条目。该条目通过过滤现有的 crontab 文件来安装。 grep -v 同步这样做会产生一个副作用,即在搜索相同名称的普通列表中遗漏新条目。
  • Windows上: 一个名为“计划任务” WinNodeSync设置为每 12 分钟重新运行一次。
  • 苹果系统: 一个名为 launchd 的作业 com.apple.syncd多个包装盒上都贴有标签——该标签模仿了合法的苹果系统服务。

然后脚本会立即作为分离进程启动,因此在导入程序退出后它会继续运行。

第二阶段的作用

由于该夹具是一个单层 base64 编码,因此第二阶段可以干净地解码并完整读取。所有八个数据包都包含同一脚本的三种变体之一,该脚本在头部注释中标识自身。 幻影同步 v3 — topo durmiente (“沉睡的鼹鼠”)。它的任务是窃取加密货币钱包数据和开发者机密信息,并将它们从机器上转移出去。它的运行步骤如下:

  • 1. 等到机器空闲后再进行操作。 在做任何事情之前, syncd.js 检查用户不活动的时间,只有超过一定阈值(约 15 分钟)才会继续执行操作。 打印空闲 在 Linux 上, 奥雷格 macOS 上使用 HIDIdleTime,Windows 上使用 PowerShell 空闲时间查询。因此,数据采集往往发生在无人操作键盘的时候。
  • 2. 获取一个远程控制的启动开关脚本在执行操作前会从一个隐藏的服务器拉取一个小型配置。主要来源是 GitHub gist 的原始 URL(gist.githubusercontent.com/juang55/…/cfg.txt);只有当该配置读取到该配置时,脚本才会激活 活动=1如果 gist 不可用,则会回退到通过公共网关获取的三个硬编码的 IPFS 内容标识符。 网关.pinata.cloud, ipfs.iocloudflare-ipfs.com这使得操作员能够在事后进行布防/撤防控制,并具备防拆卸的备用方案。(最小型号,出厂于……) 加密验证库, 以太坊钱包助手solana-key-utils(已移除 gist 层,仅依赖于 IPFS 标识符。)
  • 3. 收集钱包里的素材和秘密。 该脚本会遍历用户的主目录—— ~/.config/solana, ~/.ethereum/keystore, ~/.foundry, ~/.hardhat, 〜/ .ssh桌面/技术文档/资料下载 (包括西班牙语文件夹名称),加上 ~/.env 以及 shell rc 文件,以及等效文件 应用程序数据 它针对的是 Windows 系统上的位置。目标包括以太坊私钥、比特币 WIF 密钥、BIP-39 助记词、Solana 密钥对、以太坊密钥库 JSON、SSH 密钥以及包含密钥的环境变量。更大的变体(在 abi编码, base58-utils, eth-dev) 包含完整的 2048 个单词的 BIP-39 词典,并使用正则表达式来 提取 它能从读取的任何文本中提取单个密钥和已验证的种子短语;而两个较小的变体则通过关键字匹配文件(种子, 助记符, 账户余额, metamask, 模体, 总账, trezor,…)并上传整个文件。
  • 4. 通过公共加密服务进行加密和泄露。 每个发现都与一个宿主指纹相关联(用户名@主机名(、平台、时间戳)并使用嵌入脚本中的硬编码 RSA-4096 公钥进行加密。然后,通过将其固定到 IPFS 来上传加密记录。 api.pinata.cloud/pinning/pinJSONToIPFS并通过硬编码的 Pinata API 凭证进行身份验证。无需查封任何定制的 C2 服务器:被盗数据存储在公共去中心化存储中,操作者可以使用生成的哈希值检索数据。上传操作之间会存在几秒钟的随机抖动,并会生成本地日志。 时间戳 | 键类型 | 返回哈希值 保存于 ~/.cache-db/.node-sync/.sl.
  • 5. 持续发出信号,每 12 小时循环一次。 第二阶段重新建立自身的持久性——在Linux系统上添加一个cron条目, com.apple.syncd macOS 上的 launchd 作业,以及一个名为“launchd”的计划任务 WindowsNodeSync 在 Windows 系统上——设置为每 12 小时重新运行一次。请注意,这是一个 不同 从投放器安装的进程中提取的 Windows 任务名称(WinNodeSync两者都值得寻找。

时间线

这八个软件包于 2026 年 07 月 13 日和 2026 年 07 月 14 日集中发布。其中一些软件包有多个版本;各个版本的投放器完全相同,只有行偏移量会随着其上方良性实用程序代码的大小变化而变化。

日期 创建
2026-07-13 集群中的首批软件包出现在一个发布者之下(solana-key-utils, eth-wallet-helpers, crypto-validate-lib 以及其他部分的早期版本)
2026-07-13 → 07-14 其余名称和后续版本已公布;每个版本都附带相同的投放器。
2026-07-14 所有八个软件包均已标记并分析;每个软件包仍然可以从注册表中安装。

在这次攻击爆发期间,发布者的注册信誉从集群开始时的大致中性变为随着检测结果的累积而出现的强烈负面——这是软件包被标记的可观察副作用,而不是设计的功能。

妥协指标

以下所有指标均已确认在分析时存在——即通过解码“第二阶段”表格中的指标。 test/fixtures/keypairs.dat 并阅读已恢复的内容 syncd.js.

文件和路径

指示符 职位
~/.cache-db/.node-sync/syncd.js 解码后的第二阶段,以模式 0o700 写入
~/.cache-db/.node-sync/.sl 本地数据泄露日志(时间戳 | 键类型 | IPFS 哈希值)
test/fixtures/keypairs.dat tar 包内放置了 Base64 编码的有效载荷,作为“测试装置”。

第二阶段网络基础设施(从 syncd.js 中恢复)

指示符 职位
gist.githubusercontent.com/juang55/b298754cb72942b1cdcf02ccd45cde2f/raw/cfg.txt 激活死信箱;脚本仅在配置读取时运行 active=1
Qmcqz3w8j4qFQXDAXAxnrdc2oSX3nzBT4NqtpTqL8mr1ga IPFS 配置回退(CID)
QmdTXoqVmTHY1i4ZWLdLkoQ9YChp5TXPh5cWXwnAYZt5iF IPFS 配置回退(CID)
QmfJkLU5gdCpqbbqEjWYC2anXW9FmuEeSLLeLiHVJKYUjp IPFS 配置回退(CID)
gateway.pinata.cloud, ipfs.io, cloudflare-ipfs.com 用于获取配置回退的 IPFS 网关
api.pinata.cloud/pinning/pinJSONToIPFS 数据外泄端点,被盗数据锁定在公共 IPFS 上
Pinata API密钥 13c766575b9270a9825d硬编码的窃取凭证

第二阶段收集目标(从 syncd.js 中恢复)

指示符 职位
~/.config/solana, ~/.ethereum/keystore, ~/.foundry, ~/.hardhat, ~/.ssh, ~/.envshell rc 文件 搜索密钥和秘密信息的目录/文件
AppData\Roaming\Solana, AppData\Local\ethereum\keystore 搜索Windows等效项
采集的文物类型 以太坊私钥、比特币WIF、BIP-39助记词、Solana密钥对、以太坊密钥库JSON、SSH密钥、秘密环境变量

持久化工件

平台 指示符
Linux 定时任务启动 syncd.js; 通过 crontab 过滤安装 grep -v syncd
Windows 预定任务 WinNodeSync (滴管)和 WindowsNodeSync (第二阶段)
macos launchd 标签 com.apple.syncd
全部内容 第二阶段以12小时为一个周期持续进行。

行为

  • 自调用函数附加在后面 模块导出,安排一个 设置超时 导入耗时约 37,000 毫秒。
  • 子进程 spawn(“节点”, ) 已设置分离选项。
  • 第二阶段的空闲门控激活(打印空闲 / 奥雷格 HIDIdleTime / PowerShell 空闲时间;阈值约为 15 分钟)。
  • 先进行 RSA-4096 加密,然后进行 HTTPS 加密 解决方案&帖子 连接到公共 IPFS pinning API。

软件包和版本(npm,发布者 solbuilder_io)

小包装 选项
base58-utils 1.0.0,1.0.1,1.0.3
abi-encode 1.0.0,1.0.1,1.0.2
eth-dev 1.0.0,1.0.1,1.0.2
arb-kit 1.0.0,1.0.1
layer2-sdk 1.0.0,1.0.1
solana-key-utils 1.0.0
eth-wallet-helpers 1.0.0
crypto-validate-lib 1.0.0

出版商

  • solbuilder_io - angel_lopez89[@]proton[.]me邮箱未经验证,没有经过验证的源代码控制帐户,没有链接的存储库。

归因与观察行为

这八个软件包共享一个发布者帐户和一个有效载荷。每个软件包都很简单——几千字节的实际实用代码,附加了相同的投放器——发布时没有链接存储库,并且使用未经验证的一次性电子邮件。这种统一性、共享的投放路径、共享的持久化标签和共享的 keypairs.dat 暂存文件是将集群连接在一起的关键。

这些包裹对自己行为的描述异常坦率。 solana-key-utils 包含内联注释,用通俗易懂的语言描述附加的代码块——其中一个标签是…… 幻影:隐形持久性另一条(西班牙语)写道: 执行 topo en background“在后台运行鼹鼠程序。”这些是代码自身对其功能的注释;本文中的活动名称取自第一个标签以及虚构的节点“同步守护程序”(同步)持久性机制模仿的。

我们仅描述代码的可观察行为。软件包的命名——全部是加密货币、钱包和区块链工具相关的术语——表明了最有可能通过名称下载它们的开发者群体;但这本身并不能确定发布者是谁。第二阶段可以通过解码 base64 编码的数据完全恢复,其行为如上所述:它收集钱包密钥、助记词和秘密信息,并通过 Pinata 将它们以 RSA 加密的形式泄露到公共 IPFS 存储中。一个值得注意的设计选择是没有使用私有 C2 服务器——配置信息来自 GitHub gist 和 IPFS,被盗数据则存储在以内容哈希为密钥的公共去中心化存储中,这两者都比单个攻击者控制的主机更难被查封。截至撰写本文时,尚未发现与此集群匹配的公开报告。

影响、趋势及对辩护者的指导

谁会被曝光? 任何将这些软件包添加到 Node 项目并运行导入该软件包的代码的人都可能成为攻击者的目标。由于引爆发生在导入时而非安装时,仅仅拥有该软件包是不够的——任何加载该模块的正常使用都会触发有效载荷。这些诱饵名称的目标用户是使用以太坊、Solana、Arbitrum、Layer-2 以及通用钱包/编码工具进行开发的开发者——这些人最有可能拥有第二阶段攻击所寻找的资产。任何在存储钱包密钥、助记词、密钥库、SSH 密钥或其他敏感信息的机器上运行过这些模块的人都可能成为攻击者的目标。 .ENV 密钥管理部门应将这些凭证视为已泄露并轮换使用。

两种值得铭记的模式。 首先, 有效载荷即夹具:将第二阶段的数据以 base64 编码的形式打包到一个名称合理的数据文件中(test/fixtures/keypairs.dat)保持软件包的可见源代码看起来干净,并将恶意内容推送到一个审查工具和人工快速浏览通常会将其视为惰性数据的文件中。其次, 具有跨平台持久性的导入时间延迟执行将触发器从安装钩子中移开,添加计时器,然后通过 cron、计划任务和 launchd 持久化,这是有意远离自动注册表扫描密切关注的、噪音较大的安装脚本技术的一步。

防御者和维护者的指南:

  • 处理附加代码 模块导出 作为审查重点——投放器逻辑经常隐藏在“真正”的模块表面之下。
  • 不要假设数据文件是静止的。base64 编码的 blob 位于 测试/夹具/ 在运行时读取并解码的文件是可执行文件附近的;标记运行时读取的 fixture 文件,这些文件提供给 功能/评估/write-then- 链。
  • 寻找掉落路径 ~/.cache-db/.node-sync/ 以及持久性单元 WinNodeSync (计划任务)和 com.apple.syncd (已启动)在提取这些名称的开发者机器上。
  • 提醒注意创建 cron 条目、计划任务或 launchd 作业的 Node 进程——合法的库在导入时很少这样做。
  • 优先使用锁定文件和固定版本,并仔细检查任何新的小型“实用程序”依赖项的差异,尤其如此。 已发布的零依赖软件包 由未经核实的帐户发布,且未关联任何存储库。

对于注册表防御者来说,关键在于安装钩子监控是必要的,但还不够:导入时、定时器延迟的投放器被放置在数据文件中,将通过仅安装时的检查,而持久化步骤通常是剩下的最明显的信号。

sca-tools-软件-成分分析工具
确定软件风险的优先级、进行补救并加以保护
注册免费账号。
不需要信用卡。

保护您的软件开发和交付

使用 Xygeni 产品套件