Антивирусное сканирование Защитника Windows с C# [исключение AccessViolation]

мы пишем код для сканирования по требованию файла с C# с помощью API-интерфейсов Защитника Windows.

        [DllImport(@"C:Program FilesWindows DefenderMpClient.dll")]
        public static extern int WDStatus(out bool pfEnabled);

        [DllImport(@"C:Program FilesWindows DefenderMpClient.dll")]
        public static extern int MpManagerOpen(uint dwReserved, out IntPtr phMpHandle);

        [DllImport(@"C:Program FilesWindows DefenderMpClient.dll")]
        public static extern int MpScanStart(IntPtr hMpHandle, uint ScanType, uint dwScanOptions, IntPtr pScanResources, IntPtr pCallbackInfo, out IntPtr phScanHandle);

        [DllImport(@"C:Program FilesWindows DefenderMpClient.dll")]
        public static extern int MpHandleClose(IntPtr hMpHandle);

        private void DoDefenderScan_Click(object sender, EventArgs e)
        {
            try
            {
                bool pfEnabled;
                int result = WDStatus(out pfEnabled); //Returns the defender status - It's working properly.
                ErrorHandler.ThrowOnFailure(result, VSConstants.S_OK);

                IntPtr phMpHandle;
                uint dwReserved = 0;

                IntPtr phScanHandle;

                MpManagerOpen(dwReserved, out phMpHandle); //Opens Defender and returns the handle in phMpHandle. 

                tagMPRESOURCE_INFO mpResourceInfo = new tagMPRESOURCE_INFO();
                mpResourceInfo.Path = "eicar.com";
                mpResourceInfo.Scheme = "file";
                mpResourceInfo.Class = IntPtr.Zero;

                tagMPRESOURCE_INFO[] pResourceList = new tagMPRESOURCE_INFO[1];
                pResourceList.SetValue(mpResourceInfo, 0);

                tagMPSCAN_RESOURCES scanResource = new tagMPSCAN_RESOURCES();
                scanResource.dwResourceCount = 1;
                scanResource.pResourceList = pResourceList;
                IntPtr resourcePointer = StructToPtr(scanResource);

                result = MpScanStart(phMpHandle, 3, 0, resourcePointer, IntPtr.Zero, out phScanHandle); **//Getting Access violation exception here**.

                MpHandleClose(phMpHandle);
                MpHandleClose(phScanHandle);
                Marshal.FreeHGlobal(resourcePointer);
            }
            catch (Exception)
            { }
        }

и структура определена здесь.

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct tagMPSCAN_RESOURCES
    {
        public uint dwResourceCount;

        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
        public tagMPRESOURCE_INFO[] pResourceList;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct tagMPRESOURCE_INFO
    {
        [MarshalAs(UnmanagedType.LPWStr)]
        public String Scheme;

        [MarshalAs(UnmanagedType.LPWStr)]
        public String Path;

         public IntPtr Class;
    }

    public class MPRESOURCE_CLASS
    {
        public uint Value;
    }

    private static IntPtr StructToPtr(object obj)
    {
        var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
        Marshal.StructureToPtr(obj, ptr, false);
        return ptr;
    }

код написан на основе документации, доступной по адресу

https://msdn.microsoft.com/en-us/library/vs/alm/dn920144(v=vs. 85).aspx

мы получаем это исключение

попытка чтения или записи в защищенную память. Это часто указание на то, что другая память повреждена.

at

result = MpScanStart(phMpHandle, 3, 0, resourcePointer, IntPtr.Zero, out phScanHandle); **//Getting Access violation exception here**.

в чем может быть проблема? Формат struct-это правильно?

P. S - в msdn нет информации о MPRESOURCE_CLASS.

Я не уверен, правильна ли эта строка кода.

 mpResourceInfo.Class = IntPtr.Zero;

обновление:

быстрое сканирование работает нормально с этим код:

result = MpScanStart(phMpHandle, 1, 0, IntPtr.Zero, IntPtr.Zero, out phScanHandle);

журналы Defender в средстве просмотра событий [ журналы приложений и служб-Microsoft-Windows-Windows Defender / Operational ] как

началось сканирование Защитника Windows.
Идентификатор сканирования: {CDC2AC0D-7648-4313-851C-4D8B7B5EB5CD}
Тип Сканирования: AntiSpyware
Параметры Сканирования: Быстрое Сканирование

3 ответов


Я не могу определить проблему. Так что я закончил с Интерфейс Сканирования Вредоносных Программ (AMSI) доступно начиная с Windows 10.

Я написал образец кода C#здесь.
Одна вещь, которую я нашел, - AMSI требует включения Защитника Windows / любого антивируса для проверки файла, переданного API. Но запуск сканирования через MpClient.dllвызовет сканирование защитника, даже если защитник выключен.

также убедитесь, что ваши цели проекта .

public enum AMSI_RESULT
    {
        AMSI_RESULT_CLEAN = 0,
        AMSI_RESULT_NOT_DETECTED = 1,
        AMSI_RESULT_DETECTED = 32768
    }

[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, ulong length, [In()] [MarshalAs(UnmanagedType.LPWStr)] string contentName, IntPtr session, out AMSI_RESULT result);

//This method apparently exists on MSDN but not in AMSI.dll (version 4.9.10586.0)
[DllImport("Amsi.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern bool AmsiResultIsMalware(AMSI_RESULT result);

private void CallAntimalwareScanInterface()
{
    IntPtr amsiContext;
    IntPtr session;
    AMSI_RESULT result = 0;
    int returnValue;

    returnValue = AmsiInitialize("VirusScanAPI", out amsiContext); //appName is the name of the application consuming the Amsi.dll. Here my project name is VirusScanAPI.   
    returnValue = AmsiOpenSession(amsiContext, out session);
    returnValue = AmsiScanString(amsiContext, @"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", "EICAR", session, out result); //I've used EICAR test string.   
    AmsiCloseSession(amsiContext, session);
    AmsiUninitialize(amsiContext);
}

Я искал о проблеме, и я прочитал это как одну из возможных причин:

" вы часто видите различия между сборками отладки и выпуска, потому что сборки debug содержат дополнительные метаданные для отладки."

здесь: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4f48c152-68cd-45ec-a11e-baa7de7f79c3/attempted-to-read-or-write-protected-memory?forum=csharpgeneral

также вы должны проверить ответ на "Можно ли поймать исключение нарушения прав доступа в .NET?" и дополнительные сведения, которые объясняются в статье Обработка Исключений Поврежденного Состояния в журнале MSDN
...

Итак, в соответствии с этими ответами и статьями я бы попробовал:

1-я двойная проверка подписей и COM-взаимодействие для всего неуправляемого кода, чтобы убедиться, что они верны.

2nd установите отладчик Visual Studio для обхода этого исключение: Меню Сервис - >Параметры - > отладка - > общие - > снимите этот флажок "подавить оптимизацию JIT при загрузке модуля"

3-я попытка-поймать исключение

(Примечание: Если вы используете .Net 4, то в приложении.config, в теге изменить среду выполнения, чтобы включить legacyCorruptedStateExceptionsPolicy enabled= "true", как:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>

)

кроме того, здесь, я обнаружил, что некоторые версии .net framework (последний комментарий указывает на 4.6.1 в один из комментариев ответа) имеет ошибку, связанную с этим исключением, и решение в прошлом обновляло структуру. Кроме того, в одном из этих ответов я прочитал:

Привет есть две возможные причины.

1.У нас есть неуправляемый код, и мы вызываем его из управляемого кода. это предотвращает запуск этого кода. попробуйте выполнить эти команды и перезагрузите компьютер

cmd: netsh winsock reset

открыть cmd.exe и выполнить команду " netsh winsock reset catalog" 2.Антивирус рассматривает неуправляемый код как вредоносный и ограничивает запуск этого кода отключите антивирус, а затем проверьте

Я хотел бы знать, помогают ли некоторые из этих подходов решить вашу проблему.

Я очень надеюсь, что это помогает.

KR,

Хуан


вы можете использовать Интерфейс Сканирования Вредоносных Программ чтобы проверить файл на наличие вредоносных программ.

интерфейс сканирования вредоносных программ (AMSI) является общим стандартом интерфейса, который позволяет приложениям и службам интегрироваться с любым программным продуктом, присутствующим на компьютере. Он обеспечивает повышенную защиту от вредоносных программ для пользователей и их данных, приложений и рабочих нагрузок.

Он доступен начиная с Windows 10.