信息盜取的隱性威脅:Rhadamanthys木馬無(wú)痕竊密
近期,火絨工程師在日常監(jiān)測(cè)安全動(dòng)態(tài)時(shí)發(fā)現(xiàn),Rhadamanthys 竊密木馬家族包含多種模塊。這些模塊采用自定義的 PE 結(jié)構(gòu),與正常的 PE 結(jié)構(gòu)相似,因此需要手動(dòng)構(gòu)造 PE 文件進(jìn)行分析。進(jìn)一步分析表明,該樣本會(huì)通過(guò)天堂之門注入到偽造父進(jìn)程創(chuàng)建的傀儡進(jìn)程中,隨后進(jìn)行殺軟檢測(cè)和反沙箱操作,且整個(gè)處理過(guò)程均在內(nèi)存中完成,無(wú)文件落地。最終,該木馬會(huì)下載竊密模塊,竊密模塊會(huì)竊取 Steam 登錄驗(yàn)證文件和 Chrome 瀏覽器數(shù)據(jù)庫(kù)文件。此外,它還會(huì)利用 Lua 腳本和 C# 動(dòng)態(tài)庫(kù)竊取加密貨幣錢包及密碼管理軟件中的秘鑰等敏感數(shù)據(jù)。目前,火絨安全產(chǎn)品已能夠?qū)υ摳`密木馬進(jìn)行有效攔截和查殺,建議廣大用戶及時(shí)更新病毒庫(kù),以防范潛在安全風(fēng)險(xiǎn)。
查殺圖
流程圖如下:
流程圖
該樣本基于AeroAdmin.exe(遠(yuǎn)程桌面控制軟件),通過(guò)篡改其___strncnt 函數(shù)的內(nèi)容,實(shí)現(xiàn)偽裝。
原 AeroAdmin 官網(wǎng)
因原文件被篡改,導(dǎo)致惡意文件的數(shù)字簽名失效。
原文件與惡意文件區(qū)別(右邊為惡意文件)
___strncnt 函數(shù)對(duì)比(右邊為惡意文件)
樣本分析
在中期階段,樣本會(huì)執(zhí)行一系列對(duì)抗操作,例如反沙箱、反虛擬機(jī)和反調(diào)試等。之后,樣本下載竊密模塊,并再次利用偽造父進(jìn)程創(chuàng)建傀儡進(jìn)程進(jìn)行注入,從而進(jìn)入竊密階段。
在竊密階段,樣本會(huì)獲取系統(tǒng)信息和其他軟件數(shù)據(jù)。此外,它還會(huì)利用 Lua 和 C# 獲取加密貨幣錢包和密碼管理軟件中的重要數(shù)據(jù),如錢包信息和密碼,并將這些數(shù)據(jù)發(fā)送至遠(yuǎn)程服務(wù)器。
此外,該樣本在內(nèi)存中維護(hù)了一張文件數(shù)據(jù)表。樣本通過(guò)傳遞文件名來(lái)定位數(shù)據(jù)地址,并返回文件數(shù)據(jù)地址和文件大小,涉及的具體文件名如下。
early.x64:注入模塊。
unhook.bin:使 EtwEventWrite 函數(shù)失效。
strategy.x86:反沙箱及檢測(cè)分析環(huán)境。
processes.x:需要檢測(cè)的進(jìn)程名列表。
ua.txt:User-Agent 列表,用于與服務(wù)器通信。
dt.x86:開源項(xiàng)目 al-khaser(具有反沙箱反調(diào)試反虛擬機(jī)等功能)。
proto.x86:加解密指定區(qū)域代碼。
netclient.x86:通信模塊,會(huì)利用該模塊下載竊密模塊,與服務(wù)器通信。
/bin/KeePassHax.dll:開源項(xiàng)目 KeePassHax(竊取 KeePass 中的秘鑰信息)。
初始階段
該階段目的:獲取 rh_0.9.0.exe 并調(diào)用(rh_0.9.0.exe 是通用惡意模塊加載器)。
使沙箱超時(shí):通過(guò)執(zhí)行三次無(wú)意義的計(jì)算耗費(fèi)時(shí)間,從而導(dǎo)致沙箱模擬超時(shí)。
通過(guò)三次循環(huán)耗費(fèi)時(shí)間
分配內(nèi)存:通過(guò)地址 0x54C956(GetModuleHandle)、0x54D20A(GetProcAddress)、0x54D8F4(VirtualAlloc),獲取函數(shù)地址并執(zhí)行 VirtualAlloc 函數(shù)分配 0x6DE04 大小的 PAGE_EXECUTE_READWRITE(可讀可寫可執(zhí)行)權(quán)限的內(nèi)存,用于存儲(chǔ)區(qū)段 .reloc 中的匯編代碼(前半段為解密循環(huán),后半段為被加密代碼)。
分配內(nèi)存
解密:解密循環(huán)中使用 xor(異或)、sub(減法)、not(非)等指令進(jìn)行解密,最終解密出一段代碼。
解密出來(lái)的代碼
該代碼的主要內(nèi)容如下:
通過(guò)哈希獲取 kernel32.dll 基址和若干函數(shù)地址。
將數(shù)據(jù)(些許函數(shù)地址和地址偏移)寫入 PEB + 0xF00 地址內(nèi),以便后續(xù)讀取或調(diào)用。
創(chuàng)建線程,執(zhí)行下一段代碼。
第一個(gè)入口
PEB + 0xF00 地址內(nèi)數(shù)據(jù)
繼續(xù)創(chuàng)建新線程并調(diào)用下一段代碼。
創(chuàng)建線程繼續(xù)調(diào)用下一段代碼
手動(dòng)加載并調(diào)用入口點(diǎn):通過(guò)自定義 PE 結(jié)構(gòu)提取入口點(diǎn)偏移、模塊名哈希、函數(shù)名哈希、重定位偏移等數(shù)據(jù)進(jìn)行手動(dòng)加載并調(diào)用入口點(diǎn)函數(shù)。
手動(dòng)加載并調(diào)用入口點(diǎn)
解密解壓縮出 rh_0.9.0.exe:進(jìn)行提取和異或解密,隨后利用 RtlDecompressBuffer 函數(shù)進(jìn)行解壓縮,可以發(fā)現(xiàn)文件名為 rh_0.9.0.exe,且文件大小有 0x7BA00。
解密解壓縮
手動(dòng)加載并調(diào)用:隨后進(jìn)行導(dǎo)入表修復(fù)、IAT 修復(fù)、重定位、TLS 回調(diào)、設(shè)置區(qū)段內(nèi)存權(quán)限等操作進(jìn)行手動(dòng)加載,接著創(chuàng)建阻塞線程、修改線程入口、恢復(fù)線程等方式調(diào)用 rh_0.9.0.exe。
rh_0.9.0.exe 手動(dòng)加載并調(diào)用
通用惡意模塊加載階段
該階段目的:獲取通用惡意模塊并加載該模塊。
正常代碼中包含惡意代碼:rh_0.9.0.exe 是一個(gè)以 https://github.com/libfann/fann/blob/master/examples/xor_test.c 為主要代碼編譯的文件,其中摻雜了惡意代碼。
下圖左右兩邊被加密數(shù)據(jù)需要使用不同解密:左邊部分直接參與 sm4 解密,右邊部分需要進(jìn)行一次初步解密再進(jìn)行 sm4 解密。
被加密內(nèi)存
右邊被加密數(shù)據(jù)初步解密:右邊部分的被加密數(shù)據(jù)用以下規(guī)則解密,主要思想是:對(duì) A-Z、a-z、0-9,以及特殊字符 "!?#$%&()*+-,/:;<>=@[\\]^`{|}~\n" 分別進(jìn)行特殊處理,從而完成解密。
字符特殊處理
將兩者組合起來(lái)利用 sm4 解密并調(diào)用入口點(diǎn):隨后將兩部分被加密數(shù)據(jù)組合起來(lái),并利用秘鑰 916F0EE05D0AE457A1959EF88B32D960 進(jìn)行 sm4 解密,解密出入口點(diǎn)代碼并調(diào)用。
sm4 解密并調(diào)用入口點(diǎn)
獲取通用惡意模塊:獲取通用惡意模塊(該模塊為病毒作者自定義的 PE 結(jié)構(gòu),文件開頭為 0x58 0x53,即 XS。),樣本將解析該自定義結(jié)構(gòu)并進(jìn)行手動(dòng)加載,此時(shí)可以通過(guò)手動(dòng)構(gòu)造 PE 的方式,使 IDA 能夠識(shí)別模塊內(nèi)容,從而利用 IDA 分析。
手動(dòng)加載
xs 結(jié)構(gòu)
通用惡意模塊第一階段
該階段目的:
解密出遠(yuǎn)程服務(wù)器 URL。
檢測(cè)殺毒軟件。
偽裝父進(jìn)程創(chuàng)建傀儡進(jìn)程(例如 svchost.exe)并注入。
入口點(diǎn)基本處理:通用惡意模塊入口點(diǎn)會(huì)進(jìn)行重定位、修復(fù) IAT、修改調(diào)用 ZwQueryInformationProcess API 地址、禁用線程通知、報(bào)錯(cuò)靜默處理等操作。
入口點(diǎn)
支持異常處理:通過(guò) Hook RtlDispatchException 函數(shù)內(nèi)的 call ZwQueryInformationProcess 偏移,修改其返回值中的 ProcessExecuteFlags 標(biāo)志位,將 ImageDispatchEnable 設(shè)置為真,從而支持手動(dòng)映射 PE 文件時(shí)的異常處理。
異常處理支持
解密出遠(yuǎn)程服務(wù)器鏈接:通過(guò)類似 base64 的方式將編碼數(shù)據(jù)解碼,隨后利用 chacha20 算法(將 64 位計(jì)數(shù)器的低 32 位初始化為 0x80)解密,接著再次通過(guò)異或解密,解密出遠(yuǎn)程服務(wù)器鏈接。
解密算法
解出遠(yuǎn)程服務(wù)器鏈接
檢測(cè)殺毒軟件:通過(guò) ZwQueryDirectoryObject 遍歷 \GLOBAL??,檢測(cè)是否存在殺毒軟件。
殺毒軟件檢測(cè)
偽造父進(jìn)程:首先循環(huán)進(jìn)程列表獲取進(jìn)程句柄,然后利用天堂之門 Hook NtCreateUserProcess 函數(shù),即調(diào)用 NtCreateUserProcess 函數(shù)的前一刻,設(shè)置新進(jìn)程的父進(jìn)程屬性為任意其他進(jìn)程句柄,從而完成偽造父進(jìn)程。
下圖是天堂之門 Hook NtCreateUserProcess 的調(diào)用入口截圖,再下一個(gè)圖是設(shè)置新進(jìn)程的父進(jìn)程屬性為任意其他進(jìn)程句柄的代碼截圖。
天堂之門入口
Hook NtCreateUserProcess
創(chuàng)建傀儡進(jìn)程:創(chuàng)建進(jìn)程時(shí)將 dwCreationFlags 設(shè)置為 CREATE_SUSPENDED | CREATE_NO_WINDOW 從而進(jìn)行阻塞和無(wú)窗口處理。
創(chuàng)建傀儡進(jìn)程
再一次將通用惡意模塊注入至傀儡進(jìn)程:通過(guò)文件數(shù)據(jù)表獲取 early.x64(注入模塊),隨后手動(dòng)加載并利用天堂之門調(diào)用該注入模塊,將通用惡意模塊(與上面通用惡意模塊入口點(diǎn)不同)注入至傀儡進(jìn)程中。
注入
兩個(gè)入口點(diǎn)
通用惡意模塊第二階段
最終目的:
Hook EtwEventWrite 函數(shù)。
反沙箱、反調(diào)試、反虛擬機(jī)、檢測(cè)分析環(huán)境等。
下載竊密模塊將其注入至傀儡進(jìn)程。
Hook EtwEventWrite:通過(guò)文件數(shù)據(jù)表獲取 unhook.bin,利用天堂之門執(zhí)行,將 EtwEventWrite 設(shè)置為空,從而使函數(shù)失效。
Hook EtwEventWrite
加載 strategy.x86 進(jìn)行反沙箱:通過(guò)文件數(shù)據(jù)表獲取 strategy.x86,手動(dòng)加載后調(diào)用入口點(diǎn),以下是入口點(diǎn)。
入口點(diǎn)
以下是入口點(diǎn)內(nèi)執(zhí)行的函數(shù)細(xì)節(jié),分別是:
測(cè)試 COM 組件是否能運(yùn)行,從而檢測(cè)沙箱(因有些沙箱模擬并不全面)。
檢測(cè)指定程序是否正在運(yùn)行,從而規(guī)避分析環(huán)境。
通過(guò)判斷屏幕是否小于 800x600,檢測(cè)虛擬機(jī)或沙箱。
通過(guò)獲取屏幕壁紙與 triage 沙箱壁紙進(jìn)行 sha1 對(duì)比,從而判斷是否在 triage 沙箱中。
通過(guò)桌面上是否有異常的文件數(shù)量,異常的文件大小、異常的軟件數(shù)量來(lái)判斷是否在沙箱中。
通過(guò)檢測(cè)用戶名和 DNS 名是否與沙箱用戶名一致,從而檢測(cè)沙箱。
通過(guò)判斷桌面上的 password 文件是否存在異常情況,從而檢測(cè)沙箱。
strategy.x86 反沙箱具體代碼
下圖是將會(huì)進(jìn)行檢測(cè)的進(jìn)程名。(通過(guò)文件數(shù)據(jù)表獲取 processes.x)
進(jìn)程名
以下是 triage 沙箱壁紙圖。
triage 沙箱壁紙
獲取 User-Agent:通過(guò)文件數(shù)據(jù)表獲取 ua.txt,用于與遠(yuǎn)程服務(wù)器通信。
ua.txt
加載 dt.x86 進(jìn)行反沙箱反調(diào)試反虛擬機(jī):通過(guò)文件數(shù)據(jù)表獲取 dt.x86,其中使用了 al-khaser 開源項(xiàng)目中的反沙箱、反調(diào)試、反虛擬機(jī)等功能。
dt.x86 入口
下圖是部分代碼截圖。
反調(diào)試、反沙箱、反虛擬機(jī)
下載竊密模塊并注入至傀儡進(jìn)程:將解密出的遠(yuǎn)程服務(wù)器與 User-Agent 當(dāng)做參數(shù)傳遞至 netclient.x86(通信模塊)下載竊密模塊,隨后將竊密模塊復(fù)制到共享內(nèi)存中,利用 NtDuplicateObject 復(fù)制共享內(nèi)存句柄并將其注入至傀儡進(jìn)程中,通過(guò)該句柄讀取并執(zhí)行竊密模塊。
netclient.x86 調(diào)用傳參
自解密:進(jìn)入 netclient.x86 模塊時(shí),首先利用 proto.x86 加解密模塊進(jìn)行加密,從而使入口點(diǎn)以及整個(gè) 9D0000 堆被加密,結(jié)束后再次利用proto.x86 加解密模塊進(jìn)行解密。
proto.x86 模塊
下圖是利用異或加密之后的調(diào)用 netclient.x86 的入口點(diǎn)和異或算法。
異或算法
竊密階段
總共可以分為三個(gè)模式:
常規(guī)竊密:獲取系統(tǒng)信息、Chrome、Steam 等軟件信息。
Lua 竊密:利用 Lua 腳本,通過(guò) Lua 解釋器解釋執(zhí)行,竊取錢包、SSH 客戶端、郵件、V*N 等軟件中信息。
C# 竊密:通過(guò)開源項(xiàng)目 KeePassHax 竊取 KeePass 數(shù)據(jù)。
常規(guī)竊密
下圖是獲取時(shí)區(qū)、Windows 版本信息、用戶名、工作組名稱、用戶帳戶控制相關(guān)、屏幕壁紙哈希、內(nèi)存大小、CPU 信息等數(shù)據(jù)的截圖。
樣本還會(huì)收集設(shè)備唯一標(biāo)識(shí)(MachineGuid)、Windows 產(chǎn)品密鑰(BackupProductKeyDefaul)、分辨率、顯示器描述(DeviceString)、計(jì)算機(jī)名、安裝軟件列表、進(jìn)程列表等數(shù)據(jù)。
收集系統(tǒng)信息
此外,樣本會(huì)收集 Chrome、Edge、Steam、IE、Firefox、OpenV*N、WinSCP、Telegram、Simple Sticky Notes、CoreFTP、TeamViewer 軟件信息。
下圖是竊取 Chrome 和 Edge 瀏覽器 和 Steam 平臺(tái)中文件代碼截圖:
竊取瀏覽器文件中的 .ldb 和.log 等數(shù)據(jù)庫(kù)文件。
竊取 Steam 平臺(tái)文件中的 .vdf 文件和 SSFN 登錄驗(yàn)證文件進(jìn)行無(wú)密碼登錄。
Chrome、Edge、Steam 文件竊取
Lua 竊密
樣本會(huì)循環(huán)讀取名稱為 00000001.xs 至 000000041.xs 的Lua 腳本,并利用 Lua 解釋器進(jìn)行解釋執(zhí)行,同時(shí)竊取錢包、SSH 客戶端、郵件、V*N 等軟件中的信息,最后利用 MessagePack 序列化數(shù)據(jù)并發(fā)送至遠(yuǎn)程服務(wù)器。
加密貨幣錢包竊?。?/span>掃描 %AppData%\
Armory 錢包竊取腳本
FTP/SSH 客戶端竊?。?/span>竊取 PuTTY、CuteFTP、FlashFXP、SmartFTP、Total Commander 等 FTP/SSH 客戶端秘鑰信息,下圖是 PuTTY 客戶端相關(guān)秘鑰的竊取腳本。
PuTTY 客戶端相關(guān)秘鑰竊取腳本
郵件與通訊軟件竊取:竊取 Outlook、The Bat!、eM Client、Pidgin 等軟件秘鑰信息,下圖是 Outlook 秘鑰信息的竊取腳本。
Outlook 秘鑰信息竊取腳本
V*N 配置竊取:竊取 NordV*N、ProtonV*N、Windscribe、AzireV*N 等 V*N 配置,下圖是 NordV*N 配置文件的竊取腳本。
NordV*N 配置文件竊取腳本
C# 竊密
該 C# 模塊通過(guò)文件數(shù)據(jù)表獲取 /bin/KeePassHax.dll 得到,該模塊為開源項(xiàng)目 KeePassHax 編譯后的動(dòng)態(tài)庫(kù)。
通過(guò)注入至 KeePass 進(jìn)程中逐步獲取 m_formMain、m_docMgr、m_dsActive、m_pwDb 等字段以獲取秘鑰數(shù)據(jù),隨后發(fā)送至遠(yuǎn)程服務(wù)器。