进程挂起了从托管代码中调用AmsiScanBuffer的过程 [英] Process hangs pinvoking AmsiScanBuffer from managed Code

查看:133
本文介绍了进程挂起了从托管代码中调用AmsiScanBuffer的过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用

I am attempting to use the AmsiScanBuffer function of the Windows Anti-Malware Service Interface from managed code, specifically C#. When attempting to call the method the program hangs on the call anytime a non-zero buffer length is provided. If a buffer length of 0 zero is provided then the method returns immediately with the HResult E_INVALIDARG. The other methods exposed by AMSI work as expected so I expect the I believe my dllimport for this function to be close but probably not completely correct. Besides the array copy approach represented here I have tried pinning the array and the behavior is identical.

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

推荐答案

主要问题是AmsiScanBufferlength参数. Windows上C/C ++中的ULONG是32位,而C#中的ulong是64位.因此,该参数需要声明为uint.我希望您在调试器下运行时,即使传递的缓冲区长度为零,也会收到不平衡堆栈"错误.您还可以将buffer声明为byte[],然后直接直接传递bytes.

The main problem is the length parameter to AmsiScanBuffer. A ULONG in C/C++ on Windows is 32 bits, while a ulong in C# is 64 bits. So the parameter needs to be declared as a uint. I would have expected you'd get an "unbalanced stack" error when running under the debugger even if you passed a buffer length of zero. You can also declare buffer as a byte[] and then just pass in the bytes directly.

为进一步简化,您可以省略CallingConvention,因为StdCall是默认设置.我还更改了它以使用确切的函数名称,因此不必在DllImport中指定它.通常,当我直接从C#使用C库时,我喜欢保留原始函数名称,例如AmsiScanBuffer而不是将其更改为Amsi.ScanBuffer.这使在有人编写代码时查找文档更加容易,尽管这当然是有品味的.

For further simplification, you can omit the CallingConvention since StdCall is the default. I also changed it to use the exact function name so it isn't necessary to specify it in the DllImport. In general, when I'm working with C libraries directly from C# I like to keep the original function names, e.g. AmsiScanBuffer instead of changing it to Amsi.ScanBuffer. This makes it easier to look up docs when somebody is working on the code, although this is of course a matter of taste.

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

Here's a working version as a console application.

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

这篇关于进程挂起了从托管代码中调用AmsiScanBuffer的过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆