前言&背景
Microsoft 的反恶意软件扫描接口 (AMSI) 在 Windows 10 和更高版本的 Windows 中提供,用于帮助检测和预防恶意软件。 AMSI 是一个接口,它将各种安全应用程序(例如防病毒或反恶意软件软件)集成到应用程序和软件中,并在执行之前检查它们的行为。 OffSec 工作人员 Victor “Vixx” Khoury 在 System.Management.Automation.dll 中发现了一个可写条目,其中包含 AmsiScanBuffer 的地址,AmsiScanBuffer是 AMSI 的关键组件,应该被标记为只读,类似于导入地址表 (IAT)条目。在这篇文章中,我们将介绍并利用此漏洞进行 0day AMSI 绕过。
大多数 AMSI 绕过都会破坏 AMSI 库 Amsi.dll 中的函数或字段,从而导致 AMSI 崩溃来绕过它。除了崩溃或patch Amsi.dll 之外,攻击者还可以使用 CLR Hooking 绕过 AMSI,通过调用 VirtualProtect 并使用返回 TRUE 的HOOK覆盖它来更改 ScanContent 函数的保护功能。虽然 VirtualProtect 本身并不是恶意的,但恶意软件可能会滥用它来修改内存,从而逃避EDR和防病毒 (AV) 软件的检测。
分析过程
首先检查 Amsi.dll 的 AmsiScanBuffer 函数,该函数扫描内存缓冲区中是否存在恶意软件,许多应用程序和服务都利用此功能。在 .NET 框架内,Common LanguageRuntime (CLR) 利用System.Management.Automation.dll 内 AmsiUtils 类中的 ScanContent 函数,该函数是 PowerShell 核心库的一部分,来调用 AmsiScanBuffer。可以通过[PSObject].Assembly.Location查看该DLL位置,
然后用dnspy找到ScanContent位置,找到调用AmsiScanBuffer调用位置:
使用windbg附加powershell.exe,查看amis模块,以Amsi关键词的符号(symbol):
在AmsiScanBuffer 上设置一个断点:
随机读取一个文件或者键入字符串,触发断点,查看调用堆栈如下:
本次攻击的目标是System Management Automation ni 模块,它调用的函数,而不是直接去操作AmsiScanBuffer函数。
从System_Management_Automation_ni+0x1099e37处往后反汇编查看代码,每个人地址可能不一样:
0:011> ub System_Management_Automation_ni+0x1099e37 L10 System_Management_Automation_ni+0x1099df1: 00007ffa`109c9df1 488975c0movqword ptr [rbp-40h],rsi 00007ffa`109c9df5 4c8d4e0clear9,[rsi+0Ch] 00007ffa`109c9df9 4c897db8movqword ptr [rbp-48h],r15 00007ffa`109c9dfd 4c8b5db0movr11,qword ptr [rbp-50h] 00007ffa`109c9e01 4d8b5b20movr11,qword ptr [r11+20h] 00007ffa`109c9e05 498b03movrax,qword ptr [r11] 00007ffa`109c9e08 488b7530movrsi,qword ptr [rbp+30h] 00007ffa`109c9e0c 4889742420movqword ptr [rsp+20h],rsi 00007ffa`109c9e11 4c897c2428movqword ptr [rsp+28h],r15 00007ffa`109c9e16 41bb10000000movr11d,10h 00007ffa`109c9e1c 4c8b55b0movr10,qword ptr [rbp-50h] 00007ffa`109c9e20 4c895588movqword ptr [rbp-78h],r10 00007ffa`109c9e24 4c8d150c000000lear10,[System_Management_Automation_ni+0x1099e37 (00007ffa`109c9e37)] 00007ffa`109c9e2b 4c8955a0movqword ptr [rbp-60h],r10 00007ffa`109c9e2f 41c644240c00movbyte ptr [r12+0Ch],0 00007ffa`109c9e35 ffd0callrax
00007ffa 109c9e35 ffd0callrax就是对AmsiScanBuffer的调用位置,绕过 AMSI 的一种方法是patch call rax,这需要 VirtualProtect. 但是在调用函数之前,研究人员发现AmsiScanbuffer函数已经是可写状态了,注意看:
dqs @rbp-0x50 L1查看基址指针寄存器 rbp(当前堆栈帧的基址)之前 80 字节 (0x50)地址。一步步找到AmsiScanBuffer地址0x7ffa10b5d9b0,相对System_Management_Automation_ni模块偏移0x78d9b0。
分析调用
现在我们深入研究一下这块是怎么填充和保护的,现在用windbg launch powershell.exe。在System.Management.Automation.ni.dll设置触发断点,执行g,然后再在System Management Automation ni +0x78d9b0 处中断读/写ba r1 System_Management_Automation_ni + 0x78d9b0,执行g
clr!NDirectMethodDesc::SetNDirectTarget+0x3b处被断下,反汇编查看附件汇编代码:
我们发现rdi已经是AmsiScanBuffer函数地址,rsi正在被写入目标地址。
继续g执行,就会发现前文提到的调用位置:
所以PowerShell刚开始执行就会初始化AmsiScanBuffer函数地址,然后后面会直接调用一次。在初始化时候的断点,查看调用堆栈,会发现初始调用块也在 clr!ThePreStub中:
它是 .NET Framework 中的一个辅助函数,用于为初始执行准备代码,其中包括即时 (JIT) 编译。它会创建一个位于被调用方和原始调用方函数之间的存根。
所以,作为 JIT 的一部分,辅助函数将 AmsiScanBuffer 地址写入 DLL 入口地址中偏移量 0x78d9b0 处,但不会将权限更改回只读。我们可以通过覆盖该函数地址来绕过 AMSI 而不调用 VirtualProtect 来滥用此漏洞。
PoC-ps1
计算机和安装的 CLR 版本不一样会导致上述的0x78d9b0 偏移量不一样,poc参考https://github.com/V-i-x-x/AMSI-BYPASS/。
原文始发于微信公众号(TIPFactory情报工厂):不使用VirtualProtect且无需动内存绕过AMSI
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论