.NET框架漏洞後期利用工具——SharpSploit功能詳解
今天,我釋出了 ofollow,noindex">SharpSploit ,這是我過去幾個月以來一直在用C#開發的一系列攻擊工具中的第一個。SharpSploit是一個用C#編寫的.NET框架漏洞後期利用庫,目的是為了突出.NET的攻擊面,並使red teamers更容易的使用和攻擊.NET框架。
SharpSploit的部分名稱是對 Shell/">PowerShellMafia/PowerSploit" rel="nofollow,noindex" target="_blank">PowerSploit 專案的致敬,這也是一款我個人最愛的攻擊工具!雖然SharpSploit確實移植了PowerSploit的某些功能,但我的目的並不是建立一個完全一樣的PowerSploit。SharpSploit將是一個獨立的專案,儘管它與PowerSploit的目標是相似的。
C#的吸引力
在將現有PowerShell工具集移植到C時,安全社群在攻擊性方面似乎正在出現一種趨勢,特別是最近我的SpecterOps隊友釋出的工具,包括: @harmj0y 的GhostPack工具集和 @0xthirteen 的 SharpView 。而SharpSploit則是整個發展趨勢中的一小部分。隨著PowerShell中增加的安全功能(即ScriptBlock Logging,AMSI等),red teamers正在將注意力轉向其他攻擊方式是有一定道理的。而且,C#是PowerShell未來發展過程中合乎邏輯的下一步,它們都是基於.NET框架的,所以將工具集從PowerShell移植到C#是相當容易的。
但是,從攻擊的角度來看,C#並不是沒有它自己的問題。 從Matt Graeber的解釋來看 optics 要出現在.NET裡(點選檢視Matt Graeber的解釋) ,並且從開發人員可用性的角度來看,我們失去了相當多的靈活性,因為我們的程式語言從一個像PowerShell的指令碼語言變成了像C#這樣的編譯語言。
現在,我們還得開始擔心.NET版本的問題。預設情況下,你會在大多數Windows作業系統版本上找到.NET v3.5,但較新的Windows 10和Server 2016系統預設只安裝了.NET v4.0 +。另外的一個“問題”是所有的Windows作業系統版本上都沒有預設啟用.NET,你會發現在Windows Server 2008和早期的伺服器作業系統版本上需要明確啟用.NET。SharpSploit試圖通過使用.NET v3.5和v4.0來解決這個問題,儘可能獲取更多的覆蓋範圍,但是你需要注意要在正確的作業系統上使用正確的版本。
控制檯要還是不要?
你會在SharpSploit和到目前為止已經發布的大多數其他攻擊性的C#庫之間看到的最重要的區別,我的工具沒有SharpSploit.exe,因為SharpSploit被設計為一個“庫”,所以只有一個SharpSploit.dll。
我的目的是讓SharpSploit主要用於安全人員在自己的工具集中引用的庫。但是,我預計此實現會有一些限制,這可能會迫使我最終新增基於控制檯的介面。例如,Cobalt Strike的execute-assembly模組需要應用程式具有EntryPoint(即“main”函式)來執行,因此SharpSploit目前還無法使用Cobalt Strike來輕鬆操作。這是一個很好的例子,說明了在我們從PowerShell過渡到C#時我們必須解決一些靈活性問題。
現在不要太擔心這個問題,你很快就能看到我在這篇文章中描述的執行SharpSploit的一些具有創新性的其他方法。我可能會在某些方面撰寫後續的文章來介紹執行如何方便的執行SharpSploit的功能。
SharpSploit 功能介紹
那麼SharpSploit到底包含了些什麼?我們繼續深入吧!SharpSploit目前包括4個關鍵的高級別名稱空間:Credentials,Enumeration,Execution,和LateralMovement。接下來,我們將逐一介紹每個名稱空間。
SharpSploit.Credentials
該SharpSploit.Credentials名稱空間包含了與憑證處理相關的任何一個類!目前,這包括了Mimikatz的所有功能以及令牌操作。
SharpSploit.Credentials.Mimikatz
SharpSploit.Credentials.Mimikatz類實現了執行任何Mimikatz命令的功能。SharpSploit的這個功能實現使用了 @subtee 的PELoader 的改編版本,並借鑑了 @xorrior 的 實現思路 ,以及載入 @gentilkiwi 開發的優秀專案—— Mimikatz 。
在這裡,我要提及下 @harmj0y 的 SafetyKatz專案 。主要區別在於 SafetyKatz 提供了在lsass.exe的minidump上使用Mimikatz的便利,同時SharpSploit.Credentials.Mimikatz可以讓使用者執行任何Mimikatz命令。
以下是SharpSploit.Credentials.Mimikatz類中實現的主要功能:
·Command() – 使用PE.Load()載入Mimikatz PE並執行選定的Mimikatz命令。
· LogonPasswords()- 使用PE.Load()載入Mimikatz PE並執行Mimikatz命令並從LSASS檢索明文密碼。等價於Command("privilege::debug sekurlsa::logonPasswords")。(需要管理員許可權)
· SamDump() – 使用PE.Load() 載入Mimikatz PE並執行Mimikatz命令並從SAM資料庫中檢索密碼雜湊值。等價於Command("privilege::debug lsadump::sam")。(需要管理員許可權)
· LsaSecrets() – 使用PE.Load()載入Mimikatz PE並執行Mimikatz命令並檢索儲存在登錄檔中的LSA密文。等價於Command("privilege::debug lsadump::secrets")。(需要管理員許可權)
· LsaCache() – 使用PE.Load()載入Mimikatz PE並執行Mimikatz命令並從登錄檔中檢索域快取憑證雜湊值。等價於Command("privilege::debug lsadump::cache")。(需要管理員許可權)
· Wdigest() – 使用PE.Load()載入Mimikatz PE並執行Mimikatz命令並從登錄檔中檢索Wdigest憑證。等價於Command("sekurlsa::wdigest")。
· All()- 使用PE.Load()載入Mimikatz PE並執行上述每個內建的本地憑證轉儲命令。(需要管理員許可權)
· DCSync() – 使用PE.Load()載入Mimikatz PE並執行“dcsync”模組以檢索指定(或所有)Domain使用者的NTLM雜湊值。(需要域管理員許可權(或同等許可權))
· PassTheHash() – 使用PE.Load()載入Mimikatz PE並執行“pth”模組然後以使用NTLM密碼雜湊進行身份驗證的使用者啟動新程序。(需要管理員許可權)
SharpSploit.Credentials.Tokens
SharpSploit.Credentials.Tokens類實現了令牌操作功能,以及依賴於令牌操作更復雜的動作。雖然目前已經建立了許多令牌操作專案,但SharpSploit.Credentials.Tokens的開發過程中多次借鑑了 @0xbadjuju 開發的很棒的 Tokenvator 專案。
以下是SharpSploit.Credentials.Tokens類中實現的主要功能:
· WhoAmI() – 獲取當前使用的或模擬令牌的使用者名稱。
· ImpersonateUser() – 模擬指定使用者擁有的程序的令牌。用於以指定使用者身份執行後續命令。(需要管理員許可權)
· ImpersonateProcess() – 模擬指定程序的令牌。用於以與指定程序的令牌關聯的使用者身份執行後續命令。(需要管理員許可權)
· GetSystem() – 模擬SYSTEM使用者。等價於ImpersonateUser("NT AUTHORITY\SYSTEM")。(需要管理員許可權)
· BypassUAC() – 通過令牌複製繞過UAC並生成具有高完整性的指定程序。(需要管理員許可權)
· RunAs() – 使用指定密碼作為指定使用者執行指定函式的新令牌。RevertToSelf()執行該功能後會自動呼叫。
· MakeToken() – 使用指定的使用者名稱和密碼建立新令牌,並模擬該令牌以指定使用者的身份執行後續的操作。
· RevertToSelf() – 結束模擬任何令牌,恢復到與當前程序關聯的初始令牌。在與模擬令牌功能一起使用並且不自動RevertToSelf功能時非常有用,如:ImpersonateUser(),ImpersonateProcess(),GetSystem(),和MakeToken()。
· EnableTokenPrivilege() – 為指定的令牌啟用指定的安全許可權。(需要管理員許可權)
SharpSploit.Enumeration
SharpSploit.Enumeration名稱空間包含了用作列舉的任何類。目前,這包括了一些基本的基於本地主機的列舉,網路列舉(即ping /埠掃描),以及域和網路列舉。我認為這個名稱空間有很多增加和改進的空間。
SharpSploit.Enumeration.Host
SharpSploit.Enumeration.Host類執行本地基於主機的基本列舉操作。這個類目前實現的是非常基礎的功能。我計劃最終做一些有用的補充功能,但目前還有許多其他更強大的工具,如Seatbelt。
以下是SharpSploit.Enumeration.Host類中實現的主要功能:
· GetProcessList() – 獲取系統上正在執行的程序的列表。
· CreateProcessDump() – 建立正在執行的程序的記憶體的小型轉儲。如果轉儲LSASS程序,會對離線使用Mimikatz很有用。(需要管理員許可權)
· GetHostname() – 獲取系統的主機名。
· GetUsername() – 獲取正在執行的程序的當前域和使用者名稱。
· GetCurrentDirectory() – 獲取當前工作目錄的完整路徑。
· GetDirectoryListing() – 獲取當前工作目錄的目錄列表。
· ChangeCurrentDirectory() – 通過將指定的字串附加到當前工作目錄來更改當前目錄。
· RegistryRead() – 讀取儲存在登錄檔中的值。
· RegistryWrite() – 將值寫入登錄檔。
SharpSploit.Enumeration.Network
SharpSploit.Enumeration.Network類包含了用於網路列舉的TCP ping/埠掃描器。
以下是SharpSploit.Enumeration.Network類中實現的主要功能:
· PortScan() – 對指定的計算機和埠進行埠掃描並報告開啟的埠。
· Ping() – Ping指定的計算機並識別存活的系統。
SharpSploit.Enumeration.Domain
SharpSploit.Enumeration.Domain類提供了Active Directory域列舉庫。這是 @harmj0y 的 PowerView 專案的部分C#實現。
這個類不打算成為PowerView的直接或完整實現,有很多東西的格式和實現方式也不同。我還應該提到 @0xthirteen 的 SharpView 專案,它的目標是成為PowerView更直接或更完整的C#實現。
SharpSploit.Enumeration.Domain.DomainSearcher
SharpSploit.Enumeration.Domain.DomainSearcher類的功能有助於使用一組憑證搜尋特定的AD域。
與使用PowerView相比,這是你在使用SharpSploit.Enumeration.Domain時會注意到的第一個主要差異。PowerView功能可以作為“靜態”函式獨立執行,符合PowerShell作為指令碼語言的性質。SharpSploit包含了面向物件程式語言(如C#)的本質。你需要建立一個DomainSearcher物件,該物件需要設定為使用一組特定的憑據搜尋特定域,並在該DomainSearcher物件上呼叫特定的列舉函式。
DomainSearcher類包含了下列主要功能:
· GetDomainUsers()- 獲取DomainObject當前域中指定(或所有)的使用者列表。
· GetDomainGroups()- 獲取DomainObject當前域中指定(或所有)的使用者組的列表。
· GetDomainComputers()- 獲取DomainObject當前域中指定(或所有)的計算機列表。
· GetDomainSPNTickets()- 獲取指定的DomainObjects的SPNTicket。
· Kerberoast()- 獲取SPNTicket在當前域中設定了SPN的指定(或所有)的使用者列表。
SharpSploit.Enumeration.Net
SharpSploit.Enumeration.Net類依舊是PowerView的部分C#實現,並且包括了通過使用Windows API函式(類似於Windows 本地的“NET.EXE”實用程式)列舉在遠端計算機上的本地使用者,使用者組,登入和會話的功能。需要注意的一點是不支援PowerView中針對“WinNT”的列舉功能。
SharpSploit.Enumeration.Net類包括了以下主要功能:
· GetNetLocalGroups()-從指定的遠端計算機上獲取LocalGroup 列表。
· GetNetLocalGroupMembers()-從指定的計算機組中的指定遠端計算機上獲取LocalGroupMember 列表。
· GetNetLoggedOnUsers()-從指定的遠端計算機上獲取LoggedOnUser 列表。
· GetNetSessions()-從指定的遠端計算機上獲取SessionInfo 列表。
SharpSploit.Execution
SharpSploit.Execution 名稱空間包含了與執行相關的任何類。目前的功能有 PE 載入, .NET 程式集和 shell / powershell 命令。
SharpSploit.Execution.Assembly
SharpSploit.Execution.Assembly 類包括了用於載入 .NET 元件和通過反射在元件內執行功能的方法。
SharpSploit.Execution.Assembly 類包括了以下主要功能:
· Load() – 載入 .NET 程式集位元組陣列或 base64 編碼的位元組陣列。
· AssemblyExecute() – 載入 .NET 程式集位元組陣列或 base64 編碼的位元組陣列,並使用反射在指定型別中使用指定的引數執行指定的方法。
SharpSploit.Execution.PE
SharpSploit.Execution.PE 這個類計劃是用於載入任意的 PE 檔案。目前,它實際上只作為 Mimikatz PE 的載入器。這個類是 @subtee 的 PE 載入器的改編版本,用於支援任意 PE 檔案的載入。順便提醒一下,我在使用這個類的時候沒有成功的載入過任意 PE 檔案,所以你的實際操作可能和我的會有所不同。我希望這個類的功能最終能夠得到充分實現。
SharpSploit.Execution.PE 類包括了以下主要功能:
· Load() – 使用指定的位元組陣列載入 PE 。(需要管理員許可權)
· GetFunctionExport() – 獲取指向已載入的 PE 中匯出函式的指標。之後,指標可用於執行 PE 中的功能。
SharpSploit.Execution.Shell
SharpSploit.Execution.Shell 類包括了用於執行“ Shell ”( cmd.exe )命令和 PowerShell 命令和指令碼的的方法。可以作為備用使用者來執行 shell 命令(假設你具有有效的密碼),類似於在 Windows 本地檔案中的 runas.exe 可執行檔案。
這個 PowerShellExecute() 功能讓我感到特別興奮。預設情況下, PowerShellExecute() 函式使用了 @mattifestation 的 AMSI 繞過方式和 @tifkin_ 的 PowerShell 日誌記錄繞過方式(繞過 ScriptBlock 日誌記錄和模組日誌記錄)。以前通過 PowerShell 執行某些型別的繞過的時候會遇到繞過方式本身被記錄或被 AMSI 掃描的問題,這就造成了一些是“先有的雞”還是“先有的蛋”的問題。通過使用 C# ,我們可以在執行任何 PowerShell 之前在 C# 中執行這些繞過,從而實現無日誌和無 AMSI 的 PowerShell 執行!
SharpSploit.Execution.Shell 類包含了以下主要功能:
· PowerShellExecute() – 使用 System.Management.Automation.dll 執行指定的 PowerShell 程式碼,並繞過 AMSI , ScriptBlock 日誌記錄和模組日誌記錄(但不轉錄日誌記錄)。
· ShellExecute() – 執行指定的 Shell 命令,可選擇使用備用使用者名稱和密碼。等價於 ShellExecuteWithPath(ShellCommand, "C:\\WINDOWS\\System32")
· ShellExecuteWithPath() – 從指定目錄執行指定的 Shell 命令,可選擇使用備用使用者名稱和密碼。
SharpSploit.Execution.ShellCode
SharpSploit.Execution.ShellCode 類包括了用於執行 shellcode 的方法。 Shellcode 執行是通過將其複製到固定記憶體,使用 Win32.Kernel32.VirtualProtect() 修改記憶體許可權並通過 .NET delegate 來完成執行。該類是在 @enigma0x3 編寫的程式碼上實現的。
SharpSploit.Execution.ShellCode 類包括了以下主要功能:
· ShellCodeExecute()- 通過將指定的 shellcode 位元組陣列複製到固定記憶體,使用 Win32.Kernel32.VirtualProtect() 修改記憶體許可權並使用 .NET delegate 來執行指定的 shellcode 位元組陣列。
SharpSploit.Execution.Win32
SharpSploit.Execution.Win32 是一個比較大的庫,其中包含了 SharpSploit 的各種功能中使用的 Win32 API 函式的 PInvoke 簽名和結構。 www.pinvoke.net 是實現此類的寶貴資源。我不會在本文中記錄所有的簽名,但你可以在 Win32.cs 檔案中檢視這些簽名。
SharpSploit.LateralMovement
SharpSploit.LateralMovement 名稱空間包括了允許在遠端計算機上執行任何型別的程式碼的類。目前,只有 WMI 橫向移動的功能,但其他的功能將很快到來 !
SharpSploit.LateralMovement.WMI
SharpSploit.LateralMovement.WMI 類包含了基本的 WMI 橫向移動功能。目前,唯一的功能是使用 WMI 的 Win32_Process.Create 方法並指定使用者名稱和密碼在遠端系統上生成程序。
SharpSploit.LateralMovement.WMI 類目前僅包括下列主要功能:
· WMIExecute() – 使用 Win32_Process 並指定登入憑據在遠端系統上建立程序。
測試和文件
有關SharpSploit的完整的文件,請訪問 https://sharpsploit.cobbr.io/api/index.html !
SharpSploit專案還包括了SharpSploit.Tests,單元測試萬歲!我沒有在這些單元測試中實現完全覆蓋,但我仍在努力。我認為,如果我們作為一個安全社群可以嘗試升級我們的軟體開發遊戲幷包含攻擊性專案的單元測試,那將是極好的。它們提供了很好的示例,向其他人說明了該如何使用我們的工具集,同時提升了程式碼質量,並對貢獻者很有用。
更多待辦事項
本文只是SharpSploit的一個開始!你會注意到我在上面的描述中提到了很多需要在SharpSploit中實現的補充功能。我打算繼續努力和維護SharpSploit,所以希望你很快就能看到很多的更新功能。
.NET 防禦
本文確實是一個通過介紹SharpSploit 來闡述.NET攻擊的文章,但是至少我會談及.NET的防守面。在進行了一些自我教育之後,我會計劃一個更全面的防禦性部落格文章作為後續的跟進。
要開始討論.NET的防禦,澄清術語很重要。我在這篇文章中幾乎可以互換的使用“.NET”和“C#”,但是這裡有一個微妙的區別。.NET框架是Windows的“託管程式碼”的庫和執行時。“託管程式碼”是編譯為CIL(通用中間語言,以前稱為“MSIL”)的任何程式碼,將由CLR(公共語言執行時)管理,它是.NET框架的執行時並將CIL轉換為“原生”的機器程式碼。C#是使用編譯為CIL的託管程式碼的語言示例。此外,C#專門針對.NET而建立,它的物件模型與.NET物件模型是對齊的。其他可以編譯為CIL的語言(因此可以在.NET框架下執行)包括VB.NET和JScript.NET。
因此,雖然我們從攻擊性方面談了很多關於C#的內容,但從防守的角度來看,我們真正關心的是.NET。具體來說,我們關心的是CLR解釋的CIL程式碼。有一個壞訊息是,傳統上,防禦者對.NET程式碼中發生的事情沒有多少視角。即使他們這樣做,也可能很難識別出惡意的.NET。事實上,在 @blowdart 釋出的 這條推文 中,首先讓我對攻擊性.NET感到興奮:
好訊息是,這似乎正在發生變化。我在本文的開頭提到了這一點,但似乎.NET optics目前正在開發中(由@mattifestation發現):
但是,據我所知,微軟尚未就如何利用這些optics提供官方指導。雖然希望我們能得到一些指導和檔案,但似乎這些工作仍在進行中。
沒有這些optics,我們還有其他選擇嗎?好訊息是,在某些時候沒有磁碟讀寫的情況下執行.NET的方法仍然很少。如果你可以從磁碟恢復.NET程式集,很容易將程式集逆向為原始碼並開始識別關鍵指標(CIL程式碼仍然是位元組碼!)。
執行惡意.NET程式集的最簡單和最流行的方法是利用System.Reflection.Assembly.Load()方法。那麼攻擊者將如何執行此方法來啟動惡意的.NET程式集呢?通常情況下,無論是通過powershell.exe還是通過基於scriptlet的執行技術,例如regsvr32.exe和wmic.exe( @tiraniddo 開發的 DotNetToJScript 專案中有相應的示例程式碼)。雖然這些基於scriptlet的技術確實能夠執行遠端託管的scriplet,但這仍然導致scriptlet在可預測的位置下進行磁碟讀寫,路徑是%LOCALAPPDATA%\Microsoft\Windows\Temporary Internet Files\(我不確定所有的red teamers是否都已經明白)。這是脫離了powershell.exe在不進行磁碟讀寫的情況下執行.NET程式集的最後一種真正可用的方式,PowerShell具有出色的日誌記錄功能,可確保你在ScriptBlock日誌中捕獲程式集!從磁碟或日誌中捕獲元件後,你將能夠輕鬆地對其進行逆向並使用.NET偵錯程式(例如 dnSpy )進行原始碼分析。
我希望這是一個像樣的,而不是簡短的描述如何檢測惡意的.NET。再次說明,一旦我進一步的進行了自我教育,我會嘗試在後續發表更詳細的文章。
結論
本文只是SharpSploit的一個開始!你會注意到我在上面的描述中提到了很多需要在SharpSploit中實現的補充功能。我打算繼續努力和維護SharpSploit,所以希望你很快就能看到很多的更新功能。
我希望其他人能夠覺得SharpSploit確實有幫助,特別是那些試圖從PowerShell多樣化他們的工具集的人。正如我在本文開頭所暗示的那樣,SharpSploit是我在過去幾個月裡一直在開發的一系列C#工具中的第一個,所以期待在這裡看到更多!
信任和感謝
我辜負了很多人的信任。SharpSploit的功能中幾乎沒有一個是真正的原創作品。SharpSploit移植了其他人用PowerShell編寫的許多模組,利用其他人發現的技術,並借用了其他C#專案的想法和程式碼。話雖如此,但我還是要感謝以下人員為該專案做出的貢獻:
· Justin Bui( @youslydawg ) – 貢獻了SharpSploit.Enumeration.Host.CreateProcessDump()功能。
· Matt Graeber( @mattifestation ),Will Schroeder( @harmj0y )和Ruben( @FuzzySec ) – 感謝他們在 PowerSploit 上的付出和分享。
· Will Schroeder( @harmj0y ) – PowerView 專案。
· Alexander Leary( @0xbadjuju ) – Tokenvator 專案。
· James Foreshaw( @tiraniddo ) – 因為他發現了 這裡記錄 的令牌複製繞過UAC的技術。
· Matt Nelson( @enigma0x3 ) – 用於令牌複製繞過UAC的 Invoke-TokenDuplication 實現,以及他的C# 執行shellcode的方法。
· Benjamin Delpy( @gentilkiwi ) – 為 Mimikatz 專案。
· Casey Smith( @subtee ) – C# PE載入器。
· Chris Ross( @xorrior ) – 他在 這裡公佈 了Mimikatz PE載入器的實現。
· Matt Graeber( @mattifestation ) – 他 在這裡公佈 了AMSI繞過方法。
· Lee Christensen( @tifkin_ ) – 他 在這裡公佈 了PowerShell日誌記錄繞過方法。
· www.pinvoke.net 的所有貢獻者- 大部分PInvoke簽名。