Jump to content

我們會在本文中介紹基於簽名的檢測和基於行為的檢測之間的主要區別。此外,還會舉例說明了繞過各個檢測的示例。

經常會有人有疑問,為什麼在有關Packer(封隔器)被發布後,MSF- 或CobaltStrike- (CS)有效負載仍然會被檢測到。答案無非有兩種:

1.基於簽名的檢測被繞過了;2.基於行為的檢測被觸發並終止進程。

使用我們的自定義封隔器將導致反掃描。被封隔的MSF有效負載如下:

1.JPG

但這並不意味著,在運行時執行時,這些殺毒程序不會檢測到有效負載。為什麼會出現這種情況?

基於簽名的檢測基於簽名的檢測非常簡單。最早的殺毒程序有一個帶有File-Hashes的簽名數據庫,他們只是將磁盤上任何可執行文件的哈希與已知的惡意可執行程序哈希進行比較。例如,該數據庫包含Mimikatz發布二進製文件的SHA1/MD5哈希。改變一個可執行文件的哈希值就像操縱其中的一個字節一樣簡單,所以這種檢測並不可靠。

基於這一事實,安全供應商轉而檢測特定的字節模式(BytePattern)簽名。因此,為了繼續使用Mimikatz的示例,具體的字節模式/十六進制值被標記如下:

2.png

可以看到,不僅要為每個已知的惡意二進製文件/有效負載標記一個模式,而且要使用多個常見模式。 Mimikatz始終是基於簽名的檢測的一個很好的示例,因為通常供應商有幾十種Mimikatz二進制檢測的模式。通過這種方式,稍微修改過的版本也能被檢測到。

甚至可以使用yara規則構建更高級的檢測。這些規則可以掃描文件或內存內容,並允許更複雜的條件和不同模式的組合。 Mimikatz yara規則的一個示例如下:

3.png

在本示例中,如果在文件或內存中找到上述三個字符串,則會觸發此規則,AV/EDR程序可以執行警報或終止進程等操作。例如,我們在構建自定義Mimikatz二進制代碼的文章中描述的技術就可以繞過這樣的檢測。

封隔器的內部工作原理首先要了解封隔器的基本工作原理,了解它能做什麼,不可能做什麼。最後利用一個程序將一個有效負載封裝到另一個程序中,以避免對其進行基於簽名的檢測。因此,如果像Mimikatz這樣的負載包含特定的字符串,那麼這些字符串將在生成的二進製文件中不再可見。包裝過程可以通過某種編碼/混淆或加密來完成。我個人更喜歡加密有效負載,因為這將產生最好的隨機性,因此基於簽名的檢測最少。

4.png

這種經過編碼或加密的負載必須在生成的加載器程序中解碼/解密,以便可以從內存中執行明文負載。

根據有效負載的不同,封隔器也可以在當前進程或遠程進程中刪除更多檢測:

如果你的封隔器正在打補丁/繞過AMSI,你可以安全地從內存執行不同的已知惡意腳本(PS1,VBA,JS等)或c#程序集。

為了繞過基於ETW的檢測,封隔器還可以通過不同的發布技術修補/繞過ETW。

基於掛鉤的Win32 API檢測可以通過取消掛鉤或直接/間接使用Syscall來繞過。

基於熵的檢測將檢測到許多封隔器,因為有效負載的加密將由於隨機性而導致非常高的熵。這可以通過在生成的二進制中添加數千個單詞來繞過,因為這再次降低了熵。

但是,即使所有這些技術都得到了應用,仍然存在更多潛在的“問題”:

1.內存掃描;

2.行為檢測;

3.攻擊者。

一般來說,使用封隔器也可以繞過內存掃描,但這非常有限。

內存掃描和常用的繞過技術由於基於簽名的檢測很容易被封隔器技術繞過,越來越多的AV/EDR供應商傾向於使用掃描進行內存分析。這些掃描通常不會在所有進程中一直進行,因為這會消耗太多資源,但可能會由特定條件觸發。

例如,內存掃描通常在以下情況下出現:

生成一個新進程,例如運行一個可執行文件;

進程的行為觸發內存掃描;

第一個很容易繞過。例如,即使是封隔器也可以在解碼/解密真正的有效負載之前休眠一段時間。在這種情況下,將進行內存掃描,但不會發現任何東西,因為負載仍然是加密的。仍然有方法檢測Win32基於睡眠的內存掃描繞過,例如這裡演示的。作為使用Sleep的替代方案,你也可以在特定的時間內執行偽代碼或進行計算。除了使用Sleep,還有許多其他替代方法。

但一般來說,繞過內存掃描有以下三種方法:

更改/修改有效負載的源代碼,以避免基於簽名的檢測;

更改有效負載的行為,以便永遠不會觸發內存掃描;

內存加密。

我個人更喜歡第一種選擇,它在每個程序中都是一次性的,只要新的代碼庫不公開,它也不應該在未來被檢測到。

繞過基於行為的內存掃描是比較困難的,這取決於你的有效負載的行為。試想一下Mimikatz的行為(例如,用OpenProcess打開LSASS的句柄)會觸發一次掃描,此時,無法從內存中隱藏Mimikat,因為它需要進行加密才能工作。因此,Mimikatz不會選擇內存加密。

對於像Cobalt Strike這樣著名的C2框架,最常見的選擇是內存加密。但是如果你沒有訪問源代碼的權限,就不可能修改它以避免內存檢測。一般來說,C2框架是這項技術的優先選擇,因為它們大部分時間都處於休眠狀態。如果一個程序什麼也不做,它的內存內容可以在這個時間段內被加密,而不會出現任何問題。

基於行為檢測的一些示例和繞過但是,哪些行為會在運行時觸發AV/EDR操作或內存掃描呢?基本上全都可以。將內容寫入內存,以特定的順序或時間框架加載特定的庫,創建註冊表項,執行初始HTTP請求或任何其他操作。

我將在這裡舉幾個例子,介紹相應繞過技術。

根據我的個人經驗,AV/EDR在檢測到特定行為後極少立即終止進程。這是因為AV/EDR供應商不希望有太多的誤報結果。由於誤報結果與終止進程的行為會導致生產環境的中斷,這是非常糟糕的。所以他們需要幾乎100%的確定,一個行為肯定是惡意程序終止相應的進程。這也是為什麼許多供應商將行為檢測與內存掃描結合起來,以驗證他們發現了惡意內容。

Fodhelper UAC繞過示例基於行為的檢測的一個很好的示例是帶有Windows Defender的Fodhelper UAC繞過。這個方法非常流行,但也很容易被利用,因為它只需要創建一個註冊表項,然後調用fodhelper.exe:

5.png

在啟用殺毒軟件的情況下執行此操作將導致以下檢測:

6.JPG

此警報既不會終止正在執行的進程,也不會終止新生成的進程,但仍會導致任何攻擊中的檢測。檢測本身不能繞過AMSI,修補ETW也無濟於事。因為這是觸發此警報的特定行為。

我對此處標記的內容進行了一些簡單的試錯分析,發現殺毒軟件不喜歡HKCU:\Software\Classes\ms-settings\Shell\Open\command(Default)條目以及目錄*C:\windows\system32*和*C:\windows \syswow64*中的任何.exe。

因此,觸發警報的行為是使用其中一個字符串在上述目錄中創建註冊表項。

幸運的是,我們不需要指定.exe來執行二進製文件,也不需要兩個目錄來進行攻擊。因此,作為一種替代方案,我們可以直接將e.G. a C2-Stager複製到任何可寫目錄中,並使用UAC-Bypass執行它,而無需調用擴展名。

7.png

但到2022年,許多OffSec用戶將意識到,在安裝了AV/EDR的系統上運行任何未簽名的可執行文件可能不是一個好主意。因此,作為一種替代方案,我們還可以執行任何經過簽名的可信可執行文件,並將相應的Sideloading-DLL放到相同的目錄中。還有第三種選擇,就是我們可以將rundll32.exe複製到我們的可寫目錄中並在那裡執行它。

8.png

基於Meterpreter行為的檢測切記,不要使用分段有效負載,它們會被殺毒軟件捕獲。因此,在我們的示例中,我們將生成用於執行的不分段的反向HTTPS Shellcode。這可以通過以下命令來實現:

9.png

我不會在本文介紹執行Shellcode的方式,因為我只想展示行為檢測,但通常您需要以下內容:

對Shellcode進行加密並在運行時解密,以避免在磁盤上簽名,或者在運行時從遠程Web服務器加載它;

使用直接或間接的系統調用執行,否則Shellcode將在執行前被標記;

在這種情況下,無需修補AMSI/ETW即可使Meterpreter運行。

但是,即使你使用系統調用繞過了基於簽名的磁盤檢測和Shellcode檢測,你也應該能夠看到一個新的Meterpreter Session傳入:

10.JPG

但這只是意味著,我們的初始有效負載成功地執行了。一秒鐘後,進程被終止並出現以下檢測:

11.JPG

同樣,這是一個基於行為的檢測,由附加的DLL文件觸發,通過普通Win32 API和反射DLL注入技術加載。在本例中,stdapi-DLL的注入觸發了一個警報。

在msfconsole提示符中,你可以通過以下命令禁用stdapi DLL的加載:

12.png

這樣,你就應該可以很好地接收Meterpreter Session:

13.JPG

然而,禁用stdapi加載將導致你的Meterpreter-Session中幾乎沒有命令/模塊,只有“內核命令”可用。

等待幾分鐘後,你可以使用以下命令手動加載stdapi,但仍應沒有檢測:

14.JPG

這種基於行為的檢測是關於什麼的?我不能百分之百地肯定,但很可能是以下因素的組合:

1.新生成的進程;

2.在調用用於反射加載DLL的特定Windows API之前,新進程的時間框架x;

3.內存掃描,用於驗證惡意內容;

4.內存中Meterpreter的檢測和終止進程的操作。

注意:這是繞過Meterpeter防禦行為檢測的唯一可能方法。

如上所述,繞過內存掃描的一個通用方法是修改源代碼以避免內存中的簽名。繞過內存掃描的一個通用方法是修改源代碼以避免內存中的簽名,因此修改源代碼是另一種選擇,Meterpreter源代碼混淆的自動化方法可以點擊這裡。這樣做之後,就能夠在啟用autostdapi-Loading的情況下避免這種檢測。

第三種方法是內存加密,這對於Meterpreter來說並不容易實現,因為在請求命令之前,HTTP/HTTPS源代碼不像許多其他c2框架那樣在時間框架x上休眠。它只是拋出許多HTTP(S)請求,其間有一些小延遲。所以內存加密會中斷這個過程。如果你使用這個方法,那麼你需要在源代碼中自己集成一個帶有內存加密的自定義Sleep-function。

Cobalt Strike檢測Cobalt Strike很可能是最複雜、分析最深入的C2框架。這很可能是因為在過去幾年裡,它被許多不同的攻擊組織在野外使用。不更改默認設置在大多數環境中是不可用的,因為這會立即被檢測到。

即使使用自定義的打包器/加載器和系統調用來執行Shellcode,在許多環境中仍然會失敗。因此,我會解釋作為操作員在使用此框架時需要做的最低要求和修改。

C2服務器/基礎設施最低要求:

1.禁用Malleable配置文件中的分段,如果啟用了該功能,你的植入程序幾乎會立即被終止,因為有許多Internet範圍內的自動掃描器下載第二階段來分析和共享它。

2.你必須使用帶有許多不同重要繞過設置的自定義Malleable C2-Profile來繞過一些檢測。

3.必須在C2服務器前面使用重定向器。此重定向程序應釋放/阻止已知的沙盒分析IP範圍,並且僅允許和重定向那些符合Malleable C2配置文件的請求。 RedWarden或RedGuard是實現此流程自動化的最佳工具。使用它還可以避免在第一次連接後對Cobalt Strike服務器進行指紋識別和檢測。

植入程序的最低要求:

1.使用加密/混淆和運行時解密/反混淆打包Shellcode。如果你不這樣做,加載器將在磁盤或內存中被簽名標記(取決於加載方式);

2.使用直接或間接的系統調用來執行CS-Shellcode或從內存加載工件。如果不這樣做,在大多數環境中都會導致即時檢測,因為Shellcode始終具有相同的IoC,並且很容易被AV/EDR掛鉤檢測到。

3.使用環境鍵控(environmental keying)繞過潛在的沙盒或自動EDR雲提交分析。

4.你必須通過有關工具包修改Cobalt Strike中的默認睡眠掩碼模板。如果在Malleable C2 Profile中啟用,信標將加密堆和堆棧內存,以在成功執行後從內存掃描程序中隱藏自身。但由於這個默認的睡眠掩碼源代碼本身也被AV/EDR簽名嚴重攻擊,因此也會被內存掃描器標記。你不應該使用任何未修改的公共Github睡眠加密代碼,因為這也會被標記。

所有這些(除了睡眠掩碼的修改)都可以通過一個完全自定義的打包器/加載器或使用有關工具包(Arsenal Kit)來完成,Arsenal Kit已經提供了很多模板代碼。如果你打算使用Arsenal Kit,那麼你必須熟悉C/C++,並對模板代碼進行大量自定義,以繞過檢測。

睡眠掩碼的修改也適用於原始的Shellcode輸出,所以當你使用自己的自定義加載器時,你甚至可以在Arsenal Kit中對其進行修改。不過通過上述修改,Microsoft Defender for Endpoint 在我的測試中仍然檢測到許多惡意行為。

注:即使你應用了上述所有要求,你的植入程序仍然可以在成熟環境中檢測到。根據目標環境中使用的EDR,這是不夠的。仍然存在一些問題:

如果你收到信標連接,別以為你能夠發現什麼。在許多環境中,我都能夠讓Beacon運行,但在發出一個命令/模塊後,植入程序立即被檢測到並終止。正如我所說,CS很可能是目前最複雜的框架,看看這些yara規則,你會發現,供應商確實為每個命令/模塊實現了檢測規則。這些基於行為的檢測使我個人只能使用Cobalt Strike啟動反向Socks Connection,而不能避免本地系統IoC,通過Socks在網絡上完成所有事情。因此,在我的許多項目中,Cobalt Strike或多或少成為了一個獨立的socks5反向代理程序。

對於自動AV/EDR分析,一個簡單的內存加密可能就可以了,但在這種情況下,你需要避免更多的IoC,如RWX/RX內存權限,你不能使用Win32 Sleep,因為這很容易被檢測。

在某些環境中,我的Beacon/Process甚至在回調之前就被檢測到。說實話,我不知道這些監測是乾什麼的,說實話,我也不知道如何繞過他們。

一些更有經驗的Cobalt Strike用戶向我暗示,用戶定義的反射加載器(UDRL)幾乎有無限的可能性,比如TitanLdr。在成熟的環境中,通過可塑配置文件選項來調整Cobalt Strike行為是不夠的。例如,內核將始終使用Win32 API(具有潛在的檢測功能),而不是直接使用Syscall。直到有人將系統調用選項與更新集成。但使用UDRL,你還可以使用導入地址表掛鉤修改所有Cobalt Strike 內核行為。例如,你可以將內核的Hook VirtualProtect設置為NtProtectVirtualMemory。

因此,由於CS內核本身的局限性,它可能是堅持使用UDRL的最隱蔽的方式,而不是使用自定義打包器/加載器或經過修改的Arsenal Kit。

對我個人來說,這已經不是一個選擇了。掛鉤IAT修改一個閉源程序的內核,只是為了繞過基於行為的檢測。在某種程度上,我決定至少在這一刻不會為了讓這個框架的c2連接運行而越來越深入地研究Windows內部。在一年的時間裡,我只開發了很少的沒有檢測的環境和一些有反向Socks代理的環境,我決定使用其他框架。以前沒有CS我也很好,將來也會很好。

真的需要這些繞過技巧嗎?我認為不需要,所有這些繞過技術最終只是用來繞過簽名。

如果你使用的是自己生成的Shellcode,你可以選擇再次堅持使用Win32 API。 WriteProcessMemory或CreateThread將導致對輸入參數的檢測和對Shellcode入口點的分析。但如果沒有已知的惡意簽名,它將正常運行,不會被阻止。

如果你正在使用內部工具或經過大量修改的開放源代碼,AMSI將永遠不會發現你,因為它正在搜索已知的簽名。

如果你使用的是一個混淆的開源C2框架,或者是一個自己開發的框架,內存掃描不會發現你。

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...