“無文件”惡意軟件的最新藏匿處
在2022年2月,卡巴斯基實驗室的研究人員首次觀察到將shellcode放入Windows事件日志的技術。該技術允許在文件系統中隱藏“無文件”最后stager的木馬。這種對活動中事件日志的關注不僅限于存儲 shellcode。 Dropper 模塊還修復了與事件跟蹤 (ETW) 和反惡意軟件掃描接口 (AMSI) 相關的 Windows 原生 API 函數,以使感染過程更加隱蔽。
除了事件日志之外,攻擊者的工具集中還有許多其他技術。其中,開發者在功能中增加了偵察,可以模仿合法域名的 C2 Web 域名,以及受害者使用的現有和軟件的名稱。為了使攻擊更加隱蔽,攻擊者使用 Linode、Namecheap、DreamVPS 上的虛擬專用服務器。
一種更常見的方法是使用大量的反檢測解密器。攻擊者使用不同的編譯器,從微軟的 cl.exe 或 MinGW 下的 GCC 到最新版本的 Go。此外,為避免被檢測到,某些模塊使用數字證書進行簽名。研究人員認為它是由攻擊者發布的,因為遙測數據沒有顯示任何與之簽名的合法軟件,只有這次活動中使用的惡意代碼。
關于最后stager的特洛伊木馬,攻擊者決定使用多個基于 HTTP 和命名管道。顯然,除了事件日志之外,攻擊者還癡迷于內存注入,許多 RAT 命令與它相關并且被大量使用。除了上述自定義模塊和技術外,攻擊者還使用了一些商業滲透測試工具,如 Cobalt Strike 和 SilentBreak 的工具集。
感染鏈
研究人員從內存中的最后一個stager開始研究,然后使用遙測技術,重建了幾個感染鏈,該活動的針對性很強,且使用的大量工具還包括商業工具。
該活動包括各種技術和模塊,讓我們把它分成幾類來從技術上描述這個活動,比如商業滲透測試套件、圍繞它們的自定義反檢測包裝器和最后stager的木馬。
商業工具集有:
- 反檢測包裝器——大量使用系統調用庫的Go 解密器,這可以使Cobalt Strike 模塊多次編碼,并使用 AES256 CBC 加密 blob,這是首次觀察到 擁有Cobalt Strike 的Go的使用情況。
- 反檢測包裝器——一個庫啟動器,在 MinGW 環境下使用 GCC 編譯。這個stager唯一可能的原因是反檢測。
- 反檢測包裝器——AES 解密器,使用 Visual Studio 編譯器編譯;
- 最后stager RAT—— 基于 HTTP 的木馬,可能的原始名稱是 ThrowbackDLL.dll 和 drxDLL.dll,但代碼比 SilentBreak 的 Throwback 的舊版本更復雜。
- 最后stager RAT—— 基于管道的命名木馬,可能的原始名稱是 monolithDLL.dll 和 SlingshotDLL.dll。根據文件名,最后stager模塊可能是商業 Slingshot 版本的一部分。
同樣,我們認為定制的一些模塊(如包裝器和最后stager)可能是商業產品的一部分。分類之后,我們準備一個一個地分析模塊。
初始感染
我們觀察到的最早攻擊stager發生在 2021 年 9 月。Cobalt Strike 模塊的傳播是通過說服目標下載合法站點 file.io 上的 .rar 鏈接并自行運行來實現的。內部 Cobalt Strike 模塊的數字證書如下(在使用相同的活動期間,從 wrapper 到 last stagers 簽署了 15 個不同的 stager):
由于所有目標主機的感染情況不同,我們將僅描述觀察到的一種情況。由于能夠使用木馬將代碼注入任何進程,攻擊者可以自由地廣泛使用此功能將下一個模塊注入 Windows 系統進程或受信任的應用程序(如 DLP)。
記住截斷的進程注入,甚至模仿 Web 域注冊,我們可以將攻擊過程描述為非常迭代(quite iterative):對一些模塊進行初始偵察,然后準備額外的攻擊。
商業工具集
關于商業工具,這次活動中使用 SilentBreak 和 Cobalt Strike 工具集的痕跡非常明顯。名為 ThrowbackDLL.dll 和 SlingshotDLL.dll 的木馬讓我們想起 Throwback 和 Slingshot,它們都是 SilentBreak 框架中的工具,而與 dropper (sb.dll) 關聯的“sb”可能是供應商名稱的縮寫。
這里我們要提一下,二進制文件中的幾個 .pdb 路徑包含項目的目錄 C:\Users\admin\source\repos\drx\ 以及其他未以 Throwback 或 Slingshot 命名的模塊,例如 drxDLL.dll。但是,加密函數與公開可用的 Throwback 代碼中的相同。
反檢測設計
對于反檢測包裝器,使用了不同的編譯器。除了 MSVC,Go 編譯器 1.17.2 和 MinGW 下的 GCC 都在使用。解密器差異很大,它們包含的功能如下表所示:
- 幾個編譯器——可以使用 Go 和 C++ 模塊完成相同的 AES256 CBC 解密;
- 列入白名單的啟動器——WerFault.exe 的自動運行副本將啟動器映射到進程地址空間;
- 數字證書 ——15 個文件使用“Fast Invest” 證書簽名,我們沒有觀察到任何用它簽名的合法文件
- 修復 ntdll.dll 的日志記錄導出——為了更加隱蔽,Go dropper 將與日志記錄相關的 API 函數(如 EtwEventWriteFull)修復到具有空功能的自地址空間中;
- 在事件日志中保留 shellcode——這是攻擊者的主要創新,使用 next stager 加密的 shellcode 被分成 8 KB 的block并保存在事件日志的二進制部分中;
- C2 網絡域名模仿——攻擊者在使用標題中,注冊了一個ERP網絡域名;
這層感染鏈解密、映射到內存并啟動代碼。本文我們將僅介紹 Cobalt Strike 的 Go 解密啟動器。
主包中的函數名稱被混淆了,Main.init 從與事件日志創建相關的 kernel32.dll 和 ntdll.dll 庫(WriteProcessMemory 和其他函數)中解碼 Windows API 函數名稱。二進制文件中的每個名稱都連續四次使用 base64 編碼。使用 WriteProcessMemory,擁有“xor rax, rax; ret”的dropper在內存中編碼以下函數:EtwNotificationRegister、EtwEventRegister、EtwEventWriteFull、EtwEventWriteFull、EtwEventWrite。
在 Main.start 中,惡意軟件會檢查主機是否在域中,并且只有在它為真時才起作用。然后動態解析上述函數的地址。下一個stager使用 AES256(CBC 模式)加密,密鑰和 IV 使用 base64 編碼。
使用這種方法,研究人員需要編寫一些腳本來收集下一個模塊的加密部分。解密后,要獲得最終的可移植可執行文件,還需進一步轉換數據。
最后stager類型
Last stager 有兩種通信機制——使用RC4加密的HTTP通信機制和使用命名管道的非加密通信機制。后一種方式在技術上能夠與任何網絡可見的外部主機通信,但在Windows環境中,命名管道是建立在SMB協議之上的,它幾乎不會對外部網絡開放。所以這些模塊很可能用于橫向移動。
在對惡意軟件集進行了介紹之后,我們現在將描述感染鏈,研究人員使用 Cobalt Strike 滲透測試套件進行Dropper注入。
用DLL中的Dropper實現order劫持
研究人員從 wrapper-dropper 動態庫開始自定義模塊分析。此代碼被注入到諸如 explorer.exe 之類的 Windows 進程中。在加載到啟動程序進程的虛擬地址空間后,在其單個入口點,dropper 刪除由先前stager或執行創建的文件。
首先,該模塊將原始合法的操作系統錯誤處理程序 WerFault.exe 復制到 C:\Windows\Tasks。然后,它將一個加密的二進制資源放置到同一目錄中的wer.dll文件中,以進行典型的DLL order劫持。為了持久化,該模塊將新創建的WerFault.exe設置為自動運行,在Software Microsoft\Windows\CurrentVersion\Run Windows系統注冊分支中創建一個Windows問題報告值。
dropper 不僅將啟動器放在磁盤上進行側載,而且還會將帶有 shellcode 的信息消息寫入現有的 Windows KMS 事件日志。
被刪除的wer.dll是一個加載器,如果沒有隱藏在Windows事件日志中的shellcode,它不會造成任何傷害。dropper在事件日志中搜索類別為 0x4142(ASCII 中的“AB”)并以密鑰管理服務作為源的記錄。如果沒有找到,則通過 ReportEvent() Windows API 函數(lpRawData 參數)將 8KB 的 shellcode 塊寫入信息記錄消息。從 1423 開始,創建的事件 ID 會自動遞增。
wer.dll 中的啟動器
這個啟動器,被第一個stager放到 Tasks 目錄中,它代理所有對wer.dll的調用,并將其導出到原始合法庫。在入口點,一個單獨的線程將所有上述 8KB 片段組合成一個完整的 shellcode 并運行它。由合法 WerFault.exe 的副本創建的相同虛擬地址空間用于所有這些代碼。
為了防止 WerFault 繼續其錯誤處理過程,DLL 使用典型的 Blackbone trampoline修復啟動器的入口點
阻止合法啟動器執行的方法很新穎。在主線程中,wer.dll 找到它的入口點并用一個簡單的函數對其進行修復。上面屏幕截圖中的 WaitAndExit() 只會使用日志收集線程 ID 調用 WaitForSingleObject() ,然后退出,這意味著永遠不會執行真正的 WerFault.exe 錯誤處理代碼:映射到其地址空間的欺騙性 DLL 會阻止它。
Windows 事件日志中的Shellcode
啟動器將控制傳輸到收集的 shellcode 的第一個字節。在本文中,研究人員為下一個函數準備了三個參數:
- 下一個stager木馬的地址,它也包含在從事件日志中提取的數據中;
- 導出函數名稱的標準 ROR13 哈希在此木馬中加載 (0xE124D840);
- 字符串“dave”和常量“4”的地址,它們成為導出函數的參數,可以通過哈希找到;
解析下一個 Windows 可移植可執行文件以定位其入口點的做法是非常典型的。為了讓下一個stager的木馬不那么顯眼,攻擊者清除了標題中的“MZ”魔法。在木馬的入口點調用代碼后,shellcode 還會搜索請求導出并調用它。
除了搜索入口點并調用它,shellcode 還通過硬編碼哈希搜索木馬導出,并使用參數“dave”和“4”運行找到的函數
HTTP木馬
相比之前的輔助模塊,對于最后一個stager,我們會介紹的更詳細一些。 C++ 模塊顯然使用了 SilentBreak(現為 NetSPI)的 Throwback 公共存儲庫中的代碼:基于 XOR 的加密函數,一些示例的原始文件名,例如 ThrowbackDLL.dll 等。讓我們從前面提到的Load()導出函數開始。這就像上面的WerFault補丁(函數在主木馬線程上等待),但是它忽略了任何參數,所以“dave”和“4”沒有被使用。這個啟動器可能支持比這個更多的模塊。
目標搜索
該模塊使用單字節 XOR 密鑰解密 C2 域,在此示例中,只有一個域 eleed[.]online。該木馬能夠處理其中的許多,以“|”字符分隔并加密。為了進一步通過普通HTTP進行通信,木馬從用戶代理“Mozilla 5.0”的集合中隨機選擇一個C2。
該惡意軟件通過收集以下信息生成一個追蹤字符串,也用“|”分隔:
- SOFTWARE\Microsoft\Cryptography 中 MachineGUID 的值;
- 計算機名稱;
- 使用 GetAdaptersInfo 獲取的本地 IP 地址;
- 架構(x86 或 x64);
- 操作系統版本;
- 當前進程是否有SeDebugPrivilege;
追蹤識別器還將“1.1”附加到字符串(可能是惡意軟件版本)和當前配置的睡眠時間。
與C2進行加密的HTTP通信
在HTTP通信之前,該模塊使用硬編碼的32字節長的RC4密鑰發送空(但仍然加密)的ICMP數據包來檢查連接。與任何其他字符串一樣,此密鑰使用基于Throwback xor的算法加密。
如果ping端口為80的控制服務器成功,則將上述追蹤數據發送到該控制服務器。作為回應,C2共享木馬主循環的加密命令。
木馬命令
代碼的命令功能:
- 0——再次對目標進行追蹤識別;
- 1——執行命令,木馬在新進程中執行接收到的命令并將結果發送回C2;
- 2——從 URL 下載并保存到給定路徑;
- 3——設置新的睡眠時間,如果 C2 尚未響應要執行的命令,則將此時間(以分鐘為單位)用作超時。隨機化公式為(0,9 - 1,1之間的隨機數)*睡眠時間;
- 4——在不改變配置的情況下休眠指定的分鐘數。
- 5——列出具有 PID、路徑、所有者、名稱和父數據的進程;
- 6——將 shellcode 注入并運行到目標進程的地址空間。要注入同一個進程,命令參數應該是“local”。與事件日志中的 shellcode 一樣,該代碼將運行提供的 PE 的入口點以及通過哈希找到的特定導出。
- 99——終止木馬和C2之間的會話。
本次活動中使用的另一個木馬是基于管道命名的,這樣命令系統更有意義,包括特權升級、截圖、非活動時間測量等。繼續使用另一種最后stager的木馬類型,發現它被注入到了像edge.exe這樣的進程中。
基于管道命名的木馬
木馬的位置是 C:\Windows\apds.dll,具有相同名稱的原始合法 Microsoft 幫助數據服務模塊庫位于 C:\Windows\System32 中。木馬的主要工作周期是在一個單獨的線程。該惡意軟件還導出一個Load()函數,其唯一目的是等待一個工作線程,這是該活動的模塊的典型。
首先,木馬主線程獲取原始apds.dll并導出,并將其保存到內存中木馬映像之后的一個已分配的新堆緩沖區中。然后,木馬會編輯自己導出的函數數據,這樣它就可以通過如下精心制作的存根調用原始的apds.dll導出,其中的地址就是從真正的apds.dll解析出來的地址:
這個trampoline代碼取自Blackbone Windows內存黑客庫(remotemmemory::BuildTrampoline函數)。DLL劫持并不是什么新鮮事,我們已經多次看到這種技術被用于代理合法函數,但僅用短存根重新創建自導出來調用原始合法函數卻很不尋常。然后,該模塊創建一個雙工命名的管道“MonolithPipe”,并進入它的主循環。
工作周期
在對導出函數進行上述操作后,該模塊會輕微地使用架構和 Windows 版本信息對主機進行追蹤識別。木馬還使用提到的稀有常量初始化一個隨機的 11 字節 ASCII 字符串,例如這里的 init_keys 函數。結果用作唯一的會話 ID。
惡意軟件連接到端口 443 上的硬編碼域(在本例中為 https://opswat[.]info:443),并向 C2 端的 submit.php 發送 POST 請求。 HTTPS 連接選項設置為接受服務器端的自簽名證書。在本例中,C2通信使用Dhga(81K1!392-!(43<KakjaiPA8$#ja密鑰的RC4算法加密。對于基于管道命名的木馬,常用的命令有:
- 0——將“continue”標志設置為 False 并停止工作;
- 1—— N/A,保留至今;
- 2——獲取自上次用戶輸入以來的時間(以分鐘為單位);
- 3——獲取當前進程信息:PID、架構、用戶、路徑等;
- 4——獲取主機域和用戶帳戶;
- 5——使用提供的憑據模擬用戶;
- 6——獲取當前進程的可用權限;
- 7——使用 cmd.exe 解釋器執行命令;
- 8——使用與給定主機(地址和端口)的原始 TCP 套接字測試的連接;
- 9——獲取正在運行的進程信息:路徑、所有者、名稱、父進程、PID等;
- 10——使用提供的 ID 的進程令牌模擬用戶;
- 11——列出目錄中的文件;
- 12——截取屏幕截圖;
- 13——將內容寫入文件;
- 14——讀取文件內容;
- 15——刪除文件;
- 16——將提供的代碼注入到具有給定名稱的進程中。
- 17——在C2上運行shellcode;
研究人員現在已經介紹了該活動的三個層面,有趣的是,研究人員觀察到一個木馬具有如上表所示的完整命令集,但仍然使用rc4加密的HTTP與C2通信,而不是指定管道。最后一個stager的示例看起來像一個模塊化的平臺,攻擊者能夠根據他們當前的需要組合其功能。
基礎設施
研究人員認為這些代碼是自定義的(木馬、包裝器),與以前已知的活動或以前注冊的SilentBreak工具集模塊沒有相似之處。現在研究人員不愿意給這個活動命名,而是堅持只用“SilentBreak”。
本文翻譯自:https://securelist.com/a-new-secret-stash-for-fileless-malware/106393/