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

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

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

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

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

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

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

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

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

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