<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    如何發現信標(一)

    VSole2022-08-11 11:11:29

    MDSec 提供了一個商業命令和控制框架,可以避免隱蔽的活動被檢測到,不過這已經不是什么秘密了。考慮到這一點,我們一直在研發可以檢測到它們的方法。有些人會認為,建立一個難以捉摸的信標的最佳方法是,不僅要了解你的對手發現你的方式,還要嘗試找到他們將來可以檢測到你的新方法。

    在這項研究中,我們將介紹一些尋找信標的有效策略,這些策略由我們為執行這些策略而開發的 BeaconHunter 工具提供支持,并且我們打算在適當的時候將其開源。

    信標檢測方法

    雖然有各種不同的方法來檢測在網絡中運行的信標,但我們將較少地關注特定的開發后功能的功能,而更多地關注識別駐留或加載到內存中的信標的一般方法。

    行為

    信標在運行和加載時的行為可以為防御者帶來檢測機會。許多商業框架是封閉源代碼的,因此某些行為無法輕易更改,從而允許防御者創建與這些行為一致的簽名。

    一個很好的例子是信標如何加載自身及其依賴項,讓我們看看與圖像加載相關的行為如何為防御者提供檢測機會。

    為了讓信標提供豐富的利用后框架,它通常嚴重依賴操作系統原生的庫,允許開發人員通過避免靜態地綁定許多依賴項,使信標的大小盡可能小。

    通過分析大量的信標框架,我們已經注意到,它們中的許多會在加載時加載核心信標所需的所有依賴項,而不是在使用時。在某些情況下,這將導致在終端上發生的一系列事件,防御者可以輕松地對其進行簽名。

    例如,通過加載 winhttp.dll 和 wininet.dll,可以看到信標利用本地 Windows HTTP 庫作為出口信標,當加載到通常不會執行 HTTP 交互的進程時,這些可能會突出顯示異常。此外,一些信標還會加載使用更少的庫,如credui.dll、dbghelp.dll或samcli.dll。

    使用這些DLL加載序列,就可以使用EQL規則來構建簽名,以檢測信標何時執行。

    例如,使用類似于以下的 EQL 規則,可以在短時間內檢測或搜索所有加載 credui.dll 和 winhttp.dlls 的進程:

    此類檢測當然可以通過設計為模塊化或負載依賴于使用或具有延遲負載的信標來避免。

    內存檢測

    在許多情況下,信標可能會保留在內存中,以避免磁盤檢測。信標通常是由加載器注入內存的,加載器將創建一個新的線程或劫持一個現有線程,在其中運行信標。

    信標的典型加載過程可能如下所示:

    一旦信標在內存中運行,通過對進程的分析,我們通常可以利用許多指標來檢測信標,讓我們看一些內存檢測的方法。

    簽名

    檢測已知惡意軟件的內存信標的最簡單但最有效的策略之一可能是通過簽名檢測。雖然許多反病毒引擎和 EDR 實施自己的內存掃描例程,但防御者可以使用 Yara 規則輕松實現全面的內存掃描。

    一個可以與yara64.exe命令行工具一起使用的簡單的Yara規則可能是這樣的,它將匹配檢測內存中列出的三個字符串中的任何一個:

    為嵌入在信標中的字符串/數據或來自 .text 部分的代碼創建 Yara 規則在概念上可以用作檢測已知內存惡意軟件的有效技術。

    Elastic 過去在如何利用它來檢測內存中的 Cobalt Strike 方面做了一些出色的工作,建議閱讀這些技術如何在實踐中應用。

    為了逃避這種內存掃描,信標可以使用多種技術來混淆它們在內存中的足跡,包括替換已知字符串,例如可以使用 Cobalt Strikes strrep 可塑性配置文件選項或使用混淆和休眠策略,例如我們在 Nighthawk 中使用的一種,用于在休眠時保護信標的所有字符串、數據和代碼。

    內存掛鉤

    為了規避控制或更改進程的運行方式,信標或操作員可以將掛鉤應用于內存中的某些函數。這些掛鉤可以留下隱藏的痕跡,從而為防御者提供揭示隱藏信標的機會。讓我們來看看這種行為的一些具體示例。

    修復ETW 和 AMSI

    修補諸如 AMSI 之類的安全控制或削弱通過 Windows 事件跟蹤獲得的檢測數據在攻擊性社區中已經不是什么秘密了,事實上我們過去曾在介紹過這些策略。

    這些補丁通常通過修改內存來應用,讓我們看兩個來自 Sliver C2 庫的例子:

    https://github.com/sliverarmory/injectEtwBypass

    https://github.com/sliverarmory/injectAmsiBypass

    正如我們在上面的屏幕截圖中看到的,這兩個示例都會導致信標將補丁應用到 ntdll!etwEventWrite 或 amsi.dll!AmsiOpenSession 函數。

    考慮到這一點,低噪聲檢測的機會就出現了,只需搜索應用這些補丁的進程,以及其他常用的補丁函數,如AmsiScanBuffer或sleeppex,由Cobalt Strike的線程堆棧欺騙功能應用于這些函數。

    復制寫入的修改

    如上所述,信標應用補丁來處理內存的情況并不少見,這可以為防御者創造檢測機會。然而,一旦執行了開發后操作,如果信標刪除了這些補丁,檢測的準確率可能會降低。例如,植入程序可以在內存中執行 .NET 程序集之前應用 AMSI 補丁,然后在執行后將補丁恢復為其原始操作碼。這種方法比簡單地將未修復漏洞留在內存中要明智一些。

    然而,為了避免重復,Windows將把公共dll返回到運行進程共享的物理內存中。如果信標或操作員執行對這些dll應用補丁的操作,則會發生寫入時復制操作,從而使該頁面成為該進程的私有頁面。使用 QueryWorkingSetEx API,我們能夠查詢有關進程特定虛擬地址的頁面的信息。在返回的 PSAPI_WORKING_SET_EX_INFORMATION 結構中是一個 PSAPI_WORKING_SET_EX_BLOCK 聯合,它指示查詢地址處頁面的屬性。在這個聯合中,我們能夠通過共享位的返回值來確定頁面上是否發生了寫入復制操作。此技術被諸如 Moneta 之類的內存掃描儀使用,并且在檢測內存中的補丁時非常有效,即使原始補丁值已恢復。

    然而,在大規模應用這種技術時存在一些誤報的風險,因為 EDR 和防病毒軟件應用它們自己的內存掛鉤并不少見,這意味著它們可以使我們從查找中獲得的一些價值無效用于寫操作時的復制。然而,為了降低誤報的風險,我們可以通過解析修改頁面上的導出,并對 EDR通常不掛鉤的函數(如EtwEventWrite或AmsiScanBuffer)應用更大的權重,從而對其應用更多智能。

    線程異常

    如上所述,一旦信標在內存中運行,它通常會存在于一個或多個線程中,具體取決于信標是同步的還是異步的。與這些線程相關的異常可以提供信標活動的高信號指標,特別是當與其他指標結合或相互結合時。一些常見的可疑線程相關指標包括:

    未映射的內存:源自虛擬內存且不受 DLL 支持的線程是注入線程的經典標識。這些線程可以通過尋找具有 MemoryType 為 MEM_IMAGE 和 MemoryState 為 MEM_COMMIT 的內存區域的線程來輕松檢測到。或者,這些線程通常由 EDR 檢查通過線程創建 API 的內核回調來檢測。有許多工具可以查找這個標識。

    延遲狀態:大部分時間信標將處于休眠狀態,然后醒來恢復其任務。為了實現這種休眠行為,通常使用諸如sleeppex這樣的windows API調用,這將使線程處于等待狀態,并將導致線程調用堆棧包含對 KernelBase.dll!SleepEx 和 ntdll.dll!NtDelayExecution 的調用。當與其他指標結合時,例如module stomping的跡象(稍后討論)或調用堆棧中對虛擬內存的調用,那么這可能會提供一些信標行為。

    繞過可疑線程檢測的嘗試最近變得流行起來,一些概念證明和商業實現正在已發布。

    這些實現通常通過截斷線程的調用堆棧(例如通過將幀的返回地址設置為空)或通過復制現有線程的上下文來工作。考慮到這一點,我們可以尋找更多指標來添加到我們的指標中:

    可疑起始地址:截斷線程調用堆棧的副作用之一是起始地址并非源自預期位置。也就是說,線程通常源自 ntdll!RtlUserThreadStart 和 kernel32!BaseThreadInitThunk,或者在 CLR 線程的情況下源自 ntdll!RtlGetAppContainerNamedObjectPath。尋找不遵循此模式的線程可用作進一步分析的可疑指標。此外,如果線程的 NtQueryInformationThread(ThreadQuerySetWin32StartAddress) 的返回值與最后一幀的返回地址之間存在不匹配,則線程的起始地址也可以被認為是可疑的,這意味著有潛在的截斷。

    初始幀之間的距離:如上所述,調用堆棧的初始起始地址通常源自用于執行線程初始化和創建的一組地址。注意到這些初始堆棧幀之間的距離相對一致,并且通常在第一幀和第二幀之間是靜態的(例如 ntdll!RtlUserThreadStart 和 kernel32!BaseThreadInitThunk)。在調用堆棧被截斷的情況下,這些幀之間的距離幾乎肯定是可變的。

    復制上下文:如上所述,除了截斷線程的調用堆棧外,欺騙調用堆棧的一種方法是復制合法線程的上下文。這種技術可以有效且實施起來相對簡單。首先,在線程的線程信息塊中,有許多指向有關線程的各種信息的指針,這些跨線程的副本,例如具有相同堆棧基數(堆棧底部)和堆棧限制(堆棧上限)的多個線程,是線程上下文已被復制的良好指標。

    頁面權限

    一般來說,信標將從虛擬內存中運行,或者如果Module Stomping,則從 DLL 支持的區域內運行。

    為了使信標恢復并執行其任務,信標所在的頁面需要對其應用執行權限。

    例如,我們可以在下面的截圖中看到,0x22f96c5000的內存沒有一個DLL支持,它被標記為“Private:Commit”(即 VirtualAlloc 導致的虛擬內存),并設置了 RX 頁面權限:

    這些指標是一個強烈的信號,表明有信標在該地區執行。

    接下來的挑戰便是如何避免這一指標,答案很簡單,如果你的信標是從虛擬內存運行的,則它不能,在某些時候信標需要執行。折衷方案實際上是僅在信標執行任務時維護可執行權限,并在信標休眠時利用策略刪除可執行權限。因此,避免諸如 SOCKS 代理之類的交易有助于最大限度地減少該指標的暴露:

    一些植入程序采用了根據信標狀態調整頁面保護的策略,以及幾個開源實現,例如 @Ilove2pwn_ 的 Foliage、@c5pider 的 Ekko、@mariuszbit 的 ShellcodeFluctuation 和 Josh Lospinoso 的 Gargoyle。

    這些策略通常會利用某種形式的事件驅動執行來休眠和喚醒信標,使用ROP小工具重新執行來調用VirtualProtect,并將信標的頁面重置為可執行權限。由MDSec的Peter Winter-Smith發現并被Ekko使用的基于計時器的技術,最初是由MDSec的Nighthawk c2逆向工程而來。簡而言之,這種技術的工作原理是使用CreateTimerQueueTimer將多個計時器排隊,然后當事件觸發器返回到之前定義的Context記錄時,使用NtContinue執行并調用VirtualProtect來重新啟用執行位。

    要更詳細地理解這種技術,可以在這里找到@Ilove2pwn_的原始文章。

    Module Stomping

    Module Stomping提供了一種將信標隱藏在內存中的替代方法,從而避免了與未映射內存中的信標相關的一些常見指標。為了實現這一點,需要加載一個不太可能被進程使用的合法DLL,信標通過模塊自我復制,然后創建一個由 stomped 代碼支持的線程:

    Cobalt Strike 自 3.11 版本以來就提供了此功能,并且可以使用“set module_x64 / module_x86”可擴展配置選項使用。

    雖然這種技術可以提供許多 OpSec 優勢,但它確實留下了幾個我們可以可靠檢測的指標:

    1.檢測這種攻擊的最簡單的技術可能是比較內存中的模塊內容和磁盤上存在的模塊內容。代碼部分的任何變化幾乎肯定會暗示一些可疑的行為。這個進程當然是相對密集的,因為它需要從磁盤加載進程中的所有模塊,并與運行中的內存進行比較。

    2.如上所述,對進程內模塊存儲器的修改將導致發生寫入操作時的復制。考慮到這一點,用于檢測內存掛鉤的相同邏輯也可以應用于檢測Module Stomping,因為在內存中覆蓋 DLL 將導致生成 DLL 的副本并清除共享位。

    3.有幾種方法可用于執行Module Stomping,其中一些涉及利用現有的 Windows API,例如 LoadLibrary,而其他更復雜的實現可能使用自定義加載器將 DLL 映射到內存中。一些技術具有與它們相關的已知指標,在 PEB 中留下可用于尋找該技術的常駐痕跡是高度可信的。稍后將更詳細地討論這方面的示例。

    檢測Cobalt Strike的方法

    Cobalt Strike 是最受歡迎的命令和控制框架之一,受到防御者和攻擊者的青睞。在這篇文章中,我們將討論防御者如何使用第一篇文章中介紹的技術,在不同配置和跨網絡中檢測 Cobalt Strike 。所有分析均在 Cobalt Strike 4.6.1 上進行。、

    Cobalt Strike 信標具有高度擴展性,因此某些指標可能會根據所選的擴展性配置文件選項而有所不同。

    內存中的Cobalt Strike

    過去,在內存中尋找 Cobalt Strike 簽名對于防御者來說是卓有成效的,之前 Elastic 提供了全面的記錄。然而,從那時起,HelpSystems做了很多工作,Cobalt Strike 4.4 引入了休眠策略。

    Cobalt Strike 為其混淆和休眠策略提供了以下可能的配置選項:

    沒有休眠掩碼:信標、它的字符串和代碼將在內存中保持明文,并且可以通過內存掃描輕松識別。

    在可擴展配置文件中啟用 sleep_mask:當在 malleable 配置文件中將 sleep_mask 設置為 true 時,beacon 將使用內置的混淆和休眠策略來屏蔽內存中使用 xor 來混淆字符串和數據的信標。正如 Elastic 在前面提到的帖子中所詳述的,這當然可以通過定位代碼部分來簽名。

    使用用戶定義的休眠掩碼:用戶定義的休眠掩碼向用戶公開信標的混淆和休眠功能,允許他們滾動自己的實現。在這樣做的同時,它還為用戶提供了許多指向信標使用的任何堆記錄的指針,以便用戶可以對它們進行加密。利用用戶定義的休眠掩碼確實有一些折衷,特別是為了混淆 .text 部分,配置必須將“userwx”選項設置為 true。也就是說,如果要對其進行混淆,信標將始終存在于 RWX 內存中。如果 userwx 選項設置為 false,則信標將從 RX 內存中運行,但 .text 部分不會被混淆,因此可以進行簽名。由操作員自行決定選擇他們覺得最舒服的指標。

    例如,當使用將 userwx 選項設置為 false 的 Sleep Mask Kit 時,可以使用以下 Yara 規則檢測 Cobalt Strike:

    對注入的信標運行此Yara規則將顯示檢測到簽名:

    啟用 userwx 會將頁面權限設置為 EXECUTE_READWRITE ,但這意味著信標現在正在混淆其 .text 部分:

    頁面權限

    Cobalt Strike 信標通常在具有 RX 或 RWX 頁面權限的頁面上運行,具體取決于可擴展配置文件的“userwx”配置選項的值,并且沒有Module Stomping,將由未映射的內存支持。

    這是一個明確的指標,使得在內存中發現信標相對來說很簡單:

    為了避免JIT程序集,可以掃描這些內存區域,搜索具有PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ頁面權限和MEM_COMMIT標志的頁面。當與其他指標一起使用時,這對識別信標活動可能是有價值的。當使用-p標志時,我們將此簽入到BeaconHunter中:

    線程

    注入內存時,Cobalt Strike 會占用一個線程,信標是同步的。默認情況下,信標運行所在的線程是高度可疑的,并且有許多與之相關的指標。

    在 Process Hacker 中檢查 Cobalt Strike 信標的線程可能看起來像這樣:

    僅在上面的屏幕截圖中,我們就可以看到一些使線程看起來非常可疑的指標:

    首先,線程通常有一個 0x0 的起始地址。總體而言,這有點不規則,盡管從掃描合法進程來看,它確實有時會在某些進程(如 chrome.exe)中發生。

    深入了解線程的調用堆棧,我們還注意到對 KernelBase!SleepEx 和 ntdll.dll!NtDelayExecution 的調用。這些調用是信標處于睡眠狀態的標志,用于在信標處于睡眠狀態時延遲線程的執行。

    在調用 KernelBase.dll!SleepEx 之前,我們可以在 0x1b8ef69fcc7 的跟蹤中看到調用,堆棧遍歷尚未解析此地址的符號,因此幾乎可以肯定它是虛擬內存。由虛擬內存支持的線程非常可疑,可能需要進一步分析。

    綜上所述,防御者能夠高度自信地確定惡意活動來自線程。由于這些指標,BeaconHunter 會排除這些可疑線程:

    還應該注意的是,Cobalt Strike 在 21 年 6 月將堆棧欺騙引入了到了工件中。但是,調用堆棧欺騙僅適用于通過工件工具包生成的 exe/dll 工件,而不是通過注入線程中的 shellcode 注入的信標。因此,它們不太可能有效地掩蓋內存中的信標。

    分析表明,fiber的使用很少見,因此可以通過分析 ntdll.dll!RtlUserFiberStart 的起始地址的調用堆棧來輕松找到這些fiber,當與其他指標結合使用時,可以為尋找 Cobalt 工件提供一個好的開端:

    Module Stomping

    Cobalt Strike 支持使用“set module_x64”和“set module_x86”可擴展選項的Module Stomping。配置這些選項會導致信標由磁盤上的模塊支持,提供一些操作安全方面的優勢,而不是從虛擬內存中操作。

    然而,Cobalt Strike Module Stomping技術的實施確實在流程的 PEB 中留下了一些攻擊指標。除了將內存中的模塊與磁盤上的副本進行比較或刪除共享位之外,實際的實施技術還允許防御者創建高度準確的Module Stomping檢測。

    鑒于 Cobalt Strike 用于Module Stomping的方法,它首先使用對 LoadLibraryExA(moduleName, NULL, DONT_RESOLVE_DLL_REFERENCES) 的調用來加載犧牲 DLL:

    這指示加載器不執行 DLL 入口點,并避免處理 DLL 的導入表以加載依賴項。

    但是,這種方法的副作用是 PEB 中的 LDR_DATA_TABLE_ENTRY 結構中的某些屬性被保留在罕見的配置中,具體而言,EntryPoint 屬性將設置為 NULL 并且 ImageDLL 位為 false。

    遍歷PEB并解析該結構可以為配置中這些屬性的組合提供一個高置信度指標:

    網絡上的Cobalt Strike

    Cobalt Strike C2 服務器基于 NanoHttpd,這是一個輕量級 Java HTTP 服務器,并進行了少量更改以使其與 Cobalt Strike 用例保持一致。FoxIT 之前已經完成了在野外識別 Cobalt Strike 團隊服務器的工作,然而,多余的空白字符的痕跡早已被修補。當時,FoxIT的研究表明,Cobalt Strike C2服務器可能比NanoHttpd服務器多得多。

    對 Cobalt Strike C2 服務器的粗略分析揭示了許多進一步的 C2 指紋識別方法。

    第一個涉及到 Range HTTP 標頭的使用,其中發送一個帶有無效整數的請求將導致服務器不返回任何響應:

    可以看到,發生了未處理的異常:

    仔細查看C2服務器源代碼(src/main/java/cloudstrike/WebServer.java),我們可以很快找到原因,服務器嘗試將字符串轉換為整數,但該值無效且未進行異常處理:

    用于對 Cobalt Strike C2 服務器進行指紋識別的第二種技術也存在于 Range HTTP 標頭中。提供服務器無法滿足的范圍(例如 1-0),將導致一個“range Not Satisfiable”錯誤。雖然這個錯誤也會出現在 NanoHTTPd 服務器中,但我們可以通過錯誤的 Server 標頭暗示它是 Cobalt Strike,即 IIS、Apache 和 Nginx 等服務器不返回此錯誤:

    進一步分析C2服務器的源代碼,我們可以很容易地識別其他可能導致指紋的響應,例如 src/main/java/cloudstrike/NanoHTTPD.java 中的以下內容:

    正如我們在上面看到的,當在 URI 中提交了無效的 URL 編碼字節時,C2 服務器將返回一個可指紋識別的響應。

    使用這個邏輯,我們可以構建一個 Nuclei 模板來掃描團隊服務器:

    匹配示例如下:

    本文我們介紹了防御者可以識別來自野外 Cobalt Strike 信標惡意活動的一些技術,包括內存中、線程內和整個網絡中的指標。

    我們在本文中介紹了對 C2 框架執行威脅追蹤的通用方法以及針對 Cobalt Strike 的實際示例。下一篇文章中,我們將分析由 Dark Vortex 開發的命令和控制框架 Brute Ratel。

    堆棧dll注入
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    在Windows大部分應用都是基于消息機制,他們都擁有一個消息過程函數,根據不同消息完成不同功能,windows通過鉤子機制來截獲和監視系統中的這些消息。一般鉤子分局部鉤子與全局鉤子,局部鉤子一般用于某個線程,而全局鉤子一般通過dll文件實現相應的鉤子函數。
    全局鉤子注入在Windows大部分應用都是基于消息機制,他們都擁有一個消息過程函數,根據不同消息完成不同功能,windows通過鉤子機制來截獲和監視系統中的這些消息。一般鉤子分局部鉤子與全局鉤子,局部鉤子一般用于某個線程,而全局鉤子一般通過dll文件實現相應的鉤子函數。
    簡介這次實驗是在WIN7 X86系統上進程,使用的編譯器是VS2017。所謂的DLL注入,其實就是在其他的進程中把我們編寫的DLL加載進去。所以DLL注入的核心就是把要注入DLL的路徑寫到目標進程中,然后在目標進程中調用LoadLibrary函數,并且指定參數為保存了DLL路徑的地址。要實現DLL注入,首先就要創建一個用來注入DLL
    Windows注入的一些方式
    CS-exe木馬分析
    2023-02-06 10:03:07
    分析Windows Executable 生成的artifact.exe查殼:無殼二、具體分析401840關鍵函數:獲取系統時間戳,通過sprintf拼接管道名,創建線程,寫加密數據到創建的管道內,最后解密執行。讀取管道內的數據,解密數據,跳轉執行。shellcode分析:1.loadlibrary加載wininet.dllInternetOpen函數:在進行HTTP、FTP和服務器通信前初始化 WinInet.dll 。簡單的說通過 InternetOpen 函數創建位于根部的 Hinternet 句柄。HttpSendRequestA發送HTTP請求到指定的服務器。跳轉到申請的內存處,解密出dll。; ebx+ReflectiveLoader函數偏移-7call ebx ; call ReflectiveLoader
    BEServer - BattlEye服務器,收集上傳的信息,并判定作弊行為。本次分析的是BEDaisy,也就是BE內核驅動中的各種檢測。上傳的內容主要是一些黑名單特征,這些特征應該是從服務器下發的,因此可以在不重新編譯驅動的情況下,動態調整檢測的特征。沒有給定偏移量的特征,BE在檢測時會按子串匹配的方式嘗試所有位置進行匹配。
    本系列將以官網資料為基礎主要通過動態跟蹤來解析DynamoRIO的源代碼。因為如果不結合實例只是將各函數的作用寫出來,實在無法很好的說明問題,我們將以代碼覆蓋工具drcov為例,分析DynamoRIO的執行流程。
    1.CheatEngine工具的基本使用
    不幸的是,“軟件供應鏈安全指南”再次強化了這種謬誤。該指南要求集中化管理的安全團隊對軟件工程活動施加重大限制,從而實現“將安全作為重中之重”。為了安全起見,速度甚至可靠性都被視為合理的“傷亡代價”。對于政府情報部門而言,國家安全是主要使命,因此他們認為安全摩擦和障礙是值得的。該指南明確表示不鼓勵開源軟件。事實上,為了推銷廠商的安全產品,指南甚至給出了諸如手動發布流程之類的危險建議。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类