AMSI: выполнять сканирование больших файлов на наличие вредоносных программ по частям

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;
            }
        }
    }
}

Есть ли у вас какие-либо идеи, почему это не работает, или какие-либо предложения о том, как достичь цели?


person Gennadiy Falatiuk    schedule 23.08.2018    source источник
comment
вы когда-нибудь решили эту проблему? у меня похоже точно такая же проблема   -  person lostsource    schedule 27.11.2019


Ответы (1)


Поскольку вы не указали, какие ошибки вы получаете или что не работает, я мало чем могу помочь.

Что я могу сказать, так это то, что у меня есть работающая реализация сканирования файлов с помощью AMSI на C++. Так что да, это работает. Он даже сканирует в ZIP-файлы (в зависимости от антивирусного сканера).

Есть много вещей, которые могут потерпеть неудачу. Например: вам необходимо включить защиту в реальном времени в Центре безопасности Защитника Windows (если вы используете Защитник Windows). В противном случае вызов AmsiScanBuffer вернет код ошибки 0x80070015 с сообщением «Устройство не готово». Другие антивирусные сканеры также могут иметь такую ​​опцию.

В вашем коде отсутствуют проверки возвращаемых значений. Судя по имеющейся информации, AmsiInitialize может выйти из строя.

person gyun    schedule 18.06.2019