Мы пишем код для сканирования по требованию файла с C# с использованием API-интерфейсов Windows Defender.Windows Defender Антивирусная проверка с C# [AccessViolation exception]
[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'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
Мы получаем это исключение
Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.
на
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 Защитник/Эксплуатация] как
Началось сканирование защитника Windows.
Scan ID: {CDC2AC0D-7648-4313-851C-4D8B7B5EB5CD}
Тип сканирования: АнтиШпион
Параметры сканирования: Быстрое сканирование
Священные закодированные пути, Бэтмен! Пожалуйста, не делайте этого. Что делать, если мой загрузочный диск не является дисководом C? А что, если Защитник Windows не установлен в Program Files? –
@CodyGray - Это POC. Но спасибо за указание. – mlg
Первая ошибка, которую я вижу, это объявление члена MPSCAN_RESOURCES.pResourceList. Это указатель на массив, а не UnmanagedType.ByValArray. Вы должны объявить его как IntPtr и маршалировать массив самостоятельно. Использование Pack = 1 также очень неверно. Там может быть больше ошибок, это не просто api. Вы будете впереди, используя C++/CLI, чтобы сделать это, по крайней мере, вы можете положиться на заголовочный файл mpclient.h. –