TL博士
一位 npm 發布者發布了八個小型軟體包,這些軟體包的名稱就像是區塊鏈和錢包開發中常用的構建模組。 base58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpers以及 crypto-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 分鐘)才會繼續執行操作。 xprintidle 在Linux系統上, ioreg macOS 上使用 HIDIdleTime,Windows 上使用 PowerShell 空閒時間查詢。因此,資料採集往往發生在無人操作鍵盤的時候。
- 2. 取得遠端控制的啟動開關腳本在執行操作前會從一個隱藏的伺服器拉取一個小型設定。主要來源是 GitHub gist 的原始 URL(gist.githubusercontent.com/juang55/…/cfg.txt);只有當該配置讀取到該配置時,腳本才會激活 活動=1如果 gist 不可用,則會回退到透過公用閘道取得的三個硬編碼的 IPFS 內容識別碼。 網關.pinata.cloud, ipfs.io以及 cloudflare-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(“節點”, ) 已設定分離選項。
- 第二階段的空閒門控啟動(xprintidle / ioreg 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 進程——合法的庫在導入時很少這樣做。
- 優先使用鎖定檔案和固定版本,並仔細檢查任何新的小型「實用程式」依賴項的差異,尤其如此。 已發布的零依賴軟體包 由未經核實的帳戶發布,且未關聯任何儲存庫。
對於註冊表防御者來說,關鍵在於安裝鉤子監控是必要的,但還不夠:導入時、定時器延遲的投放器被放置在數據文件中,將通過僅安裝時的檢查,而持久化步驟通常是剩下的最明顯的信號。



