AMSI имеет функцию AmsiScanBuffer
для сканирования байтового массива. Но в этом случае содержимое всего должно быть прочитано в память, что может быть невозможно для больших файлов. Функция AmsiScanBuffer
имеет параметр amsiSession
, который предназначен для корреляции нескольких запросов сканирования. Насколько я понимаю, должно работать чтение одного файла по чанкам и вызов AmsiScanBuffer
для этих чанков с одинаковым сеансом и контекстом. Но это не так:
public enum AMSI_RESULT
{
AMSI_RESULT_CLEAN = 0,
AMSI_RESULT_NOT_DETECTED = 1,
AMSI_RESULT_DETECTED = 32768
}
public static class NativeMethods
{
[DllImport("Amsi.dll", EntryPoint = "AmsiInitialize", CallingConvention = CallingConvention.StdCall)]
public static extern int AmsiInitialize([MarshalAs(UnmanagedType.LPWStr)]string appName, out IntPtr amsiContext);
[DllImport("Amsi.dll", EntryPoint = "AmsiUninitialize", CallingConvention = CallingConvention.StdCall)]
public static extern void AmsiUninitialize(IntPtr amsiContext);
[DllImport("Amsi.dll", EntryPoint = "AmsiOpenSession", CallingConvention = CallingConvention.StdCall)]
public static extern int AmsiOpenSession(IntPtr amsiContext, out IntPtr session);
[DllImport("Amsi.dll", EntryPoint = "AmsiCloseSession", CallingConvention = CallingConvention.StdCall)]
public static extern void AmsiCloseSession(IntPtr amsiContext, IntPtr session);
[DllImport("Amsi.dll", EntryPoint = "AmsiScanString", CallingConvention = CallingConvention.StdCall)]
public static extern int AmsiScanString(IntPtr amsiContext, [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)]string @string, [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)]string contentName, IntPtr session, out AMSI_RESULT result);
[DllImport("Amsi.dll", EntryPoint = "AmsiScanBuffer", CallingConvention = CallingConvention.StdCall)]
public static extern int AmsiScanBuffer(IntPtr amsiContext, [In] [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint length, [In()] [MarshalAs(UnmanagedType.LPWStr)] string contentName, IntPtr session, out AMSI_RESULT result);
}
class Program
{
static void Main(string[] args)
{
IntPtr amsiContext;
IntPtr session;
AMSI_RESULT result = 0;
int returnValue;
returnValue = NativeMethods.AmsiInitialize("Win10AMSIScanner", out amsiContext);
returnValue = NativeMethods.AmsiOpenSession(amsiContext, out session);
Scan(amsiContext, session, ref result);
Console.WriteLine(result);
NativeMethods.AmsiCloseSession(amsiContext, session);
NativeMethods.AmsiUninitialize(amsiContext);
Console.ReadLine();
}
private static void Scan(IntPtr amsiContext, IntPtr session, ref AMSI_RESULT result)
{
const int bufferLength = 10;
using (var fs = new MemoryStream(Encoding.UTF8.GetBytes(@"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*")))
{
long alreadyRead = 0;
fs.Seek(0, SeekOrigin.Begin);
long toReadCount = alreadyRead + bufferLength <= fs.Length ? bufferLength : fs.Length - alreadyRead;
while (toReadCount > 0)
{
var content = new byte[toReadCount];
fs.Read(content, 0, (int)toReadCount);
NativeMethods.AmsiScanBuffer(amsiContext, content, (uint)toReadCount, "eicar-test-file", session, out result);
alreadyRead += toReadCount;
toReadCount = alreadyRead + bufferLength <= fs.Length ? bufferLength : fs.Length - alreadyRead;
}
}
}
}
Есть ли у вас какие-либо идеи, почему это не работает, или какие-либо предложения о том, как достичь цели?