和很多安全行業從業者一樣,這些天我們忙于Shadow Brokers泄漏的實現研究和檢測。其中有大量有趣的內容,尤其是DOUBLEPULSAR payload引起了我們的注意。因為它是一個非常穩定的內核模式的payload,是很多漏洞利用的默認的payload。另外,它能注入任意的DLL到用戶層的進程中。我們也確認了一個潛在的有用的特征,以檢測這種技術是否用于主機(需要未重啟)上。
我們尤其感興趣我們的EDR軟件是否能檢測出這種代碼注入,以便更好的保護我們的用戶。很多安全行業的人都在測試注入Meterpreter DLL和其他公開的框架,我們也這么做了,并且確認了我們能檢測到這種注入的DLL和線程。然而,類似Meterpreter移植體在內存中的噪點非常多,我們不確定我們是否只能檢測特定的公開的反射加載的技術,或者我們是否能檢測到通用的DOUBLEPULSAR注入技術。
0x01 細節
首先,我們研究了通過它使用的機制能否注入任意的DLL,而不是像很多公開的利用框架使用的反射加載技術需要特殊構造的DLL。我們嘗試注入一個標準的Windows DLL(wininet.dll)到calc.exe進程中,同時使用Sysinternals的進程監控工具監控,并使用Windbg分析注入前后的目標進程的地址空間,同時還是用了我們EDR軟件。

正如我們所見,wininet.dll成功加載了,因為它加載了依賴的DLL,如normaliz.dll、urlmon.dll等。然而,在那之前沒有什么可觀察的行為,沒有wininet自身的加載,意味著它必須使用內存技術加載。另外,我們也看到了EDR軟件報告的兩種反射dll加載技術,以確認了內存DLL注入技術。通過在windbg中比較注入前后的地址空間,我們很快能發現一些有趣的區域,與我們報告的可疑的內存區域對應。

第一個區域是有趣的,因為它看起來很像一個加載的DLL,但是所有的節是獨立加載的,不像標準DLL的文件映射,并且明顯使用自定義的loader加載的,而不是標準的Windows loader。分析這些節能與wininet.dll內容對應。

第二個感興趣的是對應原始wininet整個內容的單獨區域。奇怪的是,有個區域在這之前也分配了PAGE_EXECUTE_READWRITE,并且是個更大的內存但內容幾乎都是0,除了內存中23字節的小內存塊。

盡管在我們的EDR軟件中也能看到這些,這很明顯是一種不同于各種利用框架中和已知的惡意軟件家族中的標準公開技術的高級技術,我們很想知道它是如何工作的,因此我們進一步深入分析。
另外,我們還解密了C2通信流量,它使用簡單的4字節XOR算法,我們最近公布了一個python腳本來完成解密。我們使用這個轉儲了使用DOUBLEPULSAR注入DLL時發給服務器的整個payload。進一步分析,我們發現了接近4885字節的內核代碼,接著是逐字節的wininet的副本。我們假設這是一些必要的機制,目的是為了將內核空間中任意的DLL隱蔽的加載到用戶模式的進程中,因此我們逆向了這個payload。下面是payload的每部分的細節。

在一些標準函數序言后,payload調用了下面的函數,很明顯是遍歷內存,直到找到MZ頭為止(0x5a4d)。這用于定位內核內存中的ntoskrnl.exe。然后使用作為指針,開始動態定位需要的內核函數,它使用了下面的函數:

這個函數使用4字節的哈希來定位感興趣的函數。這和其他的shellcode技術很類似,而不是硬編碼函數名字字符串來定位函數。哈希處理如下:

我們使用python實現哈希算法,基于所有的內核函數生成一個哈希查詢表,并使用這個來記錄解析后期需要的函數。這個查詢過程和注釋如下:

繼續解析另外一些函數,但是在這里我們做了一個假設,它將枚舉進程以找到要注入的目標進程,然后使用ZwAllocateVirtualMemory和KeInsertQueueApc組合注入用戶層的DLL到目標進程中,然后通過APC執行代碼。

在這里我們跳過了一些無趣的細節但是是必要的,在內核中定位函數的過程如下:
枚舉運行的進程
檢查進程名得到想要的目標
附加到進程中,提取命令行參數,檢查得到想要的目標
在目標進程中使用PAGE_EXECUTE_READWRITE屬性分配內存
在內存中寫入0x12458a字節,來自后面的內核payload(起始于“SUWVATUAA”)
|