开发人员受众和示例代码

反恶意软件扫描接口是为两组开发人员设计的。

  • 希望从应用中请求反恶意软件产品的应用程序开发人员。
  • 反恶意软件产品的第三方创建者希望其产品为应用程序提供最佳功能。

应用程序开发人员

AMSI 专为打击“无文件恶意软件”而设计。 可以充分利用 AMSI 技术的应用程序类型包括脚本引擎、在使用前需要扫描内存缓冲区的应用程序,以及处理可包含非 PE 可执行代码(如 Microsoft Word 和 Excel 宏或 PDF 文档)的文件的应用程序。 然而,AMSI 技术的实用性并不局限于这些示例。

有两种方法可以在应用程序中与 AMSI 进行交互。

有关介绍如何在 COM 应用程序中使用 AMSI 的示例代码,请参阅 IAmsiStream 接口示例应用程序

反恶意软件产品的第三方创建者

作为反恶意软件产品的创建者,可以选择创建并注册自己的进程内 COM 服务器 (DLL),以充当 AMSI 提供程序。 AMSI 提供程序必须实现 IAntimalwareProvider 接口,并且必须在进程内运行。

请注意:在 Windows 10 版本 1709(2017 年秋季创建者更新)之后,如果 AMSI 提供程序 DLL 依赖于要同时加载的路径中的其他 DLL,则你的 AMSI 提供程序 DLL 可能无法正常工作。 为了防止 DLL 劫持,我们建议提供程序 DLL 使用安全 LoadLibrary 调用或等效方式显式(使用完整路径)加载其依赖项。 我们建议这样做,而不是依赖 LoadLibrary 搜索行为。

以下部分介绍如何注册 AMSI 提供程序。 有关显示如何编写自己的 AMSI 提供程序 DLL 的完整示例代码,请参阅 IAntimalwareProvider 接口示例应用程序

向 AMSI 注册提供程序 DLL

首先,需要确保这些 Windows 注册表项存在。

  • HKLM\SOFTWARE\Microsoft\AMSI\Providers
  • HKLM\SOFTWARE\Classes\CLSID

AMSI 提供程序是进程内 COM 服务器。 因此,它需要向 COM 注册自身。 COM 类在 HKLM\SOFTWARE\Classes\CLSID 中注册。

以下代码示例显示如何注册 AMSI 提供程序,我们将假定其 GUID(在本例中)为 2E5D8A62-77F9-4F7B-A90C-2744820139B2

#include <strsafe.h>
...
HRESULT SetKeyStringValue(_In_ HKEY key, _In_opt_ PCWSTR subkey, _In_opt_ PCWSTR valueName, _In_ PCWSTR stringValue)
{
    LONG status = RegSetKeyValue(key, subkey, valueName, REG_SZ, stringValue, (wcslen(stringValue) + 1) * sizeof(wchar_t));
    return HRESULT_FROM_WIN32(status);
}

STDAPI DllRegisterServer()
{
    wchar_t modulePath[MAX_PATH];
    if (GetModuleFileName(g_currentModule, modulePath, ARRAYSIZE(modulePath)) >= ARRAYSIZE(modulePath))
    {
        return E_UNEXPECTED;
    }

    // Create a standard COM registration for our CLSID.
    // The class must be registered as "Both" threading model,
    // and support multithreaded access.
    wchar_t clsidString[40];
    if (StringFromGUID2(__uuidof(SampleAmsiProvider), clsidString, ARRAYSIZE(clsidString)) == 0)
    {
        return E_UNEXPECTED;
    }

    wchar_t keyPath[200];
    HRESULT hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Classes\\CLSID\\%ls", clsidString);
    if (FAILED(hr)) return hr;

    hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, L"SampleAmsiProvider");
    if (FAILED(hr)) return hr;

    hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Classes\\CLSID\\%ls\\InProcServer32", clsidString);
    if (FAILED(hr)) return hr;

    hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, modulePath);
    if (FAILED(hr)) return hr;

    hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, L"ThreadingModel", L"Both");
    if (FAILED(hr)) return hr;

    // Register this CLSID as an anti-malware provider.
    hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Microsoft\\AMSI\\Providers\\%ls", clsidString);
    if (FAILED(hr)) return hr;

    hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, L"SampleAmsiProvider");
    if (FAILED(hr)) return hr;

    return S_OK;
}

如果 DLL 实现 DllRegisterServer 函数,如上例所示,则可以使用 Windows 提供的可执行文件 regsvr32.exe 注册。 从提升的命令提示符中,发出以下形式的命令。

C:>C:\Windows\System32\regsvr32.exe SampleAmsiProvider.dll

在本例中,该命令将创建以下条目。

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{2E5D8A62-77F9-4F7B-A90C-2744820139B2}

    (默认值)REG_SZ 示例 AMSI 提供程序实现

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{2E5D8A62-77F9-4F7B-A90C-2744820139B2}\InprocServer32

    (默认值)REG_EXPAND_SZ %ProgramFiles%\TestProvider\SampleAmsiProvider.dll

    ThreadingModel REG_SZ Both

除了常规的 COM 注册,还需要向 AMSI 注册提供程序。 可以通过向以下键添加一个条目来完成此操作。

HKLM\SOFTWARE\Microsoft\AMSI\Providers

例如,

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\Providers\{2E5D8A62-77F9-4F7B-A90C-2744820139B2}

已知问题

流程不符合签名级别要求

如果你有 Windows 保护进程灯(PPL)或反恶意软件保护进程灯(反恶意软件 PPL)的非Microsoft反恶意软件服务,则尝试在 AMSI 提供程序中加载,可能会在代码完整性事件日志中看到以下信息:

 
Log Name: Microsoft-Windows-CodeIntegrity/Operational 

Source: Microsoft-Windows-CodeIntegrity 

Event ID: 3033 

Description: 

Code Integrity determined that a process (\Device\HarddiskVolume3\<Folder>\<Folder w/ the ISV name>\<Folder w/ the product name>\<ProcessName>.exe) attempted to load \Device\HarddiskVolume3\<Folder>\<Folder w/ the ISV name>\<Folder w/ the product name>\<Your Amsi Provider>.dll that did not meet the Custom 3 / Antimalware signing level requirements. 

若要查看代码完整性事件日志,请执行以下步骤:

  1. 打开“事件查看器”。

  2. 在导航窗格中,展开应用程序和服务日志>Microsoft>Windows>代码完整性,然后选择“操作”。

或者,如果已启用系统审核完整性审核,请查找以下项:

  • 日志名称:安全性
  • 来源:Microsoft Windows 安全
  • 事件 ID: 5038

文件哈希无效

AMSI API 旨在处理非受保护的进程。 ISV 无法对其已注册在 AMSI 的 DLL 进行签名,以使其能够加载到经过 ELAM/PPL 保护的进程中。 在这种情况下,你可能会在 Windows 安全事件日志中看到以下信息:


Description: 

Code integrity determined that the image hash of a file is not valid.  The file could be corrupt due to unauthorized modification, or the invalid hash could indicate a potential disk device error. 

File Name: \Device\HarddiskVolume3\<Folder> \<Folder w/ the ISV name> \<Folder w/ the product name>\<Your Amsi Provider>.dll 

若要查看 Windows 安全事件日志,请执行以下步骤:

  1. 打开“事件查看器”。

  2. 在导航窗格中,展开 Windows 日志,然后选择 安全

解决方法:

可以按照以下步骤筛选出事件:

  1. 若要筛选出事件(例如事件 ID 3033 或 5038),请打开事件查看器。

  2. 在导航窗格中,展开应用程序和服务日志>Microsoft>Windows>代码完整性,然后选择“操作”。

  3. 右键单击 操作,然后选择筛选当前日志...

  4. <所有事件 ID> 框中,键入 -3033(或 -5038),然后选择 确定

或者,在事件查看器中,可以展开 Windows 日志,右键单击“安全性”,选择 “筛选当前日志...”,然后指定 -3033-5038

提示

如果使用 Windows 事件转发(WEF),可以筛选要转发的事件 ID 或描述的详细信息。 有关详细信息,请参阅 技术社区博客:Windows 事件查看器中的高级 XML 筛选

在 SIEM 中排除事件 3033 和 5038。

如果您的组织使用SIEM服务器,请确保筛选出与AMSI相关的事件ID 3033和/或事件ID 5038,以避免引入对安全运营中心(SOC)分析师无效的信息。 有关详细信息,请参阅 使用 Windows 事件转发来帮助进行入侵检测