大約在一個月前,Shadow Brokers(影子經紀人)泄露了方程式組織(為NSA效力的黑客組織)的軟件FuzzBunch,一個類似于Metasploit的利用框架。這個框架中有幾個針對Windows的未認證的遠程利用(如EternalBlue, EternalRomance和 EternalSynergy)。很多利用的漏洞在MS17-010中被修復了,它可能是近十年來最關鍵的Windows補丁。
提示:你能使用我的MS17-010 Metasploit auxiliary module來掃描你網絡中沒有打補丁的系統。如果沒有安裝補丁,還會檢查是否感染DoublePulsar。
0x01 介紹
DoublePulsar是FuzzBunch中SMB和RDP利用中使用的主要的payload。下面分析是在Windows Server 2008 R2 SP1 x64上使用EternalBlue SMBv1/SMBv2 exploit完成的。
Shellcode基本上執行了下面幾個步驟:
步驟0:判斷x86還是x64。
步驟1: 從KPCR中定位IDT,從第一個中斷處理反向遍歷找到ntoskrnl.exe的基址(DOS MZ頭)。
步驟2:讀取ntoskrnl.exe的導出目錄,并使用哈希(和應用層shellcode類似)來找到ExAllocatePool/ExFreePool/ZwQuerySystemInformation函數地址。
步驟3:使用枚舉值SystemQueryModuleInformation調用ZwQuerySystemInformation,得到一個加載驅動的列表。通過這個定位到Srv.sys,一個SMB驅動。
步驟4:將位于SrvTransaction2DispatchTable[14]的SrvTransactionNotImplemented()函數指針指向自己的hook函數。
步驟5:使用輔助的DoublePulsar payload(如注入dll),hook函數檢查是否正確運行并分配一個可執行的緩沖區來運行原始的shellcode。所有的其他請求直接轉發給原始的SrvTransactionNotImplemented()函數。"Burning" DoublePulsar不會完全擦除內存中hook函數,只是休眠它。
在利用后,你能看到缺少SrvTransaction2DispatchTable符號。在這里應該有兩個處理程序與SrvTransactionNotImplemented符號。這是DoublePulsar后門(數組索引14):

我真的很好奇這個payload,在Countercept的DLL注入代碼分析之外沒有看到很多它的細節。但是我很好奇初始SMB后門是如何安裝的,這也是本文的內容。
使用IA32_LSTAR系統調用MSR(0xc000082)和包含FEFE的Srv.sys的區域的EternalBlue利用中有一些有趣的設置,但是我將專注于原始的DoublePulsar的方法…很像EXTRABACON shellcode,這個非常狡猾并不只是產生一個shell。
0x02 shellcode詳細分析
在shadow brokers的轉儲中你能找到DoublePulsar.exe和EternalBlue.exe。當你使用FuzzBunch中的DoublePulsar,有個選項是將它的shellcode輸出到一個文件中。我們還發現EternalBlue.exe包含了它自己的payload。
步驟0:判斷CPU架構
主payload非常大,因為它包含x86和x64的shellcode。前面一些字節使用操作碼技巧來決定正確的架構(參考我之前的文章匯編架構檢測)。
下面是x86頭幾個字節。

你該注意到inc eax意思是je指令不執行。接著是一個call和pop,獲取正確的指令指針。
下面是x64的:

其中inc eax由rex替換。因此zf標志寄存器由xor eax,eax操作設置。因為x64有RIP相對尋址,不需要獲取RIP寄存器。
X86的payload和x64的基本一樣,所以這里只關注x64。
由于NOP在x64中一個真正的NOP,我使用16進制編輯器用CC CC(int 3)覆寫40 90。中斷3是調試器的軟件斷點。

現在執行利用,我們附加的內核調試器將自動斷點在shellcode開始執行處。
步驟1:找到ntoskrnl.exe的基址
一旦shellcode判斷是在x64上面運行,它將開始搜索ntoskrnl.exe的基地址。代碼片段如下:

相當簡單的代碼。在用戶模式下,x64的GS段包含線程信息塊(TIB),其保存了進程環境塊(PEB),該結構包含了當前運行進程的各種信息。在內核模式中,這個段寄存器包含內核進程控制區(KPCR),其中偏移0處包含當前進程的PEB。
該代碼獲取KPCR的偏移0x38處,是IdtBase并包含一個KIDTENTRY64結構的指針。在x86中很熟悉,能知道這是中斷描述符表。
在KIDTENTRY64的偏移4,你能得到中斷處理的函數指針,其代碼定義在ntoskrnl.exe中。從那里按頁大小(0x1000)增長反向搜索內存中.exe的DOS MZ頭(cmp bx,0x5a4d)。
步驟2:定位必要的函數指針
一旦你知道了PE文件的MZ頭的位置,你能定位到導出目錄,并得到你想要的函數的相對虛擬地址。用戶層的shellcode一直能做到這個,通常是找到ntdll.dll和kernel32.dll的一些必要的函數。只需要和用戶層shellcode一樣,ring0 shellcode也使用哈希算法代替硬編碼字符串,以便找到必要的函數。
下面是要找的函數:
ZwQuerySystemInformation
ExAllocatePool
ExFreePool
ExAllocatePool能用來創建可執行內存區域,并且ExFreePool能用來清理內存區域。這些是重要的,因此shellcode能為它的hook函數和其他函數分配空間。ZwQuerySystemInformation在下一步中是重要的。
步驟3:定位SMB驅動Srv.sys
使用SystemQueryModuleInformation(0xb)調用ZwQuerySystemInformation能實現。得到所有加載的驅動的列表。

Shellcode在這個列表中搜索兩個不同的哈希,定位到Srv.sys,這是SMB運行的主要驅動。

過程和用戶層一樣,通過PEB->Ldr得到,遍歷搜索加載的DLL。這里要查找的是SMB驅動。
步驟4:Patch SMB的trans2派遣表
現在DoublePulsar已經有了主要的SMB驅動,它遍歷.sys的PE節,直到找到.data節。

.data節中通常是全局讀寫內存,在這里存儲著SrvTransaction2DispatchTable,一個處理不同的SMB任務的函數指針數組。
Shellcode分配一些內存并實現函數hook。

接下來shellcode存儲派遣函數SrvTransactionNotImplemented()的函數指針(以便能在hook函數中調用)。然后使用hook覆蓋SrvTransaction2DispatchTable中的這個成員。

后門完成了。現在它返回到它自己的調用棧,并做一些小的清理操作。
步驟5:發送“Knock”和原始的shellcode
當DoublePulsar發送了指定的“knock”請求(被視為不可靠的SMB調用),派遣表調用hook的假的SrvTransactionNotImpletemented()函數。能觀察到奇怪的行為:正常的SMB響應MultiplexID必須匹配SMB請求的MultiplexID,但是增加了delta作為一個狀態碼。
操作能夠隱身,在Wireshark中沒有合適的解析。

狀態碼(通過MultiplexID delta):
0x10 = 成功
0x20 = 不可靠的參數
0x30 = 分配失敗
操作列表:
0x23 = ping
0xc8 = exec
0x77 = kill
你能使用下面的算法得到操作碼:

反之,你能使用這個算法制作包,其中k是隨機生成的:

在一個Trans2 SESSION_SETUP請求中發送一個ping操作將得到一個響應,其中包含需要為exec請求計算的XOR密鑰的一部分。
“XOR密鑰”的算法是:

更多的shellcode能使用Trans2 SESSION_SETUP請求和exec操作發送。使用XOR密鑰作為基本流密碼,一次性在數據包4096字節的“數據payload”部分中發送。后門將分配一塊可執行內存區域,解密復制shellcode并運行。注入dll的payload能注入你想要的DLL。
我們能看見hook被安裝在SrvTransaction2DispatchTable+0x70 (112/8 = index 14)處:

全部的匯編在這里。
0x03 總結
這是一個復雜的多平臺的SMB后門。它是一個非常酷的payload,因為你能感染一個系統,駐留,并能在你想要的時候做更多的事。它在系統中找到了一個很好的隱藏位置,并且不會觸PatchGuard。
通常我們只能在本地漏洞利用看到內核shellcode,因為它會變換進程令牌以便提權。然而,微軟在內核中做了很多網絡相關的事,例如Srv.sys和HTTP.sys。所描述的技術在很多方式完全符合遠程利用中用戶模式的shellcode的操作方式。
當它移植到Metasploit中,我可能不會逐字節復制,而是跳過后門的想法。它不是最安全的,因為它不再是秘密,任何人都可以使用你的后門。
下面是可以代替做的事:
1. 和DoublePulsar相同的方式獲得ntoskrnl.exe地址,并讀取導出目錄獲得必要的函數。
2. 啟動一個隱藏的進程(如notepad.exe)
3. 使用Meterpreter payload插入APC
4. 恢復進程,退出內核
5. ???
6. 收獲
|