web-dev-qa-db-ja.com

C#からのWindows DefenderAntivirusスキャン[AccessViolation例外]

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

コードは、次のWebサイトで入手可能なドキュメントに基づいて記述されています。

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;

更新:

クイックスキャンは次のコードで正常に機能しています。

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

Defenderはイベントビューアにログインします[アプリケーションとサービスログ-Microsoft-Windows-Windows Defender/Operational]。

Windows Defenderスキャンが開始されました。
スキャンID:{CDC2AC0D-7648-4313-851C-4D8B7B5EB5CD}
スキャンタイプ:AntiSpyware
スキャンパラメータ:クイックスキャン

18
mlg

ここでは問題を特定できませんでした。そのため、Windows 10から Antimalware Scan Interface (AMSI)が利用可能になりました。

サンプルのC#コード here を書きました。
AMSIは、APIに渡されたファイルを確認するために、Windows Defender /アンチウイルスを有効にする必要があるAMSIを見つけました。ただし、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);
}
13
mlg

私は問題について探していて、考えられる原因の1つとしてこれを読みました:

「デバッグビルドにはデバッグを支援する追加のメタデータが含まれているため、デバッグビルドとリリースビルドの違いがよく見られます。」

ここ: 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マガジンの記事 破損した状態の例外の処理 で説明されている詳細
.。

だから、その答えと記事によると、私は試してみます:

最初に、すべてのアンマネージコードの署名とCOM相互運用サンクを再確認して、それらが正しいことを確認します。

2番目にこの例外をバイパスするようにVisualStudioデバッガーを設定します:[ツール]メニュー-> [オプション]-> [デバッグ]-> [一般]-> [モジュールの読み込み時にJIT最適化を抑制する]のチェックを外します

3回目の試行-例外をキャッチ

(注:.Net 4を使用している場合は、App.configで、タグ内でランタイムを変更して、legacyCorruptedStateExceptionsPolicy enabled = "true"を含めます。

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

さらに、 ここ 、いくつかの.netフレームワークバージョン(最新のコメントは回答のコメントの1つで4.6.1を指している)には、この例外と解決策に関連するバグがあることがわかりました。過去、フレームワークをアップグレードしてきました。また、私が読んだその答えの1つで:

こんにちは2つの考えられる理由があります。

1.アンマネージコードがあり、マネージコードから呼び出しています。それがこのコードの実行を妨げています。これらのコマンドを実行して、PCを再起動してください

cmd:netsh winsockリセット

cmd.exeを開き、コマンド「netsh winsock resetcatalog」を実行します。2。アンチウイルスは、管理されていないコードを有害であると見なし、このコードの実行を制限してアンチウイルスを無効にしてからチェックします。

これらのアプローチのいくつかがあなたの問題を解決するのに役立つかどうか知りたいのですが。

これがお役に立てば幸いです。

KR、

ファン

3
Juan

Antimalware Scan Interface を使用して、ファイルにマルウェアがないか確認できます。

マルウェア対策スキャンインターフェイス(AMSI)は、アプリケーションとサービスをマシン上に存在するマルウェア対策製品と統合できるようにする汎用インターフェイス規格です。ユーザーとそのデータ、アプリケーション、およびワークロードにマルウェア保護を強化します。

Windows10以降で利用できます。

2
Ivan Zhakov