进程挂起来自托管代码的精确AmsiScanBuffer

时间:2018-01-12 18:09:48

标签: c# pinvoke dllimport

我正在尝试使用托管代码中的Windows防恶意软件服务接口的AmsiScanBuffer功能,特别是C#。尝试调用该方法时,只要提供非零缓冲区长度,程序就会挂起。如果提供的缓冲区长度为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);
}

1 个答案:

答案 0 :(得分:5)

主要问题是length的{​​{1}}参数。 Windows上的C / C ++中的AmsiScanBuffer是32位,而C#中的ULONG是64位。所以参数需要声明为ulong。我预计即使你传递的缓冲区长度为零,在调试器下运行时也会出现“不平衡堆栈”错误。您也可以将uint声明为buffer,然后直接传递byte[]

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

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

Amsi.ScanBuffer