【网络安全】Metasploit生成的Shellcode的导入函数解析以及执行流程分析(2)
密碼破解的利器——彩虹表(rainbow table)
確定 shellcode 依賴于哪些導入將使研究人員進一步了解其其余邏輯。不用動態分析shellcode,并且考慮到研究人員已經弄清楚了上面的哈希算法,研究人員可以自己構建一個彩虹表。
彩虹表是一個預先計算好的表,用于緩存加密哈希函數的輸出,通常用于破解密碼哈希。
以下 Python 代碼段計算位于最常見系統位置的 DLL 導出的“Metasploit”哈希值。
例如,下面的PowerShell命令生成一個彩虹表,然后搜索下圖中首先觀察到的726774Ch哈希值。為了方便大家,研究人員發布了包含 239k 哈希值的 Rainbow.csv 版本。
如上所述,shellcode解析并調用的第一個導入是LoadLibraryA,它由32位和64位kernel32.dll導出。
執行流程分析
將導入解析排序后,理解剩余的代碼變得更加容易。如下圖所示,shellcode開始執行以下調用:
在?處LoadLibraryA確保ws3_32庫加載,如果還沒有加載,它將映射內存中的ws3_32.dll DLL,使shellcode能夠進一步解析與Windows Socket 2技術相關的附加函數。
在?處,WSAStartup在 shellcode 的進程中啟動套接字的使用。
WSASocketA 在?處創建一個新的套接字,這將是一個基于流(SOCK_STREAM)的IPv4套接字(AF_INET)。
套接字初始化的反匯編
創建套接字后,shellcode 繼續調用 ? 處的連接函數,并使用先前進入堆棧 (?) 的 sockaddr_in 結構。 sockaddr_in 結構包含從事件響應角度看的有價值的信息,例如協議(0x0200 是 AF_INET,又名 IPv4,小端)、端口(0x115c 是大端的默認 4444 Metasploit 端口)以及 C2 IPv4 地址?(0xc0a801ca 在大字節序中是 192.168.1.202)。
【網絡安全學習資料】
如果連接失敗,shellcode 最多重試 5 次(在 ? 處定義的計數器在 ? 處遞減),之后它將使用 ExitProcess (?) 中止執行。
如果連接成功,shellcode 將創建一個新的 cmd 進程并將其所有的標準錯誤、輸出和輸入(?)連接到已建立的 C2 套接字。進程本身是通過 ? 處的 CreateProcessA 調用啟動的。
逆向shell
最后,當進程運行時,shellcode執行以下操作:
通過調用 WaitForSingleObject 在 ? 處無限期等待遠程 shell 終止;
終止后,使用 GetVersion 在 ? 處識別 Windows 操作系統版本,并使用 ExitProcess 或 RtlExitUserThread 在 ? 處退出;
終止shellcode
總的來說,Metasploit 的 windows/shell_reverse_tcp shellcode 的執行流程架構如下:
Metasploit的TCP逆向shell執行流
Shellcode被中斷
在完成了執行流分析之后,讓我們看看如何在 shellcode 上打開表格并破壞它。從攻擊者的角度來看,shellcode 本身被認為是可信的,而它運行的環境是被污染的。本節將假設研究人員不知道 shellcode 在內存中執行的位置,因此,掛鉤/修改 shellcode 本身不是一個可接受的解決方案。
接下來,我們在介紹概念驗證實現之前,會首先介紹一些理論方面的內容。
【網絡安全學習資料】
CWE-1288:輸入一致性驗證不當
當接收一個包含多個元素或字段的復雜輸入時,這些元素或字段必須彼此一致,但它不驗證或不會很正確地驗證輸入是否實際一致。
從shellcode的角度來看,只有兩個外部交互提供了一個可能的攻擊面。第一個也是最明顯的表面是C2通道,在這個通道中,一些安全解析方案可以檢測/削弱通信協議或周圍的API調用。然而,這種攻擊表面有大量的警告,安全解析方案必須區分合法和惡意行為,可能會導致一些中等/低置信度的檢測。
第二個不太明顯的攻擊面是導入解析本身,從shellcode的角度來看,它依賴于外部進程數據。在這個導入解析例程中,研究人員觀察到 shellcode 如何依賴 BaseDllName 屬性為每個模塊生成哈希。
哈希例程檢索Buffer和MaximumLength以哈希模塊的BaseDllName
雖然模塊的導出是以 UTF-8 NULL 結尾的字符串,但 BaseDllName 屬性是一個 UNICODE_STRING 結構。此結構包含多個屬性:
Length:存儲在Buffer中的字符串的長度,以字節為單位;
MaximumLength:緩沖區的長度,以字節為單位;
緩沖區:指向用于包含寬字符字符串的緩沖區的指針;
……
如果字符串以null結尾,Length不包括末尾的空字符。
MaximumLength 用于指示 Buffer 的長度,以便在將字符串傳遞給 RtlAnsiStringToUnicodeString 等轉換例程時,返回的字符串不會超過緩沖區大小。
【網絡安全學習資料】
雖然上文沒有明確提到,但我們可以隱約地感覺到緩沖區的MaximumLength屬性與實際字符串的Length屬性無關。Unicode字符串不需要消耗整個Buffer,也不能保證以null結束。理論上,Windows API應該只考慮Buffer的第一個Length字節進行比較,忽略Length和MaximumLength位置之間的任何字節。增加UNICODE_STRING的緩沖區(buffer和MaximumLength)不應該影響依賴于存儲字符串的函數。
由于shellcode的哈希例程依賴于緩沖區的MaximumLength,不同大小的緩沖區中的類似字符串將生成不同的哈希。哈希例程中的這個漏洞可以用來消除潛在的Metasploit shellcode。從技術角度來看,由于安全解決方案已經掛鉤進程創建并自我注入,因此可以通過增加 Metasploit 所需模塊的 BaseDllName 緩沖區(例如:kernel32.dll)來在不知道其存在或位置的情況下干擾哈希例程。
研究人員接下來將利用這個哈希輸入驗證漏洞作為初始向量來導致拒絕服務和執行流劫持。
CWE-823:使用超出范圍的指針偏移
該程序對有效指針執行指針運算,但它使用的偏移量可以指向結果指針的預期有效內存位置范圍之外。
研究人員之前所做的一個觀察是 shellcode 如何無限循環模塊,直到找到匹配的導出。當他們發現一個改變哈希值的漏洞時,就試著分析如果所有哈希值都不匹配會發生什么情況。
當遍歷雙鏈表可以無限循環時,shellcode將在檢查所有模塊后實際生成一個“Access Violation”錯誤。此異常不是由shellcode生成的,而是由于代碼沒有驗證列表的邊界而發生的。鑒于對于列表中的每個項目,BaseDllName.Buffer 指針都是從偏移量 0x28 加載的,一旦研究人員訪問列表中的第一個非 LDR_DATA_TABLE_ENTRY 項目,就會發生異常。如下圖所示,一旦 shellcode 循環回到第一個 PEB_LDR_DATA 結構,就會出現這種情況,在這個階段會發生越界讀取,導致無效指針被取消引用。
遍歷InMemoryOrderModuleList雙鏈表時的越界讀取
雖然從防御的角度來看,導致拒絕服務比執行 Metasploit shellcode 更好,但讓我們看看如何進一步利用上述漏洞為防御者提供優勢。
濫用CWE-1288劫持執行流
【網絡安全學習資料】
我們感興趣的一個模塊是kernel32.dll,正如之前在“執行流分析”部分所分析的,它是調用 LoadLibraryA 函數所需的第一個模塊。在哈希例程中,kernel32.dll哈希被計算為0x92af16da。通過應用上述緩沖區調整技術,研究人員可以確保 shellcode 循環附加模塊,因為原始哈希不會匹配。至此,安全解決方案有幾個選項:
研究人員注入的安全解析方案的DLL可以命名為kernel32.dll。雖然它的哈希值是匹配的,但兩個名為kernel32.dll的模塊可能會對LoadLibraryA的合法調用產生意想不到的后果。
有兩個名為 kernel32.dll 的模塊可能會對 LoadLibraryA 的合法調用產生意想不到的后果。
同樣,由于研究人員已經在 LDR_DATA_TABLE_ENTRY 結構中修改緩沖區,但卻可以輕松保存 kernel32.dll 緩沖區的原始值并將它們分配給研究人員的安全解決方案的注入模塊。雖然這在理論上可行,但如上所述,在內存中有一個被稱為kernel32.dll的第二個緩沖區,這很容易引起運行風險。
另外,研究人員的安全解決方案的注入模塊可以有不同的名稱,只要與原始哈希存在哈希沖突。這種技術不會影響諸如 LoadLibraryA 之類的合法調用,因為它們依賴于基于值的比較,而不是 shellcode 的基于哈希的比較。
研究人員之前觀察到 Metasploit shellcode 如何使用 ASCII 字符(1 字節)的添加和旋轉來執行哈希。以下模式描述了 KERNEL32.DLL 在第三個循環中的哈希狀態,其中 ASCII 字符 K 和 E 重疊。可以看到,NULL字符是對最初是Unicode字符串(2字節)的字符串執行1字節操作的直接結果。
第一個和第三個ASCII字符重疊
為了獲得哈希沖突,研究人員需要識別在不改變結果哈希的情況下對初始KERNEL32.DLL字符串所執行的更改。下圖強調了第一個和第三個ASCII字符之間的6位關系。通過減去第一個字符的第二位,我研究人員可以增加第三個字符的第八位(2+6),而不影響得到的哈希值。
第一個和第三個ASCII字符之間的哈希沖突
雖然上面的沖突是不實際的(ASCII或Unicode字符0xC5不在字母數字范圍內),但研究人員可以應用相同的原則來識別可接受的關系。假設研究人員不改變字符串的長度,以下 Python 代碼片段會暴力破解 KERNEL32.DLL 字符串的 Unicode 字符之間的關系。
如上所述,可以修改多個字符對以導致哈希沖突。例如,在Unicode位置0和11處的字符之間存發生了 2 位左移。
【網絡安全學習資料】
如果左移2位類似于乘以 4的結果,則位置 0 處的 Unicode 字符增加任何值都需要將位置 11 處的字符減少 4 倍相同的值,以保持 Metasploit 哈希不變。以下 Python 命令突出顯示了 KERNEL32.DLL 的這兩個字符之間的不同組合。
這種哈希沖突與緩沖區調整大小技術相結合,可以鏈接起來,以確保研究人員的自定義 DLL 在哈希例程中作為KERNEL32.DLL進行計算。現在,如果研究人員導出 LoadLibraryA 函數,則Metasploit 導入解析將錯誤地調用研究人員的實現,從而導致執行流程劫持。可以利用此劫持向安全解決方案發出高置信度 Metasploit 導入解析發生的信號。
概念證明
為了驗證上述理論,首先需要構建一個概念驗證 DLL,一旦加載,它將使用 CWE-1288 來模擬 EDR(終端檢測和響應)解決方案如何在不知道其內存位置的情況下檢測 Metasploit,不過為了利用上述哈希沖突,研究人員的 DLL 將被命名為 hernel32.dlx。
該概念驗證目前已經發布在NVISO的GitHub存儲庫中了。
進程注入
為了模擬安全解析方案如何被注入到大多數進程中,讓我們構建一個簡單的函數,它將在我們選擇的進程中運行研究人員的 DLL。
Inject函數將誘使目標進程加載一個特定的DLL(研究人員的hernel32.dlx)并執行其 DllMain 函數,研究人員將在此處觸發緩沖區大小調整。雖然存在多種技術,但我們只需將DLL的路徑寫入目標進程,然后創建一個調用LoadLibraryA的遠程線程即可。最后這個遠程線程將加載我們的DLL,就像目標進程一樣。
可能有人會注意到,上面的代碼依賴于hPayload變量。這個變量將在DllMain函數中定義,因為研究人員的目標是獲得當前DLL的模塊,而不管其名稱如何,而 GetModuleHandleA 將要求研究人員對 hernel32.dlx 名稱進行硬編碼。
導出 Inject 方法后,研究人員現在可以繼續構建觸發 CWE-1288 所需的邏輯。
【網絡安全學習資料】
緩沖區大小調整
可以使用以下邏輯完成從 kernel32.dll 模塊調整 BaseDllName 緩沖區的大小。與 shellcode 的技術類似,研究人員將恢復 PEB,遍歷 InMemoryOrderModuleList,一旦找到 KERNEL32.DLL 模塊,將其緩沖區增加 1。
最好在注入發生后盡快觸發此邏輯,雖然這可以通過TLS鉤子來完成,但為了簡單起見,研究人員將更新現有的 DllMain 函數以在 DLL_PROCESS_ATTACH 上調用 Metasplop。
分析的shellcode只有依賴于LoadLibraryA,才能使構建得以實現,它將簡單地發出Metasploit警報,然后終止當前的惡意進程。下面的函數只會被shellcode觸發,它本身不會從研究人員的 DLL中被調用。
上述方法可以用于其他變體,如LoadLibraryW、LoadLibraryExA和其他變體。
準備好模擬安全解決方案后,就可以繼續演示了。現在將首先執行 Shellcode.exe,這是一個簡單的 shellcode 加載程序(如下圖所示)。這個 shellcode 加載程序提到它的進程ID(研究人員將其作為注入的目標),然后等待它需要執行的 shellcode 路徑。【網絡安全學習資料】
一旦我們知道shellcode在哪個進程中運行,我們就可以注入模擬的安全解析方案(如下圖的右側所示)。此過程通常由每個過程的安全解決方案執行,為了簡單起見,僅在研究人員的 PoC 中手動完成。使用研究人員的自定義 DLL,我們就可以使用以下命令注入所需的進程,其中 hernel32.dlx 的路徑和進程 ID 已進行了匹配。
手動模擬未來惡意進程的注入
執行注入后,Shellcode.exe 進程已被暫存(調整模塊緩沖區大小,加載沖突 DLL),以便在任何 Metasploit shellcode 運行時利用 CWE-1288 漏洞。值得注意的是,在此階段,沒有加載任何 shellcode,也沒有為其分配任何內存。這就確保了我們遵守了研究人員不知道 shellcode 在哪里執行的假設。
【網絡安全學習資料】
注入研究人員的模擬安全解決方案后,我們可以繼續向即將成為惡意的 Shellcode.exe 進程(下圖的左側)提供初始生成的 shellcode(在研究人員的示例中為 shellcode.vir)的路徑。
執行由 stager 執行的惡意 shellcode
一旦shellcode運行,我們就可以在下圖中看到如何調用LoadLibraryA信號函數,從而對基于shellcode的導入分辨率進行高置信度檢測。
將輸入驗證漏洞和哈希沖突鏈接起來向殺毒軟件發出信號
總結
本文重點介紹了Metasploit shellcode的剖析,并著重介紹了動態導入解析。在這個動態導入解析方案中,我們又發現了兩個漏洞,其中一個可以用來準確識別運行時Metasploit shellcode。
【網絡安全學習資料】
總結
以上是生活随笔為你收集整理的【网络安全】Metasploit生成的Shellcode的导入函数解析以及执行流程分析(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【网络安全】Metasploit 生成的
- 下一篇: 常见的安全应用识别技术有哪些?