基于内存补丁的AMSI绕过
AMSI的全称是反恶意软件扫描接口(Anti-Malware Scan Interface),是从Windows 10开始引入的一种机制。AMSI是应用程序和服务能够使用的一种接口,程序和服务可以将“数据”发送到安装在系统上的反恶意软件服务(如Windows Defender)。
服务和应用程序可以通过AMSI来与系统中已安装的反恶意软件通信。为了完成该任务,AMSI采用了hook方法。比如,AMSI会hook WSH(Windows Scripting Host)及PowerShell来去混淆并分析正在执行的代码内容。这些内容会被“捕获”,并在执行之前发送给反恶意软件 解决方案。
在Windows 10上,实现AMSI的所有组件如下所示:
- UAC(用户账户控制),安装EXE、COM、MSI或者ActiveX时提升权限
- PowerShell(脚本、交互式使用以及动态代码执行)
- Windows Script Host(
wscript.exe
或者cscript.exe
) - JavaScript以及VBScript
- Office VBA宏
AMSI整体架构如下图所示:

简单的说AMSI就是这玩意:

根据前人的研究,我们知道字符串是否敏感是由amsi.dll中的AmsiScanBuffer函数来进行判断的,而内存补丁是一种较为便捷的技术,我们可以对这个函数进行修补,使其丧失判断能力,这样我们就能自由执行任意powershell脚本,当然前提是脚本文件没有被杀软干掉。
实现方式有很多种,如注入一个内存修补功能的dll、获取amsiscanbuffer函数地址使用winapi进行修补。
这里我们使用获取函数地址对其进行修补,流程如下:
- 1.创建一个powershell进程
- 2.获取amsiscanbuffer函数地址
- 3.修改函数内存空间属性
- 4.修补函数执行体
前面文章有阐述过目前windows不同进程加载同一个系统模块的地址是一致的,所以我们可以使用本地加载dll获取对应函数地址去修补其他进程的该函数。
根据微软官方文档,AmsiScanBuffer
函数应该返回HRESULT
类型值,这是一个整数值,用来表示操作是否成功。在我们的例子中,如果该函数成功,那么就应当返回S_OK
(0x00000000
),否则应该返回HRESULT
错误代码。这个函数的主要功能是返回需要扫描的内容是否存在问题,这也是result
变量会作为参数传递给AmsiScanBuffer
函数的原因所在。这个变量的类型为AMSI_RESULT
枚举类型。对应的枚举原型如下所示:typedef enum AMSI_RESULT {AMSI_RESULT_CLEAN,AMSI_RESULT_NOT_DETECTED,AMSI_RESULT_BLOCKED_BY_ADMIN_START,AMSI_RESULT_BLOCKED_BY_ADMIN_END,AMSI_RESULT_DETECTED};