CrowdStrike Researchers Investigate the Threat of Patchless AMSI Bypass Attacks

  • Adversaries have employed various tactics to bypass Windows’ AMSI security feature, but such attacks are noisy, meaning they can be detected by monitoring security products
  • A CrowdStrike Red Team Engineer analyzed the inner workings of these techniques, providing insights on detection, and crafted a variation of the techniques (a patchless AMSI attack called VEH²) that would allow an adversary to bypass AMSI without detection by silently setting a hardware breakpoint
  • The CrowdStrike Falcon® platform offers behavior-based and AI-based detection capabilities to enable full protection against adversaries using advanced, patchless AMSI bypass attacks including VEH²
  • Insight into patchless AMSI bypass attacks and VEH² was presented by CrowdStrike researchers at Black Hat MEA 2023 and AVAR 2023 conferences held in November 2023 and was also featured at RHC² in May 2025

Microsoft introduced AMSI (Antimalware Scan Interface) with Windows 10 in 2015. This interface standard allows third-party security products to be integrated with applications running on a Windows PC to improve detections for fileless and script-based attacks. Naturally, adversaries immediately began efforts to defeat AMSI.

Figure 1. Antimalware Scan Interface (AMSI) workflow Figure 1. Antimalware Scan Interface (AMSI) workflow (Source: https://learn.microsoft.com/en-us/windows/win32/amsi/how-amsi-helps)
To bypass security products, red teamers (and malware authors) have adopted several ways to deactivate telemetry, such as UserMode Hooks and AMSI. One method is by patching in memory the hooked functions, structs, or scanning functions (e.g., AmsiScanBuffer). The modification of the components and artifacts used by security products has been mapped in the technique Impair Defenses: Disable or Modify Tools by the MITRE ATT&CK® framework (T1562.001), and MITRE's inclusion of this technique in the ATT&CK framework underscores its significance, as it has been frequently observed across various adversary tradecraft. CrowdStrike researchers have observed several adversaries attempting AMSI bypass, including PUNK SPIDER and VENOMOUS BEAR, where attackers tried to tamper with AMSI functions as a preliminary avoidance detection step prior to the execution of further malicious payloads.
Figure 2. AMSI bypass — memory patching attack Figure 2. AMSI bypass — memory patching attack

However, the memory patching approach is quite noisy from an attacker perspective because it can raise several alerts during memory integrity checks and also on modification itself. The memory region permissions usually need to be modified with read-write attributes by leveraging a memory protection function (VirtualProtect, NtProtectVirtualMemory). This can be monitored and detected by security products.

To avoid these behaviors and evade detection, red team operators and malware authors started to skip these “active memory manipulation” techniques. Instead, they manipulate execution flow when specific functions are called by a process. There are several ways to “hook” these functions. A good example recently observed is programmatically placing hardware breakpoints on that function address and handling the execution on raised exceptions.

Our research and presentations focus on the challenge of these “silent” patchless AMSI attacks.

Hardware Breakpoints and Vectored Exception Handler

Hardware Breakpoints

According to Intel's 64 and IA-32 Architectures Software Developer’s Manual, the DR0-DR3 debug registers contain the addresses of hardware (HW) breakpoints. When accessing a referenced location (in combination with the other DR registers), the CPU will raise a Debug Exception before executing the instruction specified at the address.

Note: Intel’s manual also specifies that the user space processes cannot access these resources:

“Debug registers are privileged resources; a MOV instruction that accesses these registers can only be executed in real-address mode, in SMM or in protected mode at a CPL of 0.”

Vectored Exception Handler

On Windows, as specified in MSDN documentation, it is possible to programmatically handle a specific exception by registering a VECTORED_EXCEPTION_HANDLER (VEH), which will manage the execution to handle that condition. In the case of a Debug Exception, the operating system will populate an EXCEPTION_POINTERS struct pointing to an EXCEPTION_RECORD with an ExceptionCode of EXCEPTION_SINGLE_STEP (0x80000004)and ExceptionAddress pointing to the hooked address.

On exception handling, a CONTEXT struct — of the thread that raised the exception — is passed to the VEH. An attacker can edit that struct in order to manipulate execution on that address by setting the RIP (on x64) register, when resuming from that exception. Malware also uses this technique for anti-analysis, an issue we explored in a previous blog post about an advanced anti-analysis techniques discovered in GuLoader.

Figure 3. Vectored exception handler structures Figure 3. Vectored exception handler structures

HWBP + VEH

To combine these components (set a hardware breakpoint on a sensitive function address and “hook” execution with arbitrary commands), an attacker needs to:

  • Register a VEH that manages EXCEPTION_SINGLE_STEP, which can be achieved by utilizing the AddVectoredExceptionHandler function.
  • Find a way to manipulate debug registers, which are inaccessible for direct modification by user-mode processes. To accomplish this, it is necessary to access and modify the CONTEXT structure (mentioned above) associated with the executing thread, as this structure stores the current state of the debug (and other) registers (Dr* registers, as shown in Figure 3).

To achieve the last condition, several projects/techniques have used the SetThreadContext function on the local process to set DR registers in the target CONTEXT. Doing so calls into ntdll's NtSetContextThread syscall — which allows setting the CONTEXT for a specific thread.

This method has been adopted and shown publicly. For example, in this article the steps above were used to achieve a patchless AMSI bypass. In this case, the author placed a hardware breakpoint on the AmsiScanBuffer function and registered a VEH that will redirect execution with a clean result (NB: CrowdStrike does not endorse third-party tools or external techniques).

Detecting NtSetContextThread

Both of these techniques leverage the usage of SetThreadContext to modify the debug register with the address to “hook.”

A similar approach has been adopted by a GitHub project dating back to 2013: hardware breakpoints. Other projects using similar techniques have been published recently — for brevity, we mentioned the ones above.

As stated above, the SetThreadContext function calls ntdll's NtSetContextThread, a system call that can be monitored leveraging kernel visibility provided by Microsoft by observing the decompiled code of the kernel side of NtSetContextThread on ntoskrnl.exe:

Figure 4. nt!NtSetContextThread decompiled on WIN1123H2 Figure 4. nt!NtSetContextThread decompiled on WIN1123H2

As highlighted on the IDA view, before return, the function calls the EtwWrite function to trace the usage of NtSetContextThread for this process, regardless of whether the target thread is related to a remote or for the same process. It logs to the Microsoft-Windows-Kernel-Audit-API-Calls ETW provider with the KERNEL_AUDIT_API_SETCONTEXTTHREAD value (Event ID=4).

To demonstrate this, it is possible to develop a small Python program that consumes the Microsoft-Windows-Kernel-Audit-API-Calls ETW provider and checks for a NtSetContextThread event to find all of the processes that (ab)use that function by checking for a patchless AMSI bypass proof of concept (POC), as shown below. Doing so requires only administrator privileges to consume that provider — there is no need to have enabled specific Protected Process Light (PPL) protections as with the Microsoft-Windows-Threat-Intelligence ETW provider:

'''
Small PoC that permits to hunt processes using NtSetContextThread - also unhooked - by using Microsoft-Windows-Kernel-Audit-API-Calls ETW provider. 
Several Red Team tools (ab)uses NtSetContextThread to perform:
- Injection/Thread hijacking
- AMSI/ETW bypass by setting HW Breakpoints
- Memory Evasion

To Run:
 - pip install pywintrace
 - Need to be Administrator to consume Microsoft-Windows-Kernel-Audit-API-Calls ETW provider 
'''

import time
import etw
import os

# define capture provider info
providers = [etw.ProviderInfo('Microsoft-Windows-Kernel-Audit-API-Calls',etw.GUID("{E02A841C-75A3-4FA7-AFC8-AE09CF9B7F23}"))]
# create instance of ETW class
job = etw.ETW(providers=providers, event_callback=lambda x: check_event(x))

def check_event(x):
    (event_id, payload) = x
    if (event_id == 4):
        print("--------------------")
        print("[+] Suspected Process called NtSetThreadContext! Check the following process: ")
        print("\tPID: " + str(payload['EventHeader']['ProcessId']) + "\tTID: " + str(payload['EventHeader']['ThreadId']))
        print("--------------------")

def analyze():
    # start capture
    job.start()
    print("[+] Checking for suspected events for 15 minutes, Ctrl+C to force quit")
    # wait some time
    time.sleep(900)
    # stop capture
    job.stop()


if __name__ == '__main__':
    try:
        analyze()
    except KeyboardInterrupt:
        print("[-] Ctrl+C: Exiting")
        job.stop()
        os._exit(1)
Figure 5. Microsoft-Windows-Kernel-Audit-API-Calls ETW detecting NtSetThreadContext, used by patchless AMSI bypass (on the right) Figure 5. Microsoft-Windows-Kernel-Audit-API-Calls ETW detecting NtSetThreadContext, used by patchless AMSI bypass (on the right)
To further confirm the hardware breakpoint is set when running the patchless AMSI bypass, it is possible to check the debug register for the target process identified by the tool by attaching a debugger:
Figure 6. Debug register set with AmsiScanBuffer address Figure 6. Debug register set with AmsiScanBuffer address
And the trigger of the vectored exception handler on exception handling for the hardware breakpoint is set on the AmsiScanBuffer function (the ExceptionCode is set to 0x80000004 and the ExceptionAddress from the EXCEPTION_RECORD structure is highlighted), as shown in Figure 7.
Figure 7. Trigger of VEH by hardware breakpoint Figure 7. Trigger of VEH by hardware breakpoint
Note: Using the Microsoft-Windows-Kernel-Audit-API-Calls ETW provider allows for monitoring (remote and local) every user usage of NtSetContextThread, even when chained with unhooking evasion techniques. This is unlike the Microsoft-Windows-Threat-Intelligence ETW provider, which allows monitoring only for remote process CONTEXT modifications, as observed in EtwTiLogSetContextThread on ntoskrnl.exe:
Figure 8. nt!EtwTiLogSetContextThread decompiled on WIN1123H2 (snipped) Figure 8. nt!EtwTiLogSetContextThread decompiled on WIN1123H2 (snipped)

VEH²: Setting a Hardware Breakpoint the Silent Way

The NtSetContextThread function is quite powerful because it permits setting CONTEXT for threads other than the current one. However, it is possible to observe that most of the techniques modify the CONTEXT for the current (main) thread (by using GetCurrentThread and 0xFFFFFFFE). By reading this article, we can assume why:

The drawback to hardware breakpoints is that they need to be applied to each thread within the process if you want a process wide bypass. Setting it on a single thread when loading a .NET DLL from memory works just fine though, since the AMSI scan is performed within the same thread loading the .NET PE.

Note: COM usage usually involves the generation of several threads.

The Idea: Avoiding Noise

We need to edit only the "local" CONTEXT, as the previous techniques modify the RIP register on the CONTEXT to control program execution during the exception handling on a vectored exception handler. Therefore, it is possible to (ab)use the VEH routine to also modify the debug registers in the CONTEXT (without using any WINAPI or NTAPI, but directly editing the bits of them). Since the goal is to edit the CONTEXT of the current thread (on local process), it is possible to force an exception that can be managed by another vectored exception handler, which will set, on resuming execution, a new CONTEXT with the new debug registers on the thread that raised the exception.

This is because, triggered by KiUserExceptionDispatcher exported by NTDLL, on resuming from the exception handled by a VEH (after the execution of the function RtlDispatchException, which calls RtlpCallVectoredExceptionHandlers), the thread will call the NtContinue function (used to set a new CONTEXT after processing exception for the executing thread) by specifying the CONTEXT managed by the Exception Handler, inside the function RtlGuardRestoreContext:

Figure 9. User exception flow on NTDLL: KiUserExceptionDispatcher Figure 9. User exception flow on NTDLL: KiUserExceptionDispatcher
Figure 10. User exception flow on NTDLL: RtlGuardRestoreContext -> NtContinue Figure 10. User exception flow on NTDLL: RtlGuardRestoreContext -> NtContinue

VEH²: The Technique

The VEH² technique can be summarized in the following steps:

  • Register two VEHs (thus the name VEH²) using AddVectoredExceptionHandler:
    • VEH1 to handle EXCEPTION_BREAKPOINT (0x80000003): will set a new CONTEXT setting on the debug register on AmsiScanBuffer address
    • VEH2 to handle EXCEPTION_SINGLE_STEP (0x80000004): will manipulate execution for the patchless AMSI bypass (avoiding the real AmsiScanBuffer)
  • DebugBreak(): force 0x80000003-> VEH1
  • AmsiScanBuffer(): raise 0x80000004-> VEH2
Figure 11. VEH² recap Figure 11. VEH² recap

Results: AMSI Bypass Without Noise

By checking on Microsoft-Windows-Kernel-Audit-API-Calls ETW provider for tracing NtSetContextThread event, it is possible to observe that the syscall is not called when using this approach.

Figure 12. (left) Microsoft-Windows-Kernel-Audit-API-Calls ETW not reporting events, (right) VEH² patchless AMSI bypass Figure 12. (left) Microsoft-Windows-Kernel-Audit-API-Calls ETW not reporting events, (right) VEH² patchless AMSI bypass

How Falcon's Behavior-based Detection Counters Advanced Patchless AMSI Bypass Techniques

Through its advanced behavior-based detection capabilities, the Falcon platform automatically identifies cutting-edge patchless AMSI bypass attempts — including those incorporating the sophisticated VEH² technique. This real-world threat data enriches Falcon's AI-driven behavioral models, showcasing CrowdStrike's ability to stay ahead of evolving adversary tradecraft through innovative machine learning technology.

Falcon's Behavior-based Detection Advantage

Unlike signature-based solutions that struggle with novel attacks, the Falcon platform:

  • Monitors process behaviors and indicators of attack patterns rather than relying solely on known signatures
  • Identifies suspicious activity sequences characteristic of AMSI bypass attempts
  • Detects the subtle behavioral indicators of patchless AMSI bypass and other advanced techniques, including those incorporating the sophisticated VEH² technique

AI-Driven Threat Intelligence Cycle

What truly differentiates Falcon's approach is its continuous learning model:

  • Real-time detection of new bypass techniques in customer environments
  • Automated analysis of attack patterns and behaviors
  • Enrichment of behavioral models with new threat data
  • Rapid deployment of enhanced detection capabilities across the entire Falcon platform

Real-World Impact

This approach creates a significant advantage in the security landscape:

  • Customers receive detections against sophisticated bypass techniques
  • The time between new technique emergence and effective detection is dramatically reduced

As threat actors continue developing sophisticated AMSI bypass techniques, Falcon's behavior-based detection powered by advanced machine learning provides a robust defense. By focusing on suspicious behaviors, CrowdStrike maintains its position at the forefront of endpoint protection, continuously adapting to evolving adversary tradecraft.

Figure 13. Falcon detection of advanced patchless AMSI bypass Figure 13. Falcon detection of advanced patchless AMSI bypass

CrowdStrike’s Commitment to Research and Industry Leadership

The discovery and publication of the sophisticated VEH² patchless AMSI bypass technique presented at Black Hat MEA 2023, AVAR 2023, and RHC² 2025 — with the detailed analysis of the mechanics involved — show how CrowdStrike leads the way in research and innovation that benefits the entire cybersecurity industry. In addition, our commitment to research like this allows the CrowdStrike Falcon platform to provide customers with protection against even the most advanced adversary tactics, including the use of patchless AMSI bypass attacks.

Additional Resources

CrowdStrike 2025 Global Threat Report

CrowdStrike 2025 Global Threat Report

Get your copy of the must-read cybersecurity report of the year.