Windows Defender Antivirus从C#扫描[AccessViolation exception]

我们正在编写一个代码,使用 Windows Defender API从C#对文件进行按需扫描.
[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,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,out phScanHandle); **//Getting Access violation exception here**.

可能是什么问题呢? struct的格式是否正确?

P.S – No information about MPRESOURCE_CLASS is available in msdn.

我不知道这行代码是否正确.

mpResourceInfo.Class = IntPtr.Zero;

更新:

快速扫描可以正常使用此代码

result = MpScanStart(phMpHandle,1,out phScanHandle);

Defender在事件查看器[应用程序和服务日志 – Microsoft-Windows-Windows Defender / Operational]中记录为

Windows Defender scan has started.
Scan ID:{CDC2AC0D-7648-4313-851C-4D8B7B5EB5CD}
Scan Type:AntiSpyware
Scan Parameters:Quick Scan

我一直在搜索问题,我已经看到这是一个可能的原因:

“You often see differences between debug and release builds because
debug builds contain extra Metadata to assist in debugging.”

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

还应该检查this answer“是否可以在.NET中捕获访问冲突异常”?以及MSDN杂志“Handling Corrupted State Exceptions”中解释的更多细节

所以,根据答案和文章我会尝试:

一个双重检查签名和COM interop thunks所有非托管代码,以验证它们是否正确.

第2集Visual Studio调试器绕过此异常:
工具菜单 – >选项 – >调试 – >一般 – >取消选中此选项“禁止模块加载上的JIT优化”

第3尝试抓住例外

(注意:如果您在App.config中使用.Net 4,则在标记修改运行时以包含legacyCorruptedStateExceptionsPolicy enabled =“true”,如下所示:

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

)

另外here,我发现一些.net框架版本(最新的评论指向4.6.1的答案的评论之一)有一个与这个异常相关的错误,解决方案过去一直在升级框架.
此外,在其中一个答案我读过:

Hi There are two possible reasons.

1.We have un-managed code and we are calling it from managed code. that is preventing to run this code. try running these commands and
restart your pc

cmd: netsh winsock reset

open cmd.exe and run command “netsh winsock reset catalog”
2.Anti-virus is considering un-managed code as harmful and restricting to run this code disable anti-virus and then check

我想知道这些方法有助于您解决问题.

我真的希望这有帮助.

KR,

胡安

相关文章

Windows注册表操作基础代码 Windows下对注册表进行操作使用的...
黑客常用WinAPI函数整理之前的博客写了很多关于Windows编程的...
一个简单的Windows Socket可复用框架说起网络编程,无非是建...
Windows文件操作基础代码 Windows下对文件进行操作使用的一段...
Winpcap基础代码 使用Winpcap进行网络数据的截获和发送都需要...
使用vbs脚本进行批量编码转换 最近需要使用SourceInsight查看...