變量隱藏一些變量不是以明文形式存儲的,而是使用一個或多個算術指令隱藏起來的。這意味著如果Roshtyak 沒有主動使用變量,它將以混淆的形式保留該變量的值。每當Roshtyak需要使用該變量時,它必須在使用它之前先解開它的掩碼。相反,在Roshtyak使用該變量後,它會將其轉換回掩碼形式。這種隱藏方法使調試期間跟踪變量的工作變得複雜,並使搜索內存中已知變量值變得更加困難。
循環變換Roshtyak 在一些循環條件下很有創意。它沒有像for (int i=0; i 1690; i++) 那樣編寫循環,而是將循環轉換為for (int32_t i=0x06AB91EE;我!=0 x70826068;i=i * -0x509FFFF +0xEC891BB1)。雖然兩個循環都將執行1690 次,但第二個循環要難得多。乍一看,不清楚第二個循環執行了多少次迭代,甚至不知道它是否會終止。在第二種情況下,在調試期間跟踪循環迭代的次數也要困難得多。
包裝如上所述,Roshtyak 的核心隱藏在多層包裝之後。雖然所有的層看起來都像是最初編譯到PE文件中,但除了嚴格必要的數據(入口點、節、導入和重定位)之外的所有數據都被剝離了。此外,Roshtyak 支持兩種自定義格式來存儲剝離的PE 文件信息,各層輪流使用對應的格式。此外,段自定義格式是加密的,有時使用基於各種反分析檢查結果生成的密鑰。
這使得將Roshtyak 的層靜態解壓到一個獨立的PE 文件中變得很困難。首先,必須對自定義格式進行逆向工程,並弄清楚如何解密加密段。然後,必須重構PE 標頭、段、段標題和導入表(重定位表不需要重構,因為重定位可以被關閉)。雖然這一切都是完全可行的,並且可以使用像LIEF 這樣的庫來簡化,但這可能需要大量的時間。除此之外,這些層有時是相互依賴的,在內存中動態分析Roshtyak 可能更容易。
其中一個自定義PE 類文件格式的段標題:raw_size 對應於SizeOfRawData,raw_size + virtual_padding_size 實際上是VirtualSize。沒有VirtualAddress 或PointerToRawData 等效項,因為這些段是按順序加載的。
其他混淆技巧除了上述技巧之外,Roshtyak 還使用其他混淆技巧,包括:
垃圾指令插入;
導入哈希;
頻繁清除內存;
混合佈爾算術混淆;
冗餘線程;
重多態性;
核心功能既然我們已經描述了Roshtyak 如何保護自己,那麼看看它的實際作用可能會很有趣。 Roshtyak 的DLL 相對較大,超過1 兆字節,但是一旦消除了所有的混淆,它的功能就非常簡單。它的主要目的是下載更多的有效載荷來執行。此外,它還執行通常的惡意軟件操作,即建立持久性、提升權限、橫向移動和洩露有關受害者的信息。
持久性攻擊Roshtyak 首先在%SystemRoot%\Temp 中生成一個隨機文件名,並將其DLL 映像移動到那裡。生成的文件名由2到8個隨機小寫字符與從硬編碼列表中選擇的隨機擴展名組成。用於生成此文件名的PRNG的捲序列號為C:\。我們分析的示例是硬編碼的7個擴展名(.log、tmp、loc、dmp、out、ttf 和.etl)。我們觀察到其他示例中使用了其他擴展,這表明這個列表是動態的。 Roshtyak 也很有可能會使用隨機生成的擴展。一旦完全構建,到Roshtyak DLL的完整路徑可能看起來如C:\Windows\Temp\wcdp.etl這樣。
將DLL 映像移動到新的文件系統路徑後,Roshtyak 將其修改後的時間戳記到當前系統時間。然後它繼續設置RunOnce(Ex) 註冊表項,以實際建立持久性。註冊表項是使用前面描述的間接註冊表寫入技巧創建的。插入密鑰的命令可能如下所示:
RUNDLL32.EXE SHELL32.DLL,ShellExec_RunDLL REGSVR32.EXE -U /s 'C:\Windows\Temp\wcdp.etl.'
這裡有幾點需要注意。首先,regsvr32 不關心它加載的DLL 的擴展名,從而允許Roshtyak 隱藏在.log 等看似無害的擴展名下。其次,/s 參數將regsvr32 置於靜默模式。如果沒有它,regsvr32將抱怨找不到名為DllUnregisterServer的導出。最後,請注意路徑末尾的句號字符。該句號在路徑規範化期間被釋放,因此它實際上對命令沒有影響。所以,我們不確定開發者的初衷是什麼。它看起來像是被設計用來欺騙一些反惡意軟件,使其無法將持久性條目與文件系統上的有效負載連接起來。
默認情況下,Roshtyak 使用HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 項進行持久化。但是,在某些情況下(例如,當它通過檢查名為avp.exe 的進程檢測到Kaspersky 正在運行時)將使用密鑰HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx。 RunOnceEx 項能夠加載DLL,因此在使用該項時,Roshtyak 直接指定shell32.dll,省略了rundll32的使用。
Roshtyak 建立的RunOnceEx 持久性條目
權限提升Roshtyak 使用UAC 繞過和常規EoP 漏洞來嘗試提升其權限,與許多其他惡意軟件只是盲目地執行開發者可以找到的任何UAC 繞過/利用的惡意軟件不同,Roshtyak 努力確定權限提升方法是否有可能成功。由於不必要地使用了不兼容的繞過/漏洞,這可能是為了降低檢測的機會。對於UAC 繞過,這涉及檢查ConsentPromptBehaviorAdmin 和ConsentPromptBehaviorUser 註冊表項。對於EoP 漏洞利用,這是關於檢查Windows 內部版本號和補丁級別。
除了檢查ConsentPromptBehavior(Admin|User) 項之外,Roshtyak 還執行其他健全性檢查以確保它應該繼續繞過UAC。即,它使用SID S-1-5-32-544 (DOMAIN_ALIAS_RID_ADMINS) 的CheckTokenMembership 檢查管理員權限。它還檢查KUSER_SHARED_DATA.SharedDataFlags 中DbgElevationEnabled 標誌的值。這是一個未記錄的標誌,在啟用UAC 時設置。最後,還有針對BitDefender(由模塊atcuf32.dll 檢測)、卡巴斯基(進程avp.exe)和我們自己的Avast/AVG(模塊aswhook.dll)的殺毒軟件檢查。如果檢測到這些殺毒軟件,Roshtyak 會避開選定的UAC 繞過技巧,大概是那些可能導致被檢測到。
至於實際的UAC旁路,主要有兩種實現方法。第一個是UACMe 中恰當命名的ucmDccwCOM 方法的實現。有趣的是,當執行此方法時,Roshtyak 通過覆蓋對應於主可執行模塊的_LDR_MODULE 結構中的FullDllName 和BaseDllName 臨時將其進程偽裝成explorer.exe。此方法啟動的有效負載是一個隨機命名的LNK 文件,使用IShellLink COM 接口放入%TEMP%。此LNK 文件旨在通過LOLBins(例如advpack 或register-cimprovider)重新啟動Roshtyak DLL。
第二種方法更像是一個UAC 繞過框架而不是特定的繞過方法,因為多個UAC 繞過方法遵循相同的簡單模式:首先註冊一些特定的shell 打開命令,然後執行自動提升的Windows 二進製文件(內部觸發shell 打開命令)。例如,可以通過向HKCU\Software\Classes\ms-settings\shell\open\command 寫入有效負載命令,然後從%windir%\system32 執行fodhelper.exe 來完成UAC 繞過。基本上,同樣的繞過可以通過用其他對替換ms-settings/fodhelper.exe來實現,例如mscfile/eventvwr.exe。 Roshtyak使用以下6對來繞過UAC:
現在讓我們看看Roshtyak 用於提升權限的內核漏洞(CVE-2020-1054 和CVE-2021-1732)。與Roshtyak 中的常見情況一樣,這些漏洞被加密存儲,並且僅在需要時才解密。有趣的是,一旦解密,漏洞利用結果是具有完全有效標頭的常規PE 文件,與Roshtyak 中的其他層不同,它們要么以shellcode 形式存在,要么以自定義剝離的PE 格式存儲。此外,這些漏洞不像Roshtyak的其他漏洞那樣容易混淆,所以它們的代碼可以立即反編譯,而且只使用了一些基本的字符串加密。我們不知道為什麼攻擊者讓這些漏洞如此暴露,但這可能是由於位數的不同。雖然Roshtyak 本身是x86 代碼(大段時間在WoW64 下運行),但漏洞利用是x64,考慮到它們利用64 位代碼中的漏洞,這是有道理的。可能Roshtyak 的開發者使用的混淆工具是為x86 設計的,不能移植到x64。
Roshtyak利用CVE-2020-1054的代碼片段,掃描IsMenu找到HMValidateHandle的偏移量
為了執行漏洞,Roshtyak 生成(AMD64 版本)winver.exe 並使用KernelCallbackTable 注入方法獲取漏洞代碼以在其中運行。 Roshtyak的這種注入方法的實現基本上與公共PoC相匹配,最大的區別是由於需要跨子系統注入而使用了略微不同的API函數(例如NtWow64QueryInformationProcess64而不是NtQueryInformationProcess或NtWow64ReadVirtualMemory64而不是ReadProcessMemory)。注入winver.exe的代碼不是利用PE本身,而是稍微混淆的shellcode,旨在將漏洞利用PE 加載到內存中。
內核漏洞針對某些未打補丁的Windows 版本。具體來說,CVE-2020-1054 僅用於版本號不高於24552 的Windows 7 系統。另一方面,CVE-2021-1732 的漏洞利用在Windows 10 上運行,目標內部版本號範圍為16353 到19042。在利用CVE-2021-1732之前,Roshtyak還會掃描已安裝的更新包,以查看是否安裝了針對該漏洞的補丁。它通過枚舉HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based services \Packages下面的註冊表項,並檢查KB4601319(或更高)的包是否存在。
橫向運動在橫向移動方面,Roshtyak 只使用久經考驗的PsExec 工具。在執行PsExec 之前,Roshtyak 通過檢查與“眾所周知的”WinAccountDomainAdminsSid 組匹配的SID 來確保運行它是有意義的。如果未檢測到域管理員權限,Roshtyak 將完全跳過其橫向移動階段。
Roshtyak 試圖通過設置Defender 排除項來繞過檢測,因為PsExec 通常被標記為黑客工具(有充分的理由)。它為%TEMP% 設置一個路徑排除(它將釋放PsExec 和其他用於橫向移動的文件)。稍後,它會為執行PsExec 的確切路徑設置一個進程排除。
雖然我們希望PsExec被捆綁到Roshtyak中,但結果是Roshtyak從https://download.sysinternals[.]com/files/PSTools.zip按需下載PsExec。下載的zip歸檔文件被放入%TEMP%中,後綴名為.zip。然後使用Windows Shell COM接口(IShellDispatch)將PsExec從這個歸檔文件解壓縮到%TEMP%中隨機命名的.exe文件中。
PsExec 執行的有效負載是一個自解壓包,由名為IExpress 的工具創建。這是一個古老的安裝程序,它是Windows 的一部分,這可能就是使用它的原因,因為Roshtyak 可以依賴它已經在受害者設備上。安裝程序生成由使用自解壓指令(SED) 語法的文本文件配置。
Roshtyak 的IExpress 配置模板
Roshtyak 使用具有三個佔位符(%1、%2 和%3)的SED 配置模板,它在運行時將其替換為實際值。如上所示,配置模板是混合大小寫編寫的,通常在Raspberry Robin 中經常使用。準備好SED配置後,它就會被寫入%TEMP% 中隨機命名的.txt 文件。然後,調用iexpress 以使用C:\Windows\iexpress.exe /n /q
生成有效負載後,Roshtyak就開始實際運行PsExec。 Roshtyak 可以通過兩種方式執行PsExec。第一個使用命令
分析受害者USB 蠕蟲往往有自己的活動。由於它們的蠕蟲行為通常是完全自動化的,因此最初部署蠕蟲的攻擊者不一定完全控制它的傳播位置。這就是為什麼攻擊者將蠕蟲信標返回到他們的CC 服務器很重要的原因。有了信標機制,攻擊者就可以獲知他們控制的所有機器的信息,並可以利用這些信息對蠕蟲進行管理。
發出的信標郵件通常包含有關受感染計算機的一些信息。這有助於有經濟動機的攻擊者決定如何利用攻擊獲利。 Roshtyak 也不例外,它收集了有關每個受感染受害者的大量信息。 Roshtyak 將所有收集到的信息連接成一個大字符串,使用分號作為分隔符。這個大字符串然後被轉移到Roshtyak的CC服務器上。下面按順序列出了過濾出來的信息。
外部IP 地址(在Tor 連接檢查期間獲得);
一個硬編碼到Roshtyak 代碼中的字符串,例如AFF123(我們無法確定這背後的含義,但它看起來像一個附屬ID);
DLL 的PE 標頭的16 位哈希(一些字段清零)與其TimeDateStamp 的低16 位異或。 TimeDateStamp 似乎是經過特殊設計的,因此異或會產生一個已知值。這可以作為篡改檢查或水印的功能;
系統驅動器上System Volume Information 文件夾的創建時間戳;
系統驅動器的捲序列號;
處理器計數(GetActiveProcessorCount);
IsWow64Process (_PROCESS_EXTENDED_BASIC_INFORMATION.Flags 2);
Windows 版本(KUSER_SHARED_DATA.Nt(Major|Minor)Version);
Windows 產品類型(KUSER_SHARED_DATA.NtProductType);
Windows 構建號(PEB.OSBuildNumber);
本地管理權限(ZwQueryInformationToken(TokenGroups)/CheckTokenMembership,檢查DOMAIN_ALIAS_RID_ADMINS);
域管理權限(檢查WinAccountDomainAdminsSid/WinAccountDomainUsersSid);
系統時間(KUSER_SHARED_DATA.SystemTime);
時區(KUSER_SHARED_DATA.TimeZoneBias);
系統區域設置(NtQueryDefaultLocale(0));
用戶區域設置(NtQueryDefaultLocale(1));
環境變量(username, computername, userdomain, userdnsdomain和logonserver);
Java 版本(GetFileVersionInfo('javaw.exe') - VerQueryValue);
處理器信息(獲取處理器品牌字符串的cpuid);
主可執行模塊的映像路徑(NtQueryVirtualMemory(MemorySectionName));
主物理驅動器的產品ID 和序列號(DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY, StorageDeviceProperty));
默認網關的MAC 地址(GetBestRoute - GetIpNetTable);
所有網絡適配器的MAC 地址(GetAdaptersInfo);
安裝的防病毒軟件(root\securitycenter2 - SELECT * FROM AntiVirusProduct);
顯示設備信息(DeviceId、DeviceString、dmPelsWidth、dmPelsHeight、dmDisplayFrequency)(EnumDisplayDevices - EnumDisplaySettings);
活動進程(NtQuerySystemInformation(SystemProcessInformation));
以base64 編碼的屏幕截圖(gdi32 方法);
信標收集過程完成後,Roshtyak將受害者的資料發送到CC服務器。配置文件通過Tor 網絡發送,使用Roshtyak 注入新生成的進程的自定義通信模塊。 CC 服務器處理洩露的配置文件,並可能使用shellcode 有效負載進行響應,以供核心模塊執行。
現在讓我們仔細看看這整個過程。值得一提的是,在生成任何惡意流量之前,Roshtyak 首先會執行Tor 連接檢查。這是通過以隨機順序聯繫28 個合法且知名的.onion 地址並檢查其中至少一個是否響應來完成的。如果他們都沒有回應,Roshtyak甚至不會嘗試聯繫CC,因為它很有可能無法與CC取得聯繫。
至於實際的CC 通信,Roshtyak 包含35 個硬編碼的V2 洋蔥地址(例如ip2djbz3xidmkmkw:53148,請參閱我們的IoC 存儲庫以獲取完整列表)。就像在連接檢查期間一樣,Roshtyak 以隨機順序遍歷它們並嘗試聯繫它們中的每一個,直到其中一個做出響應。請注意,雖然V2 洋蔥地址已被正式棄用,取而代之的是V3 地址,並且Tor 瀏覽器在其最新版本中不再支持它們,但對於Roshtyak的邪惡目的而言,它們的功能似乎仍然足夠。
Roshtyak 的硬編碼CC 地址
受害者配置文件以URL路徑發送,附加在V2洋蔥地址和/字符之後。由於原始概要文件可能包含禁止在url中使用的字符,因此概要文件被封裝在自定義結構中,並使用Base64進行編碼。自定義結構的第一個0x10字節作為加密密鑰,其餘的結構將被加密。自定義結構還包含受害者概要文件的64位哈希,它可能用作完整性檢查。有趣的是,自定義結構的尾部可能填充了隨機字節。注意,完整的路徑可能非常大,因為它包含一個雙base64編碼的截圖。 Roshtyak的開發者可能意識到URL路徑不適合發送大量數據,並決定將受害者配置文件的長度限制在0x20000字節。如果屏幕截圖使洩露的配置文件大於此限制,則不包括在內。
構建完整的洋蔥URL 後,Roshtyak 繼續啟動其Tor 通信模塊。它首先生成一個虛擬進程來託管comms 模塊。這個虛擬進程是隨機選擇的,可以是dllhost.exe、regsvr32.exe 或rundll32.exe 之一。 comms 模塊使用共享段注入到新生成的進程中,並通過前面描述的shellcode 隱藏技巧進行了混淆。然後通過NtQueueApcThreadEx 執行comms 模塊,使用已經討論過的ntdll gadget技巧。注入的comms 模塊是一個開源Tor 庫的自定義構建,包含在三個額外的保護性shellcode 層中。
核心模塊使用共享段作為IPC 機制與comms 模塊進行通信。兩個模塊同步使用具有相同種子(KUSER_SHARED_DATA.Cookie) 的相同PRNG 來生成相同的段名稱。然後,兩者都將此命名段映射到各自的地址空間,並通過讀取/寫入來相互通信。讀取/寫入該段的數據使用RC4 加密(密鑰也使用同步的PRNG 生成)。
核心模塊和通信模塊之間的通信遵循簡單的請求/響應模式。核心模塊將加密的洋蔥URL(包括要洩露的URL 路徑)寫入共享段。 comms 模塊然後解密URL 並通過Tor 向它發出HTTP 請求。核心模塊等待comms 模塊將加密的HTTP 響應寫回共享段。一旦它在那裡,核心模塊將其解密並從自定義格式解包,包括再次解密併計算哈希以檢查有效負載的完整性。解密後的有效載荷可能包含一個供核心模塊執行的shellcode。如果shellcode 存在,核心模塊分配一大塊內存,