Key findings
- NtHandleCallback.exe 是合法簽章的應用程式,作為白加黑側載宿主;整條載入鏈在磁碟上看起來像是合法程式在執行合法 DLL。
- 惡意 log.dll 作為載入器建立三條並行執行緒:T1 解密並在記憶體執行 ValleyRAT、T2 部署兩支反鑑識核心驅動、T3 維持 Defender 排除路徑。
- Server.log 是 RC4 加密的 ValleyRAT 核心,以金鑰 ??Bid@locale@std 解出「上线模块.dll」後以記憶體映射執行,本體從不落地。
- ValleyRAT 用兩個 Registry 值作為持久化容器:HKCU\Console\IpDate 可動態覆蓋 C2 設定,HKCU\Console\0 下的 32-hex 值儲存 plugin 二進位;只刪檔或封 C2 都清不乾淨。
- 邏輯層仍沿用 Gh0st RAT 的 first-byte token 加 CManager 派發設計,但網路層已拿掉 Gh0st magic 與 zlib,改用 14-byte 自訂 header 並加 UDP/ARQ 備援,規避傳統 Gh0st 偵測規則。

前言
在前一篇中,我們看到銀狐透過 men.exe 完成環境鋪設:落地元件、BYOVD 殺防毒、修改 DACL 防刪除,以及安排登入觸發。本篇要解說的是舞台搭好後,真正的 ValleyRAT 如何被載入、上線、維持與保護。本次分析所用樣本:

本文僅供防禦研究、事件應變、威脅狩獵與教育用途。文中提及之樣本與工具可能具風險,請僅在隔離、可還原且不連接生產網路之環境中測試。本文不鼓勵、協助或默許任何未經授權之行為;文中所提及之第三方平台與產品名稱僅作技術描述之用。
NtHandleCallback.exe:DLL 側載宿主
NtHandleCallback.exe 本身不是惡意程式。它是一支 PE32 應用,2020-03-11 編譯,由 Hangzhou Shunwang Technology Co.,Ltd(杭州順網科技)以 DigiCert 簽章。順網是中國一家做網咖管理軟體與遊戲雲端服務的公司,這張憑證在 2023 年後大量流入中文犯罪生態,被許多惡意程式拿來當簽章。不過這次攻擊者沒有破解簽章,只是把這支合法程式直接複製一份過來,當作側載 log.dll 的宿主。
這支 EXE 簽章合法、有 GUI 資源段(.rsrc 約 43 KB)、啟用了 Control Flow Guard,就是支商業應用,沒什麼好查的。它真正成為攻擊鏈的線索在 Import Table 裡:

注意它 IAT 中的第三方函式 log.dll!GenericLogImpl。Windows 的 DLL 搜尋順序會把應用程式目錄擺在系統目錄之前,所以只要 log.dll 跟宿主放在同一資料夾,啟動時 PE loader 就會把它映射進行程、解析匯入並呼叫 GenericLogImpl。從這裡開始,後續流程就是 log.dll 的邏輯,與這支合法 EXE 已經沒什麼關係了。
log.dll:三執行緒編排器
log.dll 是一支 PE32,共 5 個 section,ImageBase 0x10000000,大小約 176 KB。它的匯出表只有一個符號:

惡意行為都集中在 GenericLogImpl。這個函式的反組譯結果容易理解:

三條執行緒並行,主呼叫端在三個都 join 之前不會返回。這種設計讓 NtHandleCallback.exe 看起來只是卡在一個日誌輸出函式裡,而背景早已完成三件事:
以下分別拆解這三條執行緒,不過大部分篇幅會集中在 T1 的 ValleyRAT 分析。三條執行緒的進入點與職責:
| 執行緒 | 進入點 | 職責 |
|---|---|---|
| T1 | StartAddress @ 0x10003EE0 → sub_10003BB0 | 解密並執行 ValleyRAT 本體 |
| T2 | sub_10003DA0 | 部署惡意核心驅動用以反鑑識 |
| T3 | sub_10003EF0 | 維持 Defender 排除路徑 |
T1:Server.log 解密與 ValleyRAT 上線
這是本篇的主戲。我們會先拆解 T1 怎麼把 Server.log 解成 ValleyRAT 的 PE,接著深入解密後的 PE 本體,包括 config 的藏匿手法、C2 啟動路徑,以及與 Gh0st RAT 的關係。
RC4 解密與記憶體載入
sub_10003BB0(T1 函數)的目的是將被加密的 ValleyRAT 核心檔案 Server.log 解密,並對該記憶體位置執行:
strcpy(local_v3, "??Bid@locale@std"); // RC4 key, 16 bytes
fp = fopen("Server.log", "rb"); // 同目錄的密文檔
size = ftell(fp);
buf = malloc(size);
fread(buf, 1, size, fp);
rc4_decrypt(buf, size, local_v3, 16); // FUN_10004CD0 — 標準 RC4
pe = map_pe(buf); // FUN_100053D0 — 自建 PE loader
entry = find_export(pe, "NtHandleCallback"); // FUN_10005200
if (entry) entry(); // 直接呼叫匯出
整條鏈沒有檔案落地,解密完會直接映射到記憶體、解析匯出並跳過去執行。ValleyRAT 的實體從不以檔案形式存在於磁碟。雖然真正執行時檔案從不落地,逆向時仍可直接用密碼把密文解出,丟進 CyberChef 以 ??Bid@locale@std 用 RC4 還原分析(這個密碼在同系列下用了快五個月,反倒是 C2 換得更頻繁):

前 4 bytes 為 4D 5A 90 00(MZ...),基本可確定是 PE 結構;丟到 PEBear 看到匯出中包含 NtHandleCallback,接下來存為 valleyrat.dll 分析。
ValleyRAT 上線模組
把 Server.log 以 RC4 解密後,得到一支 PE32 DLL,內部名稱寫著「上线模块.dll」,匯出函式中也包含前面 log.dll 會尋找並呼叫的 NtHandleCallback。這代表 Server.log 內部藏著 ValleyRAT 的上線模組,前面的 T1 流程只是把它從密文中解出、映射到記憶體,然後轉交執行。

這裡的「上線模組」可理解成 ValleyRAT 的控制入口。它會先讀取通訊設定、連上 C2,接著依 C2 指令載入後續 plugin。因為真正啟用的能力由 C2 決定,同一套 ValleyRAT 在不同事件中可能呈現不同樣貌,有些事件只看到基礎連線,有些則進一步出現截圖、鍵盤側錄、檔案操作、遠端 shell 或其他 plugin 行為。
ValleyRAT/Winos 4.0 系列的核心仍能看到 Gh0st RAT 的影子。邏輯層保留了以 CManager 為基礎的類別架構,以及依 command token 分派功能的設計;網路層則已明顯改造,原本 Gh0st 常見的 magic 與 zlib 壓縮特徵被拿掉,改用自訂 header、TCP 通道,以及額外的 UDP/ARQ 備援設計。這讓它保留 Gh0st 的操作模型,同時避開一部分針對傳統 Gh0st 協定的偵測規則。
解密後的 PE 基本資訊:
| 項目 | 內容 |
|---|---|
| Type | PE32 DLL(i386, 32-bit) |
| Size | 111104 (108 Kb) |
| MD5 | 016d12cd1f6c68db98fcdde6075e9b71 |
| SHA256 | 5decc64bc4ed4d6ffd3f59be2e839fe5cc70eaa3f07191d77ac241d028e1c6f0 |
透過 RTTI CLASS 可以看到一些有趣的東西:
.?AVCManager@@ ← CManager(基礎管理類)
.?AVCKernelManager@@ ← CKernelManager(核心管理)
.?AVISocketBase@@ ← ISocketBase(socket 抽象基底)
.?AVCTcpSocket@@ ← CTcpSocket
.?AVCUdpSocket@@ ← CUdpSocket
.?AV?$CArqSessionT@VCUdpSocket@@V1@@@ ← CArqSession<CUdpSocket>(ARQ over UDP)
.?AVCBuffer@@ ← CBuffer
.?AVCAtlException@ATL@@ ← ATL 例外
這些名稱大致分離了三層:CManager/CKernelManager 是控制邏輯與命令分派核心;CTcpSocket/CUdpSocket/ISocketBase 是網路抽象層;CArqSessionT<CUdpSocket> 則暗示它在 UDP 上額外實作可靠傳輸機制。這個 UDP/ARQ 類別在原生 Gh0st RAT 中並不存在,較符合 Winos 4.0 系列在網路層改造後的特徵。

從偵測角度來看,單純針對傳統 Gh0st magic 或固定 TCP 行為寫規則,可能漏掉這類已改造網路層的變體。更值得觀察的特徵包括類別架構、14-byte header、自訂握手、Registry plugin 容器,以及 tracerpt.exe 注入後的外連行為。
配置參數讀取與儲存
進入執行後,ValleyRAT 會先初始化通訊設定。樣本內部硬編碼了一串 UTF-16 字串,但整串被反轉;初始化時它會把字串翻回來,再解析成以 | 分隔、以 key:value 表示的設定欄位。這種混淆只是把字元順序反轉,分析難度不高,但自 2025 年至 2026 年 4 月,銀狐使用的所有 ValleyRAT 都以這種方式儲存 C2 資訊,代表這種方式雖易分析,但透過快速的 C2 變換與多階段投放鏈,不足以影響其投放行為。本次樣本解出的設定:
|p1:ydbao8[.]cyou|o1:9000|t1:1|p2:|o2:|t2:1|p3:|o3:|t3:1|dd:1|cl:1
|fz:LINE|bb:1.0|bz:2025. 8.31|jp:1|bh:0|ll:0|dl:1|sh:1|kl:1|bd:0|

最值得注意的是這組設定還能被 Registry 覆蓋。初始化時 ValleyRAT 會讀取 HKCU\Console\IpDate;若該值存在且長度符合條件,樣本就會用其中內容取代硬編碼設定。C2 因此能在第一次成功連線後下發新設定寫入該值,下一次 RAT 啟動即改用 Registry 裡的新目標。
這點對事件應變很重要:封鎖該域名只能處理樣本內建的當下 C2,如果 HKCU\Console\IpDate 已寫入更新後的基礎設施,RAT 重啟後仍可能恢復連線。C2 IOC 是時間點快照,Registry 中的動態設定則反映端點上殘留的攻擊狀態。根據經驗,攻擊者會在首次成功連線後立即更新 C2 位置以建立分析斷點。

Registry plugin 容器:後段模組
除了 C2 設定外,ValleyRAT 還使用 HKCU\Console 作為 plugin 的本機儲存空間,這是本次樣本最關鍵的設計之一。我們觀察到另一個 Registry value:
HKCU\Console\0\d33f351a4aeea5e608853d1a56661059
注意路徑是 Console\0 這個子鍵,不是 Console 本身;0 這個一字元子鍵名稱本身可能也算反取證設計,編輯器一掃而過容易誤判為占位。value name 是 32 字元 hex,看起來像 MD5 或自動產生的識別值,容易讓人工檢查誤以為只是普通雜湊,但實際上它是 plugin 二進位的儲存容器。
首次部署時,C2 會推送一段 plugin 設定與 payload,ValleyRAT 收到後把「config + PE」一起寫入上述 value;之後即使 RAT 重啟,也不需重新下載即可重新載入執行。這個設計帶來的效果不止於「存在 Registry 而非檔案系統」:
- plugin 不以檔案形式出現在磁碟上,對只依賴檔案掃描或新建執行檔監控的防線,可見度會下降。
- 攻擊者降低了對 C2 即時可用性的依賴,只要 Registry 裡仍保存 plugin,RAT 重啟後就有機會從本機重放後段能力。
- plugin 可能帶有受害主機綁定邏輯,樣本讀回 plugin 後會做 hostname 或 UID 相關比對,不符則向 C2 回報異常,暗示 plugin 具 per-victim 客製化能力。
事件回應時,若只刪掉 NtHandleCallback.exe、log.dll 或封鎖目前 C2,仍可能留下這個 Registry plugin 容器。因此 HKCU\Console 區域是清除與蒐證時必須優先檢查的位置。
C2 連線:多次重試與備援機制
ValleyRAT 的參數預設有多個槽位,支援 TCP 與 KCP(ARQ over UDP)連線。本次樣本主要 C2 是 ydbao8[.]cyou 的 9000/tcp。主要 C2 失敗時樣本會切換到備援組,失敗次數持續累積還會升級嘗試第三組,以對抗單一網域封鎖、sinkhole、分析環境阻斷或基礎設施短暫不可用。

連線成功後,樣本送出非常短的握手資料,接著進入接收迴圈,後續封包交給 CKernelManager 處理。從這一刻起,CKernelManager 成為受害主機上的控制核心,依 C2 指令決定要忽略 heartbeat、安裝 plugin、讀回 Registry plugin,或更新本機設定。技術上這裡仍看得到 Gh0st RAT 的命令分派精神,但外層協定已被重寫,樣本使用自訂 14-byte header,取代原始 Gh0st 常見的 magic 與壓縮格式。
Plugin 部署
可以把 CKernelManager 理解成上線模組的最小派發器:它不直接提供完整 RAT 功能,而是依 C2 封包決定三件事,忽略心跳、首次安裝 plugin,或從 Registry 喚醒既有 plugin。真正的後控能力不在這層,而是在後續被注入到 tracerpt.exe 的主控模組中。主派發器(0x100054C0)依封包第一個 byte 與封包總長度這兩個簡單訊號走三條路徑:
路徑一:心跳,當第一個 byte 為 0xC9 時視為心跳,直接 return。這個 token 是 ValleyRAT 與 Gh0st 在派發層上的明顯差異:Gh0st 心跳 token 是 0x01,這裡刻意改成 0xC9,以規避「first-byte == 0x01」為基礎的 Gh0st 偵測規則。
路徑二:首次部署,當封包大小不等於 101 時走首次部署。封包前段(pkt+1 起 0xA44 = 2628 bytes)是 plugin config,後段是 payload PE。先把 payload PE 配置到記憶體並 memcpy 進去,再把同一份「config + PE」串接後以 RegSetValueExW 寫入 HKCU\Console\0\d33f351a4aeea5e608853d1a56661059,寫完立刻 _beginthreadex(sub_100052B0) 啟動注入器執行緒,後續的 needle 補位、寫入 HKLM\SOFTWARE\IpDates_info、tracerpt.exe Process Hollowing 都由這條執行緒接手。

路徑三:喚醒重放,當封包大小剛好等於 101 時走此路徑(RAT 重啟或 C2 主動觸發甦醒)。它會開啟 HKCU\Console\0,把先前保存的 config + PE 讀回還原到記憶體,接著做主機指紋驗證:比對成功就進入注入流程把 plugin 灌回 tracerpt.exe;比對失敗(表示這份 plugin 是從別台機器搬來的)則把回應封包前綴 0x05 加上完整 config 送回 C2,讓伺服端知道這台機器拒收。
三條路徑共用同一個 plugin 暫存區與同一個注入器入口(sub_100052B0);CKernelManager 自身完全不接 keylog/shell/螢幕擷取一類功能指令,那些都是 plugin 跑起來後在 tracerpt.exe 行程內由 plugin 自己的派發器處理。
Plugin 注入與啟動:自我修補與 tracerpt.exe Hollowing
在真正執行 plugin 前,ValleyRAT 會把目前的 config 寫回 plugin。樣本會在 plugin 記憶體中搜尋一段固定標記 ihziepulgned,反轉後是 dengluplugin(「登錄 plugin」的拼音)。找到標記後,ValleyRAT 會把目前設定區塊覆寫到 plugin 中,這是一種 plugin self-patch 機制:plugin 本體不用硬編碼完整 C2 與受害主機設定,載入前由上線模組注入當前 config。
接著樣本依設定中的 kl 旗標(Server 端以「傀儡進程」作為可勾選項目)選擇執行模式。本次樣本 kl 為 1 走傀儡模式:建立暫停狀態的 tracerpt.exe,將 RAT body 寫入該程序,再修改主執行緒 context,使 payload 從 tracerpt.exe 內部開始執行,典型的 process hollowing。tracerpt.exe 是 Windows 內建的 ETW trace 報告工具、具 Microsoft 簽章,攻擊者選它作為 hollow target,是為了讓端點上出現一個有簽章、位於系統路徑、名稱合理的程序來承接 RAT 行為。
樣本中還有 watchdog 設計:定期檢查被 hollow 的 tracerpt.exe 是否仍存活,如果程序被 EDR 或人工終止,樣本會重新建立並注入新的 tracerpt.exe。單純殺掉這個 process 不能終止感染,反而會觸發它重建通訊程序。若 kl 為 0,樣本則走就地執行模式,在目前 NtHandleCallback 行程內執行 plugin;這種模式隱蔽性較低但行為更少,長期觀察下攻擊者有時會選就地模式,但數量明顯偏少。
Plugin 行為
取得並分析攻擊者投放的 plugin 後,發現一個命名為 plugin DDDD 的插件被載入。這個 plugin 即為 ValleyRAT 功能核心模組,在 Server 端通常被命名為「主控模块」,提供 27 個命令 token,包括 keylog、screenshot、shell、檔案、關機重啟、EventLog 抹除等功能。
我們在感染主機的記憶體與 Registry 各取得一份 plugin 副本:記憶體版本由 HollowsHunter 從受感染行程的 unbacked 區段挖出,Registry 版本則直接從 HKCU\Console\0 之下含 plugin 二進位的 REG_BINARY 取出。兩份共通的 530,944 bytes 中只有 74 bytes 不同,差異全部集中在 plugin 的 .data 區段,內容是 plugin 跑起來後寫入的 victim runtime 狀態(疑似工作目錄或 session token)。因此可理解為同一支 PE,一個是部署當下的乾淨樣本,另一個是已執行過、攜帶受害主機指紋的活體樣本。
打開這份 plugin 的 RTTI 字串可看到 CLoginManager、CManager、CTcpSocket、ISocketBase,但 CKernelManager 缺席。推測 plugin 不是上線模組的延伸,而是一支繼承自 CManager、與上線模組平行的另一個 manager 類別。進一步看它的工作迴圈會發現它有自己的 socket 建構(TCP + UDP/ARQ 雙通道)、自己的 200-cycle p1/p2/p3 C2 failover、自己的 Registry 持久化(這次的 key 是 HKCU\Console\Ipcial,與上線模組的 IpDate 並列),甚至連對 C2 的握手與 recv loop 都是自己重新實作的。從架構看,這支 plugin 比較像「主控模塊」,是一支獨立、功能完整的次階段 RAT,而不是傳統上被後續載入的能力 plugin。
把 CLoginManager 的 vtable 第一個 slot 拉出來,看到的是一張漂亮的 switch table 派發器:
movzx eax, byte ptr [esi] ; 取封包第一個 byte 作為 token
sub eax, 0x14 ; 偏移到 0
cmp eax, 0xb6 ; 範圍檢查
ja default_handler
movzx eax, byte [eax+0x100262a8] ; 經 index 表轉為 case slot
jmp dword [eax*4+0x10026238] ; 透過 jump 表分派

token 接受範圍是 [0x14, 0xCA],jump 表共 28 個 slot(27 個有效命令 + 1 個 default),Gh0st 的命令分派也是這種寫法。對照前一節 CKernelManager 只有 3 條 path 的派發邏輯,plugin 的指令派發器徹底回到 Gh0st 風格的全功能設計。有意思的是:ValleyRAT 在上線模組那層已把 Gh0st 原始的 5-byte magic 與 zlib 拿掉,換上 14-byte 自訂 header 加通訊雙通道(推測為了加備援連線、順便繞過 WAF 針對 Gh0st 撰寫的舊規則);但在真正執行命令這層,派發機制與類別架構仍完整保留,且加入了 BCrypt AES 等現代化模組,所以這條 plugin 算是 Gh0st 架構的高度改裝。
實務上這 27 個命令可歸併成 8 個功能類別,每類底下可能對應 1~3 個 token 變體:

也就是說,這支 plugin 涵蓋了一支現代 RAT 該有的所有基本能力,從偵察、操控、持久化到事後清理都有。攻擊者拿到一台機器後,任何事情都不需再下發新 plugin,本身就夠用。其中我認為較特別的五個命令:

0x22 ClearEventLogs 是事件應變上特別麻煩的一條:它把三個 wide string Application/Security/System 依序傳給 OpenEventLogW 然後立刻 ClearEventLogW,一次性把端點上最常被檢視的三個事件來源全部清空。IR 團隊事後看到的會是一個乾淨的 EventLog,沒有登入紀錄、沒有服務啟動紀錄、沒有任何系統錯誤訊息。要對抗這條命令,可用 Sysmon 把關鍵事件即時轉到中央 SIEM,或啟用 Windows Event Forwarding,即使本機 log 被清空,IR 仍能從遠端拷貝看到完整時間軸。
T2:反鑑識核心驅動部署與 PID 保護
這條執行緒的目的是啟用惡意核心驅動,並將 T1 執行的 ValleyRAT 等工具列入保護對象,防止鑑識工具分析。它依序完成:
- 等待
NtHandleCallback.exe出現 PID - 部署
Cndom6.sys,建立 service,並開啟\\.\Cndom6驅動位置(為 IOCTL 註冊) - 向 Cndom6 下 IOCTL 註冊 loader 群組的受保護 PID
- 等待
tracerpt.exe出現 PID - 部署
XiaoH.sys,建立 service - 向 Cndom6 下 IOCTL 註冊 tracerpt 群組的受保護 PID
- 檢查
NVIDIA.exe是否在跑,若沒有就WinExec啟動 - 向 Cndom6 下 IOCTL 註冊 NVIDIA 群組的受保護 PID
三個被保護的群組對應攻擊鏈上的三個關鍵角色:NtHandleCallback.exe 是本篇的白加黑宿主,tracerpt.exe 是 ValleyRAT 本體注入的傀儡行程,NVIDIA.exe 則是 Part 2 中透過 BYOVD 殺防毒的元件。
從 log.dll 內部解出的兩支驅動
追蹤寫檔函式的呼叫點,可定位到嵌在 log.dll 內部的兩段二進位:
| 驅動 | RVA | File Offset | 大小 | 位元 |
|---|---|---|---|---|
Cndom6.sys | 0x23090 | 0x21290 | 23,616 bytes (0x5C40) | x86-64 (PE32+) |
XiaoH.sys | 0x28CD0 | 0x26ED0 | 10,808 bytes (0x2A38) | x86-64 (PE32+) |
兩段開頭都是標準 PE+ 檔案。log.dll 本身是 32-bit,但攜帶的是兩支 64-bit 驅動;這對 user-mode 載入不是問題,服務只要走 CreateService 加 StartService,載入就會由系統完成,隨後再把驅動檔案刪除。分析上只需對其 dump 即可取得驅動檔。這些驅動如何透過核心機制完成反鑑識,將於下一章詳述。
Cndom6 IOCTL 介面
log.dll T2 在本次部署實際只用了四個 IOCTL(0x222180、0x22218C、0x221E60、0x222190),但完整反向 Cndom6 後可看到它對外暴露六個 IOCTL,外加一條總旗標:

從呼叫順序可反推 Cndom6 的對外設計邏輯:攻擊者把 PID 保護需求拆成多個獨立 IOCTL,每個對應不同的核心 hook 或不同的 PID 清單。另一個值得注意的反取證設計是,Cndom6 在載入後會透過解除自身映像分頁區段的引用,把自己的 .sys 檔案從磁碟刪掉,使 log.dll T2 部署這支驅動後,在端點上找不到對應的 Cndom6.sys 檔案。
XiaoH IOCTL 介面
XiaoH 與 Cndom6 同樣提供 IOCTL 介面:Cndom6 負責隱藏與保護 PID(讓 process 看不見也殺不掉),XiaoH 負責隱藏網路連線(讓 netstat/EDR 看不到 C2 連線)。兩支拼起來形成完整的 Ring 0 反鑑識鏈。XiaoH 對外暴露四個 IOCTL:

其中 hide-list 與 whitelist 是互補的兩個容器:

「替換成假連線」是 XiaoH 比一般 rootkit 更特別的地方:它把目標連線改寫成結構合法的假連線,把目標 IP 換成 1.2.3.4、port 換成 0x3930(14640)的占位值,讓查詢時變成數量正確但內容沒有 C2 的連線清單。另一個細節是 XiaoH 的 0x221E60 IOCTL code 與 Cndom6 的 0x221E60(保護 tracerpt 群組)相同但對應不同 device namespace,因此 T2 呼叫端必須打開對應的 \\.\XiaoH 或 \\.\Cndom6,IOCTL 才會送到正確的驅動。
T3:Defender 排除路徑維持
T3 的程式碼很短,核心就是一個 PowerShell 迴圈:
while (!is_terminate_signal()) {
run_powershell(
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -Command "
"\"if ((Get-MpPreference).ExclusionPath -notcontains "
"'C:\\\\Users\\\\Public\\\\Pictures') "
"{ Add-MpPreference -ExclusionPath 'C:\\\\Users\\\\Public\\\\Pictures' }\""
);
Sleep(500);
if (is_terminate_signal()) break;
Sleep(1000);
}
目的很簡單:即使有人手動把 Defender 排除清單裡的 C:\Users\Public\Pictures 拿掉,這條迴圈會在 500 到 1000 毫秒內補回去。指令裡的 if ... -notcontains 是冪等防呆,重複執行不會產生多餘的系統事件。
不過有個有趣的狀況:如果 Defender 服務已被 NVIDIA.exe 搭配 NSecKrnl 直接殺掉,Get-MpPreference 會失敗,這條迴圈就變成背景空轉,佔用一條執行緒但實際什麼也沒做。其實 T3 通常沒實際用途,只在 Defender 還活著時才有意義,回想 Part 1 的 Inno Setup 安裝腳本已把整個 C 槽加入排除清單,那為何還要再做一次?推測是這工具在其他投放鏈也被利用,或只是作為雙重保險。
技術統整
將 NtHandleCallback.exe、log.dll、ValleyRAT 上線模組與後段 plugin 行為解析為多個技術,逐項與 ATT&CK 的對照見文末的 MITRE ATT&CK mapping 表。其中 plugin command handler 代表樣本具備的遠控能力,不一定表示所有命令都已在本次事件中被實際觸發。

結語
回頭看這條鏈,NtHandleCallback.exe 本身沒有太多戲份,更像一個被挑中的合法外殼。真正的執行者是 log.dll!GenericLogImpl:一個很短的函數,同時拉起三條線,T1 解密 Server.log 並喚醒 ValleyRAT、上線後取得 plugin;T2 部署核心驅動保護關鍵 process;T3 反覆補回 Defender exclusion。這也是這條鏈容易被低估的地方:入口看起來普通,後面卻已經把載入、持久化與反鑑識分開處理。
這次最特別的是 HKCU\Console 的相關操作:IpDate 保存 C2 config,Console\0 底下那串 32 字元 hex value 則保存 plugin 本體。即使刪掉 NtHandleCallback.exe、log.dll,再封掉硬編碼 C2,只要 Registry 裡的 config 與 plugin 還在,這台機器就不能算乾淨。
解出後段 plugin 後,ValleyRAT 與 Gh0st 的關係也更清楚:外層上線模組已拿掉 Gh0st magic 與 zlib、改成自訂 14-byte header 並加 UDP/ARQ 備援;但真正執行命令的 plugin 裡,仍能看到 first-byte token、CManager、switch table 這些 Gh0st-style 設計。它保留了 Gh0st 的控制習慣,然後把投放、通訊與存活方式重新包裝了一次。
Part 3 先停在 user-mode 這條線。下一篇會把視角往下拉到 T2 部署的 Cndom6.sys 與 XiaoH.sys,看惡意驅動如何在 kernel 裡做 PID 保護、連線隱藏與反鑑識。
樣本與參考
- 原文(Medium,OIS):《深入銀狐 Part 3:從 DLL 側載到 ValleyRAT,完整拆解記憶體載入與反鑑識鏈》
- 前一階段:深入銀狐 Part 2:失效工程:EDR 消失術
- Gh0st RAT 命令分派參考:https://github.com/sin5678/gh0st/blob/master/Server/svchost/common/KernelManager.cpp
- MITRE ATT&CK — 技術對照依據
MITRE ATT&CK mapping
| Tactic | Technique | Procedure |
|---|---|---|
| Defense evasion | T1574.002 | NtHandleCallback.exe 為合法簽章宿主,透過 Import Table 側載同目錄的 log.dll!GenericLogImpl |
| Defense evasion | T1553.002 | 以合法簽章的第三方商業程式(杭州順網 DigiCert 簽章)作為側載宿主,降低對初始程序的警覺 |
| Defense evasion | T1036.005 | log.dll、Server.log、tracerpt.exe 等名稱與合法元件靠攏,工作目錄置於 C:\Users\Public\Pictures\WindowsData |
| Defense evasion | T1027 | 上線模組以 RC4 密文存於 Server.log,C2 config 以 UTF-16 反轉字串保存,plugin 以 REG_BINARY 藏於 HKCU\Console\0 |
| Defense evasion | T1027.009 | log.dll 內嵌 Cndom6.sys 與 XiaoH.sys 兩支 64-bit 驅動 |
| Defense evasion | T1140 | T1 以 RC4 金鑰 ??Bid@locale@std 解密 Server.log,還原出「上线模块.dll」 |
| Defense evasion | T1620 | 解密後的上線模組不落地,由 log.dll 於記憶體配置、映射 PE、解析匯出並轉交執行 |
| Command and control | T1105 | 連上 C2 後接收後段 plugin 並寫入 Registry;plugin 的 DownloadExec 類命令可再拉取任意 binary 落地執行 |
| Defense evasion | T1112 | 以 HKCU\Console\IpDate 覆寫 C2 config,以 HKCU\Console\0\d33f351a4aeea5e608853d1a56661059 保存 plugin 二進位 |
| Defense evasion | T1055.012 | kl 旗標啟用傀儡模式時,建立暫停的 tracerpt.exe,寫入 RAT body 後改主執行緒 context 使其自 tracerpt.exe 內執行 |
| Command and control | T1095 | 上線模組與 plugin 以自訂 14-byte header 的封包格式進行 C2 通訊,含 TCP 與 UDP/ARQ 備援 |
| Command and control | T1571 | 硬編碼主 C2 使用 ydbao8[.]cyou 的 9000/tcp 非標準埠 |
| Persistence | T1543.003 | T2 部署 Cndom6.sys 與 XiaoH.sys,建立並啟動 driver service 取得 Ring 0 能力 |
| Defense evasion | T1014 | Cndom6.sys 保護與隱藏 process/handle,XiaoH.sys 隱藏網路連線,構成核心層反鑑識鏈 |
| Defense evasion | T1562.001 | T3 反覆以 PowerShell 檢查並維持 Defender 對 C:\Users\Public\Pictures 的排除 |
| Execution | T1059.001 | 以 powershell.exe 隱藏視窗搭配 Get-MpPreference/Add-MpPreference 操作 Defender 設定 |
| Discovery | T1007 | 後段 plugin 具服務列舉能力,蒐集受害主機服務狀態 |
| Collection | T1056.001 | plugin 具鍵盤側錄 command handler,可啟動對應執行緒側錄輸入 |
| Collection | T1113 | plugin 具螢幕擷取能力,可由 C2 指令觸發 |
| Execution | T1059.003 | plugin 具後台命令執行(shell)能力,可由 C2 觸發 |
| Defense evasion | T1070.001 | plugin 的 0x22 ClearEventLogs 依序清空 Application、Security、System 事件記錄 |
| Impact | T1529 | plugin 具強制重啟、關機與登出能力 |
| Defense evasion | T1564 | 將惡意狀態分散到加密檔案、Registry value、被 hollow 的合法系統程序與核心 driver |
Indicators of compromise
| Type | Indicator | First seen | Last verified | Confidence | Status |
|---|---|---|---|---|---|
| Domain | ydbao8[.]cyouValleyRAT 主 C2(ydbao8[.]cyou 的 9000/tcp) | 2025-09 | 2026-05-14 | High | ACTIVE |
| SHA256 | 5decc64bc4ed4d6ffd3f59be2e839fe5cc70eaa3f07191d77ac241d028e1c6f0上线模块.dll — Server.log 以 RC4 解密後的 ValleyRAT 上線模組(記憶體載入、不落地) | 2025-09 | 2026-05-14 | High | — |
| MD5 | 016d12cd1f6c68db98fcdde6075e9b71上线模块.dll — 同上,ValleyRAT 上線模組(MD5) | 2025-09 | 2026-05-14 | High | — |
| Registry | HKCU\Console\IpDateC2 設定動態覆蓋點;C2 首次連線後可下發新設定寫入此值,RAT 重啟即改用新目標 | 2025-09 | 2026-05-14 | High | — |
| Registry | HKCU\Console\0\d33f351a4aeea5e608853d1a56661059plugin 二進位(config + PE)的 REG_BINARY 儲存容器,清除與蒐證須優先檢查 | 2025-09 | 2026-05-14 | High | — |
| Registry | HKCU\Console\Ipcial後段 plugin(主控模塊)自身的持久化鍵 | 2025-09 | 2026-05-14 | High | — |
| Registry | HKLM\SOFTWARE\IpDates_info注入器執行緒寫入的標記值 | 2025-09 | 2026-05-14 | Moderate | — |
| String | ??Bid@locale@stdServer.log 的 RC4 解密金鑰(同系列沿用近五個月) | 2025-09 | 2026-05-14 | High | — |
| String | ihziepulgnedplugin self-patch 標記(反轉為 dengluplugin);找到後覆寫當前 config | 2025-09 | 2026-05-14 | High | — |
| Path | C:\Users\Public\PicturesT3 反覆補回的 Windows Defender 排除路徑 | 2025-09 | 2026-05-14 | High | — |