Windows Defender Антивирусная проверка с С# [AccessViolation exception]
Мы пишем код для проверки по требованию файла с С# с помощью API-интерфейсов Windows Defender.
[DllImport(@"C:\Program Files\Windows Defender\MpClient.dll")]
public static extern int WDStatus(out bool pfEnabled);
[DllImport(@"C:\Program Files\Windows Defender\MpClient.dll")]
public static extern int MpManagerOpen(uint dwReserved, out IntPtr phMpHandle);
[DllImport(@"C:\Program Files\Windows Defender\MpClient.dll")]
public static extern int MpScanStart(IntPtr hMpHandle, uint ScanType, uint dwScanOptions, IntPtr pScanResources, IntPtr pCallbackInfo, out IntPtr phScanHandle);
[DllImport(@"C:\Program Files\Windows Defender\MpClient.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 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
Мы получаем это исключение
Попытка чтения или записи защищенной памяти. Это часто свидетельствует о том, что другая память повреждена.
в
result = MpScanStart(phMpHandle, 3, 0, resourcePointer, IntPtr.Zero, out phScanHandle); **//Getting Access violation exception here**.
В чем может быть проблема? Правильно ли указан формат структуры?
P.S - Информация о MPRESOURCE_CLASS отсутствует в msdn.
Я не уверен, правильная ли эта строка кода.
mpResourceInfo.Class = IntPtr.Zero;
Update:
Быстрое сканирование отлично работает с этим кодом:
result = MpScanStart(phMpHandle, 1, 0, IntPtr.Zero, IntPtr.Zero, out phScanHandle);
Защитник регистрируется в средстве просмотра событий [Журналы приложений и служб - Microsoft-Windows-Windows Defender/Operational] как
Запустилось сканирование защитника Windows.
Идентификатор сканирования: {CDC2AC0D-7648-4313-851C-4D8B7B5EB5CD}
Тип сканирования: AntiSpyware
Параметры сканирования: быстрое сканирование
Ответы
Ответ 1
Я не мог идентифицировать проблему здесь. Таким образом, я закончил с Интерфейс сканирования Antimalware (AMSI), доступный начиная с Windows 10.
Я написал образец кода С# здесь.
Одна вещь, которую я нашел, - AMSI, требует, чтобы защитник Windows/любой антивирус включался, чтобы проверить файл, переданный API. Но запуск сканирования через MpClient.dll
приведет к проверке защитника, даже если защитник отключен.
Также убедитесь, что ваш проект нацелен на платформу x64
.
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);
}
Ответ 2
Я искал проблему, и я читал это как одну из возможных причин:
"Вы часто видите различия между сборками debug и release, потому что отладочные сборки содержат дополнительные метаданные для облегчения отладки.
здесь: 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
...
Итак, в соответствии с этими ответами и статьями я бы попытался:
1st Double check signature и COM interop thunks для всего неуправляемого кода, чтобы убедиться, что они верны.
2nd Set Отладчик Visual Studio для исключения этого исключения:
Меню "Сервис" → "Параметры" → "Отладка" → "Общие" → Снимите эту опцию "Отменить оптимизацию JIT при загрузке модуля"
3rd Try-Catch исключение
(примечание: если вы используете .Net 4, то в App.config, внутри тега изменить время выполнения, чтобы включить legacyCorruptedStateExceptionsPolicy enabled = "true", например:
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>
)
Кроме того, здесь, я обнаружил, что некоторые версии каркаса .net(последний комментарий к 4.6.1 в одном из комментариев) имеют ошибку связанный с этим исключением, и в прошлом решение было модернизовано.
Кроме того, в одном из этих ответов я читал:
Привет Существуют две возможные причины.
1. У нас есть управляемый код, и мы вызываем его из управляемого кода. что предотвращает запуск этого кода. попробуйте запустить эти команды и перезагрузите компьютер
cmd: netsh winsock reset
откройте файл cmd.exe и запустите команду "netsh winsock reset catalog" 2. Антивирус рассматривает не управляемый код как вредный и ограничивающий запуск этого кода, отключает антивирус, а затем проверяет
Я хотел бы знать, помогут ли некоторые из этих подходов решить вашу проблему.
Я действительно надеюсь, что это поможет.
КР,
Хуан
Ответ 3
Вы можете использовать Интерфейс сканирования Antimalware для проверки файла на наличие вредоносных программ.
Интерфейс сканирования Antimalware (AMSI) - это стандартный стандарт интерфейса, который позволяет приложениям и службам интегрироваться с любым антивирусным продуктом, присутствующим на машине. Он обеспечивает улучшенную защиту от вредоносных программ для пользователей и их данных, приложений и рабочих нагрузок.
Доступно начиная с Windows 10.