DDoS 攻擊背後的隱形指揮官?
摘要
報告提供了對 RustDuck 的全面技術分析,這是一個自 2026 年 2 月以來活躍的、架構精密的雙階段僵屍網路(Two-stage botnet)。RustDuck 展現了「Loader + Core」的架構,具備強大的跨平台適應性和快速的技術演進能力,尤其顯現在其技術堆疊從 C 語言轉移到 Rust 的過程。此僵屍網路的主要功能是執行大規模分散式阻斷服務(DDoS)攻擊。這份分析深入探討了其 Loader 的演進階段、Core 模組中使用的進階金鑰生成與加密演算法,以及其複雜的反除錯和環境閃避技術。此外,報告還包含與其他當代惡意軟體的比較概述,以凸顯不斷演變的威脅態勢和緩解策略。目標是闡明 RustDuck 的技術細節,並強調針對這類演進中的威脅,建立強健防禦措施的必要性。
1. 簡介
自 2026 年初以來,資安領域見證了 RustDuck 的出現,這是一個新穎的惡意軟體家族,其特點在於雙階段的載入機制,以及其開發範式從 C 到 Rust 的重大轉變。這種轉變凸顯了惡意軟體開發朝向能提供更高性能、記憶體安全性和降低可偵測性的語言發展的廣泛趨勢。RustDuck 的架構包含一個 Loader 和一個 Core 模組,利於大規模 DDoS 攻擊的執行,同時整合了進階的反分析和流量加密能力 [1] 。其傳播方式主要針對物聯網設備(IoT device)、網頁應用程式和企業基礎設施,透過弱密碼暴力破解和利用各種 RCE 漏洞來達成 [1] 。報告目的在剖析 RustDuck 的技術演變,重點關注其 Loader 變體、Core 功能以及複雜的閃避策略。
2. Loader 演進與分群分析
RustDuck 的 Loader 組件設計為精簡的三部分結構:載入程式碼、壓縮資料(Core)和設定資訊(Config)。這種設計通常會將壓縮後的 Core 資料和設定以覆蓋資料(overlay data)的形式附加在標準 ELF 檔案的結尾 [1] 。對設定資訊進行結構化逆向工程後,發現了 Loader 的四個不同演進階段,每個階段都引入了新的混淆和加密技術。
2.1. Loader 變體 1
這個初始變體使用 16 位元組的設定,平均分成四個 4 位元組的欄位:Key、Compress_Size、Decompress_Size 和 Magic。它使用線性同餘同餘產生器(Linear Congruential Generator, LCG)結合 XOR 進行解密,然後進行 LZ4 解壓縮。Magic 驗證演算法涉及循環左移(ROL)和 XOR 組合 [1] 。
comperss_size ^ decompress_size ^ ROL4(key, 13) ^ 0x5A3C9E7F == magic
2.2. Loader 變體 2
變體 2 將設定大小擴展到 33 位元組,引入了一個 16 位元組的 Key、4 位元組的 Compress_Size、4 位元組的 Decompress_Size、8 位元組的 Magic 和一個 4 位元組的 Noise_Size。解密機制升級為 Xoshiro128 + XOR,解壓縮演算法則切換為 BLZ。此變體中一個顯著的應對措施是引入了多個寫死在程式碼中的常數(hard-coded constants)來混淆解密和 Magic 驗證,這些常數在不同樣本中動態變化,增加了安全研究人員進行靜態批次解密的難度 [1] 。
2.3. Loader 變體 3
這個變體擁有 48 位元組的設定,標準化為使用標準 XOR 解密和 LZ4 解壓縮。記憶體佈局包含 4 位元組的 Compress_Size、4 位元組的 Decompress_Size、一個 32 位元組的 Key 和一個 8 位元組的 Magic。Magic 驗證固定為明文字串
"ASHPCK\x01\x00"
[1]
。
2.4. Loader 變體 4
最新觀察到的 Loader 變體採用 32 位元組的設定,包含 4 位元組的 Compress_Size、4 位元組的 Decompress_Size、一個 16 位元組的 Key 和一個 8 位元組的 Magic。它引入了高強度的 ChaCha20 串流加密演算法進行加密,同時保留 LZ4 進行解壓縮。Magic 驗證固定為明文字串
"iEMPK\x02\x00\x00"
[1]
。
| 階段 | 設定大小 | 解密演算法 | 解壓縮演算法 | Magic 驗證特徵 |
|---|---|---|---|---|
| Loader 變體 1 | 16 位元組 | LCG + XOR | LZ4 | 動態驗證 (ROL4 + XOR) |
| Loader 變體 2 | 33 位元組 | Xoshiro128 + XOR | BLZ | 引入動態常數 |
| Loader 變體 3 | 48 位元組 | 標準 XOR | LZ4 |
固定明文字串
"ASHPCK\x01\x00"
|
| Loader 變體 4 | 32 位元組 | ChaCha20 | LZ4 |
固定明文字串
"iEMPK\x02\x00\x00"
|
3. Core 階段演進
RustDuck 的 Core 模組展現了顯著的工程複雜度,特別是其採用 Rust 程式語言這點。這種複雜性體現在其金鑰推導、反分析和通訊協定中 [1] 。
3.1. 金鑰生成與加密演算法
RustDuck 使用 HKDF-SHA256 演算法進行金鑰推導,利用兩個主要來源:
- 使用 UTC 時間的動態金鑰: 金鑰每 10 分鐘動態更新一次,與時鐘同步,以抵擋重放攻擊(Replay Attack)和長期流量稽核。
- 非對稱金鑰交換: 使用 Curve25519(Noise_IK_25519)架構來達成前向保密(Forward Secrecy) [1] 。
對稱加密/解密演算法已經演變為兩個不同的分支:
- 分支 A: 持續使用置換(Permutation transformed)後的 Ascon128 輕量級加密演算法。
- 分支 B: 採用混合加密機制,在 handshake 階段使用 ChaCha20-Poly1305,在符合 handshake 要求後切換為 AES-GCM [1] 。
4. 反除錯與環境檢查
為了躲避自動化沙箱分析和動態除錯的偵測,RustDuck Core 模組整合了一個動態權重評分機制。該系統在執行期間執行各種環境檢查,如果累積的風險分數超過預定義的 threshold,惡意軟體會自我終止並清除其蹤跡 [1] 。
| 偵測技術 | 風險權重 | 偵測原理與應對邏輯 |
|---|---|---|
| 分析工具檢查 | 100 |
掃描行程清單,尋找封包擷取(
wireshark
、
tcpdump
)和逆向工程工具(
gdb
、
ida
、
frida
、
x64dbg
)。
|
| 除錯檢查 | 100 |
讀取
/proc/self/status
並檢查
TracerPid
是否不為 0。
|
| 函式庫檢查 | 100 |
解析
/proc/self/maps
以尋找注入/除錯函式庫(
frida
、
asan
、
ubsan
、
libdl-inject
)。
|
| SHA256 Checksum | 100 | 「逐一檢查 VBox、VMware、Parallels 的特定 OUI 前綴 MAC 位址。 |
| 蜜罐檢查 | 50 | 在關鍵系統路徑中檢查蜜罐特徵檔案(例如 Cowrie、Dionaea)。 |
| 環境變數檢查 | 40 |
檢查環境變數是否包含敏感關鍵字(
sandbox
、
malware
、
virus
、
sample
)。
|
| 網路黑洞檢查 | 35 |
非同步連線到
192.0.2.1
;如果連線迅速成功,表示身處模擬環境的沙箱。
|
| 時間跳躍檢查 | 30 |
比較
usleep
前後的系統時間和單調時間(monotonic time),以偵測時間加速或斷點暫停。
|
| 硬體檢查 | 25 |
讀取 DMI 和 SCSI 設備資訊,尋找虛擬化關鍵字(
virtualbox
、
vbox
、
bochs
)。
|
| 虛擬機 MAC 檢查 | 20 | 遍歷 MAC 位址,尋找 VBox、VMware、Parallels 的特定 OUI 前綴。 |
| PID 密度檢查 | 10 | 檢查系統總行程數是否少於 5,以過濾極簡主義的模擬器環境。 |
4.1. 關鍵反除錯程式碼實作
以下 C 程式碼片段說明了 RustDuck 所採用的一些反除錯技術 [1] :
時間跳躍檢查
此函式比較系統時間和單調時間,以偵測可能表示沙箱環境或除錯器暫停執行的異常狀況。
- // 1. Time Travel Check: Dual clock source cross verification
- int check_timing_safetly() {
- struct timeval tv1, tv2;
- struct timespec ts1, ts2;
- gettimeofday(&tv1, NULL);
- clock_gettime(CLOCK_MONOTONIC, &ts1);
- usleep(500000); // deliberately suspend for 0.5 seconds
- gettimeofday(&tv2, NULL);
- clock_gettime(CLOCK_MONOTONIC, &ts2);
- long v2 = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000;
- long v3 = (ts2.tv_sec - ts1.tv_sec) * 1000 + (ts2.tv_nsec - ts1.tv_nsec) / 1000000;
- // Must actually sleep for more than 300ms, and the system error between the two clock sources must be within 1000ms
- if (v2 > 299 && v3 > 299 && abs(v3 - v2) <= 1000) {
- return 1; // Environment is normal
- }
- return 0; // Time anomaly: Possibly fast-forwarded by a sandbox, or halted by a reverse-engineering breakpoint
- }
網路黑洞檢查
此函式嘗試連接到一個保留的測試 IP 位址(
192.0.2.1
),該位址正常情況下應該是無法連線的。如果快速連線成功,則表示身處一個模擬網際網路連線的欺騙性沙箱環境。
- // 2. Network Blackhole Check: Network blackhole/sandbox blind connection detection
- int check_network_blackhole() {
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd < 0) return 0;
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
- struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(80) };
- addr.sin_addr.s_addr = inet_addr("192.0.2.1"); // RFC 5737 test reserved IP (normally absolutely unreachable)
- connect(fd, (struct sockaddr *)&addr, sizeof(addr));
- fd_set writeset;
- FD_ZERO(&writeset);
- FD_SET(fd, &writeset);
- struct timeval tv = { .tv_sec = 0, .tv_usec = 500000 }; // asynchronous wait for 0.5 seconds
- int res = select(fd + 1, NULL, &writeset, NULL, &tv);
- close(fd);
- // If timeout and not writable, the IP matches the expected "blackhole" state (passes check)
- if (res <= 0 || !FD_ISSET(fd, &writeset)) {
- return 1;
- }
- return 0; // Connection succeeded quickly, indicating a deceptive sandbox
- }
4.2. 反除錯檢查順序
下方序列圖說明了 RustDuck 可能執行其反除錯和環境檢查的簡化流程,並根據累積的風險分數決定是正常執行還是自我終止。
5. 與其他供應鏈攻擊的比較分析
雖然 RustDuck 呈現出獨特的特徵,但其操作策略與其他複雜的惡意軟體活動有共同點,特別是那些針對供應鏈的活動。例如,同樣以 Rust 編寫的 SniperBot 惡意軟體,採用聲譽投毒和剪貼簿劫持來竊取加密貨幣,顯示出類似的對金融利用和閃避技術的關注 [2] 。Rust 在 RustDuck 和 SniperBot 中的使用,凸顯了這種語言對於惡意軟體開發者日益增長的吸引力,因為其性能和安全性特性可能會增加分析難度。
另一個相關的比較是 TrapDoor 攻擊活動,它利用 npm、PyPI 和 Crates.io 中的原生執行機制來竊取 SSH 金鑰和區塊鏈錢包設定等認證 [3] 。雖然 TrapDoor 專注於供應鏈入侵以竊取認證,但其利用平台特定功能進行初始存取和持久化的底層原則,與 RustDuck 的多階段方法相呼應。TrapDoor 活動也展示了進階的持久化和傳播模組,特別是在其 npm 樣本中,旨在跨專案和主機進行二次傳播 [3] 。
此外,在針對邊緣路由器的攻擊中觀察到的 Linux 後門植入程式(
router.elf
),它使用 DNS over HTTPS(DoH)進行 C2 通訊,並使用 iptables 進行 DNS 劫持,說明了對隱蔽的命令與控制以及網路層級操縱的共同重視
[4]
。
router.elf
所採用的反分析技術,如靜態連結、符號剝離和字串混淆,與 RustDuck Core 模組中看到的複雜閃避策略如出一轍。這兩個惡意軟體家族都展現了高度的運作安全性和對如何將惡意流量與正常網路活動混合的理解。
這些比較揭示了現代惡意軟體開發的趨勢:
- 使用如 Rust 這類高性能、記憶體安全的語言。
- 採用多階段架構以實現隱蔽性和韌性。
- 實作複雜的反分析和閃避技術。
- 利用平台特定功能進行初始入侵和持久化。
- 透過認證竊取和網路控制來專注於經濟利益或持續存取。
6. 結論
RustDuck 代表了僵屍網路能力的重大演進,其特點在於轉向 Rust、強健的雙階段架構以及先進的反分析機制。對其 Loader 變體的詳細檢視揭示了持續增強混淆和加密的努力,而 Core 模組則展示了複雜的金鑰生成、加密,以及用於環境偵測的精密動態權重評分系統。該惡意軟體適應和規避傳統安全措施的能力,加上其跨平台特性,對各種數位基礎設施構成了重大威脅。
與其他當代惡意軟體(如 SniperBot、TrapDoor 和 Linux 邊緣路由器後門)的比較分析,強調了威脅態勢的更廣泛轉變。現代的攻擊者越來越多地採用先進的程式語言、多面向的攻擊鏈和高度閃避的技術來達成其目標,無論是經濟剝削還是持續的網路存取。對這類威脅的有效防禦,需要一種主動和多層次的安全方法,超越靜態指標,轉向擁抱行為分析、持續監控,以及實施強健的安全框架,以應對像 RustDuck 這類複雜僵屍網路的不斷演變的戰術。