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

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

第一個(gè)區(qū)域是有趣的,因?yàn)樗雌饋?lái)很像一個(gè)加載的DLL,但是所有的節(jié)是獨(dú)立加載的,不像標(biāo)準(zhǔn)DLL的文件映射,并且明顯使用自定義的loader加載的,而不是標(biāo)準(zhǔn)的Windows loader。分析這些節(jié)能與wininet.dll內(nèi)容對(duì)應(yīng)。

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

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

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

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

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

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

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