进程挂起从托管代码 pinvoking AmsiScanBuffer

2024-01-18

我正在尝试使用AmsiScanBuffer https://msdn.microsoft.com/en-us/library/windows/desktop/dn889865(v=vs.85).aspx来自托管代码(特别是 C#)的 Windows 反恶意软件服务接口的功能。当尝试调用该方法时,只要提供非零缓冲区长度,程序就会挂起调用。如果提供了 0 零的缓冲区长度,则该方法立即返回 HResult E_INVALIDARG。 AMSI 公开的其他方法按预期工作,因此我希望我相信此函数的 dllimport 很接近,但可能不完全正确。除了此处介绍的数组复制方法之外,我还尝试固定数组,并且行为是相同的。

C原型

HRESULT WINAPI AmsiScanBuffer(
  _In_     HAMSICONTEXT amsiContext,
  _In_     PVOID        buffer,
  _In_     ULONG        length,
  _In_     LPCWSTR      contentName,
  _In_opt_ HAMSISESSION session,
  _Out_    AMSI_RESULT  *result
);

托管代码

[DllImport("Amsi.dll", EntryPoint = "AmsiScanBuffer", CallingConvention = CallingConvention.StdCall)]
public static extern int ScanBuffer(IntPtr amsiContext, IntPtr ptr, ulong length, string contentName, IntPtr session, out int result);

var virus = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
var bytes = Encoding.UTF8.GetBytes(virus);
int sizet = Marshal.SizeOf(typeof(byte)) * bytes.Length;
var ptr = Marshal.AllocHGlobal(sizet);

try
{
    Marshal.Copy(bytes, 0, ptr, bytes.Length);
    int hr = Amsi.ScanBuffer(context, ptr, (ulong)sizet, "Unknown Data", session, out result);
}
finally
{
    Marshal.FreeHGlobal(ptr);
}

主要问题是length参数为AmsiScanBuffer. A ULONGWindows 上的 C/C++ 是 32 位,而ulongC# 中是 64 位。所以参数需要声明为uint。我预计即使您传递的缓冲区长度为零,在调试器下运行时也会出现“不平衡堆栈”错误。您还可以声明buffer as a byte[]然后传入bytes直接地。

为了进一步简化,您可以省略CallingConvention since StdCall是默认值。我还将其更改为使用确切的函数名称,因此无需在DllImport。一般来说,当我直接从 C# 使用 C 库时,我喜欢保留原始函数名称,例如AmsiScanBuffer而不是将其更改为Amsi.ScanBuffer。这使得当有人编写代码时查找文档变得更容易,尽管这当然是一个品味问题。

这是作为控制台应用程序的工作版本。

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace AmsiTest {

    class Program {
        static void Main( string[] args ) {

            var virus = Encoding.UTF8.GetBytes(
                "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
            );

            IntPtr context;
            var hrInit = AmsiInitialize( "AmsiTest", out context );
            if( hrInit != 0 ) {
                Console.WriteLine( $"AmsiInitialize failed, HRESULT {hrInit:X8}" );
                return;
            }

            AMSI_RESULT result;
            var hrScan = AmsiScanBuffer(
                context, virus, (uint)virus.Length,
                "EICAR Test File", IntPtr.Zero, out result
            );

            AmsiUninitialize( context );

            if( hrScan != 0 ) {
                Console.WriteLine( $"AmsiScanBuffer failed, HRESULT {hrScan:X8}" );
            } else if( result == AMSI_RESULT.AMSI_RESULT_DETECTED ) {
                Console.WriteLine( "Detected EICAR test" );
            } else {
                Console.WriteLine( $"Failed to detect EICAR test, result {result:X8}" );
            }

        }

        public enum AMSI_RESULT { 
            AMSI_RESULT_CLEAN = 0,
            AMSI_RESULT_NOT_DETECTED = 1,
            AMSI_RESULT_BLOCKED_BY_ADMIN_START = 16384,
            AMSI_RESULT_BLOCKED_BY_ADMIN_END = 20479,
            AMSI_RESULT_DETECTED = 32768
        }

        [DllImport( "Amsi.dll" )]
        public static extern uint AmsiInitialize(
            string appName,
            out IntPtr amsiContext
        );

        [DllImport( "Amsi.dll" )]
        public static extern uint AmsiScanBuffer(
            IntPtr amsiContext,
            byte[] buffer,
            uint length,
            string contentName,
            IntPtr session,
            out AMSI_RESULT result
        );

        [DllImport( "Amsi.dll" )]
        public static extern void AmsiUninitialize(
            IntPtr amsiContext
        );
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程挂起从托管代码 pinvoking AmsiScanBuffer 的相关文章

随机推荐