當前位置:
首頁 > 最新 > 防禦者也在思考可視化(一)

防禦者也在思考可視化(一)

簡介

歡迎來到我們的系列博客的第一部分,題為「Defenders Think in Graphs Too!」。在本系列中,Roberto Rodriguez(@cyb3rward0g)和我(@jaredcatkinson)將通過一個專門研究檢測進程注入的案例來討論我們對數據採集、數據質量和數據分析的看法。這篇文章(第一部分)將討論現有的檢測技術,名為Get-InjectedThread的PowerShell腳本,以確保所有讀者具有相同的基礎知識。在隨後的文章中,我們將通過Get-InjectedThread的數據質量來分析問題,確定如何改進當前腳本,涵蓋與HELK項目的集成以及研究使用可視化技術來改進我們的產品。

線程注入檢測

在去年新奧爾良舉行的SANS威脅狩獵峰會上,Endgame的Joe Desimone和我發布了Get-InjectedThread,這是一個PowerShell腳本,通過檢測機器上的線程來檢測代碼注入。如果您有興趣了解更多有關這種檢測方法的信息,請查看相關視頻或查看我進一步的解釋。對於那些只關註腳本實際運行的用戶,可以查看Get-InjectedThread的演示視頻,PowerShell Empire客戶端遷移到LSASS進程後也能檢測。

與此同時,讓我們看看Get-InjectedThread的實效。本文我們將關注Get-InjectedThread的功能而不是實用程序,因此我們使用良性測試函數作為示例。Joe編寫了一個名為ThreadStart.exe的快速測試二進位文件,它模仿代碼注入行為來測試我們腳本的功能。作為PowerShell迷,我決定在PowerShell中重寫ThreadStart,以使它更易適用於我們的例子。所以第一步是從PowerShell進程中執行New-InjectedThread函數。New-InjectedThread的代碼可以在GitHub上的PSReflect-Functions存儲庫中找到。

讓我們來快速回顧一下New-InjectedThread函數的功能:

·以當前PowerShell進程的Id為參數執行Get-Process cmdlet。生成的System.Diagnostics.Process實例將包含一個稍後使用的進程句柄。

·使用VirtualAllocEx分配內存寫入「惡意」代碼。

·使用WriteProcessMemory將shellcode寫入新分配的內存區域。這一步對於測試是不必要的,但我們目前正在寫MZ作為頭兩位元組來模仿PE頭。

·調用CreateThread並設置CREATE_SUSPENDED標誌並指向VirtualAllocEx分配的內存區域。

·由於我們不再使用它,因此使用CloseHandle關閉線程句柄。

·輸出驗證「惡意」線程檢測所需的信息。

當執行New-InjectedThread時,你會看到類似下圖的結果:

使用New-InjectedThread創建一個測試注入線程

運行New-InjectedThread後,它看起來像我們有一個示例線程來檢測。注意該函數報告「惡意」線程的ProcessId(1008),ThreadId(9220)和Memory Base Address(2144746340352)。

接下來,我們可以在終端上運行Get-InjectedThread,並期望檢測出至少一個代碼注入實例。這與將Get-InjectedThread.ps1載入到當前PowerShell的運行空間並調用不帶參數的Get-InjectedThread函數一樣簡單,如下所示:

使用Get-InjectedThread檢測注入

很棒!Get-InjectedThread檢測到在powershell.exe進程中有注入。經過深入調查,我們注意到ThreadId和BaseAddress欄位與預期的基於New-InjectedThread報告的內容相符。

讓我們花點時間來了解一下Get-InjectedThread如何工作。 Get-InjectedThread是基於Matt Graeber的PSReflect模塊構建的PowerShell腳本。PSReflect將Reflection的複雜性抽象出來,圍繞Win32 API構建函數、枚舉和結構體,供PowerShell在內存中訪問。Get-InjectedThread專門使用PSReflect來收集有關進程、線程、訪問令牌和登錄會話的信息。然後將這些信息組成一個自定義的psobject實例並輸出到PowerShell管道。在下面,可以看到通過PSReflect收集到的信息InjectedThread對象的可視化。

Get-InjectedThread數據結構

對於那些對技術細節感興趣的人,下面是對Get-InjectedThread中細節更加技術性的解釋:

·使用ProcessId 為0(所有進程)並將Flag參數設置為4(TH32CS_SNAPTHREAD)調用Create Toolhelp Snapshot。這將返回所有當前正在運行的線程的快照。

·使用Thread32First和Thread32Next處理快照中的所有線程。

以下每個步驟都將在每個線程上執行:

·調用OpenThread以接收內核中的Thread對象的句柄。

·使用Thread句柄,為ThreadInformationClass參數指定值為9(ThreadQuerySetWin32StartAddress)的NtQueryInformationThread。這將返回線程的內存起始地址。

·調用OpenProcess來接收當前線程擁有進程的句柄。

·將進程句柄和線程起始地址傳遞給VirtualQueryEx以查詢目標內存頁面。這將返回一個MEMORY_BASIC_INFORMATION結構。

·檢查返回結構中的State和Type欄位。

·所有線程的狀態應該是MEM_COMMIT

·所有線程的類型應為MEM_IMAGE

·如果Type不等於MEM_IMAGE,那麼你有一個正在運行代碼的線程,這個線程不會被磁碟上的文件(又名注入)所支持。

針對所有「注入的線程」執行以下步驟:

·使用ReadProcessMemory在BaseAddress中讀取內容。基地址的前100個位元組將從該函數返回。

·使用OpenThreadToken獲取應用於線程的訪問令牌的句柄。如果此函數失敗,請使用OpenProcessToken獲取進程「主」訪問令牌的句柄。默認情況下,如果不使用模擬,線程將使用進程訪問令牌。

·調用GetTokenInformation來查詢有關訪問令牌的信息,例如用戶,特權,模擬級別,完整性級別以及許多其他屬性。

現在,我們都了解了Get-InjectedThread是如何工作的,並且有一個簡單的測試例子來驗證我們的邏輯。

改進注入線程檢測

這個PowerShell腳本的接收量比我預期的要大。讓社區擁有以前專為商業EDR解決方案或重要分析技術(如Memory Forensics)而保留的功能感覺很棒。藉助Get-InjectedThread,任何安全從業人員都可以開始在企業內部尋找內存駐留攻擊。

最近,我開始想著如何改進Get-InjectedThread。我仍然認為底層的功能非常好,但我覺得可以在數據方面做的更多。就目前而言,Get-InjectedThread在微觀層次檢測代碼注入,但在終端上錯過了更大的Context。例如,Get-InjectedThread只會為檢測到已注入的線程返回輸出。這意味著計算資源正在使用,但我們的分析師沒有收到這些數據。如果這些遺漏的數據可用於其他檢測,該怎麼辦?在Get-InjectedThread的情況下,我們必須為其他檢測工作運行一個完全獨立的集合。主要解決方案是不在終端上執行分析工作。相反,收集所有相關數據並轉發到集中日誌源(例如HELK)來進行分析。

結論

多年來,我一直專註於數據收集,Roberto專註於數據分析。我們相信,我們已經整合出一套非常好的方法來處理整個過程的數據。本系列博客是我們的嘗試,通過實際使用案例在社區分享研究結果。在第二部分中,我們將深入探討Get-InjectedThread的問題,並討論如何對腳本集進行改進。之後的博客將從數據質量、相關性和分析角度審視這些數據。本文旨在作為本系列的入門介紹,敬請關注第二部分!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

Volume Shadow 服務在滲透測試中的幾種利用姿勢
Harpoon:一款實用威脅情報工具

TAG:嘶吼RoarTalk |