首页
社区
课程
招聘
[分享]不动内存不使用VirtualProtect的AMSI绕过原理(暂未修复)
2024-5-15 18:02 2021

[分享]不动内存不使用VirtualProtect的AMSI绕过原理(暂未修复)

2024-5-15 18:02
2021

前言&背景

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 Language Runtime (CLR) 利用 System.Management.Automation.dll 内 AmsiUtils 类中的 ScanContent 函数,该函数是 PowerShell 核心库的一部分,来调用 AmsiScanBuffer 。可以通过[PSObject].Assembly.Location查看该DLL位置,

image-20240514171022580

然后用dnspy找到ScanContent位置,找到调用AmsiScanBuffer调用位置:

image-20240514171134982

image-20240514171245809

使用windbg附加powershell.exe,查看amis模块,以Amsi关键词的符号(symbol):

image-20240514171855863

在AmsiScanBuffer 上设置一个断点:

image-20240514172016755

随机读取一个文件或者键入字符串,触发断点,查看调用堆栈如下:

企业微信截图_17156813461494

image-20240515142004385

本次攻击的目标是System Management Automation ni 模块,它调用的函数,而不是直接去操作AmsiScanBuffer函数。

从System_Management_Automation_ni+0x1099e37处往后反汇编查看代码,每个人地址可能不一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:011> ub System_Management_Automation_ni+0x1099e37 L10
System_Management_Automation_ni+0x1099df1:
00007ffa`109c9df1 488975c0        mov     qword ptr [rbp-40h],rsi
00007ffa`109c9df5 4c8d4e0c        lea     r9,[rsi+0Ch]
00007ffa`109c9df9 4c897db8        mov     qword ptr [rbp-48h],r15
00007ffa`109c9dfd 4c8b5db0        mov     r11,qword ptr [rbp-50h]
00007ffa`109c9e01 4d8b5b20        mov     r11,qword ptr [r11+20h]
00007ffa`109c9e05 498b03          mov     rax,qword ptr [r11]
00007ffa`109c9e08 488b7530        mov     rsi,qword ptr [rbp+30h]
00007ffa`109c9e0c 4889742420      mov     qword ptr [rsp+20h],rsi
00007ffa`109c9e11 4c897c2428      mov     qword ptr [rsp+28h],r15
00007ffa`109c9e16 41bb10000000    mov     r11d,10h
00007ffa`109c9e1c 4c8b55b0        mov     r10,qword ptr [rbp-50h]
00007ffa`109c9e20 4c895588        mov     qword ptr [rbp-78h],r10
00007ffa`109c9e24 4c8d150c000000  lea     r10,[System_Management_Automation_ni+0x1099e37 (00007ffa`109c9e37)]
00007ffa`109c9e2b 4c8955a0        mov     qword ptr [rbp-60h],r10
00007ffa`109c9e2f 41c644240c00    mov     byte ptr [r12+0Ch],0
00007ffa`109c9e35 ffd0            call    rax

00007ffa 109c9e35 ffd0 call rax就是对AmsiScanBuffer的调用位置,绕过 AMSI 的一种方法是patch call rax,这需要 VirtualProtect. 但是在调用函数之前,研究人员发现AmsiScanbuffer函数已经是可写状态了,注意看:

image-20240515143937926

image-20240515145941141

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

image-20240515152137593

clr!NDirectMethodDesc::SetNDirectTarget+0x3b处被断下,反汇编查看附件汇编代码:

image-20240515152414700

我们发现rdi已经是AmsiScanBuffer函数地址,rsi正在被写入目标地址。

继续g执行,就会发现前文提到的调用位置:

image-20240515153647568

所以PowerShell刚开始执行就会初始化AmsiScanBuffer函数地址,然后后面会直接调用一次。在初始化时候的断点,查看调用堆栈,会发现初始调用块也在 clr!ThePreStub中:

image-20240515153012381

它是 .NET Framework 中的一个辅助函数,用于为初始执行准备代码,其中包括即时 (JIT) 编译。它会创建一个位于被调用方和原始调用方函数之间的存根。

所以,作为 JIT 的一部分,辅助函数将 AmsiScanBuffer 地址写入 DLL 入口地址中偏移量 0x78d9b0 处,但不会将权限更改回只读。我们可以通过覆盖该函数地址来绕过 AMSI 而不调用 VirtualProtect 来滥用此漏洞。

PoC-ps1

计算机和安装的 CLR 版本不一样会导致上述的0x78d9b0 偏移量不一样,poc参考https://github.com/V-i-x-x/AMSI-BYPASS/。


阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞1
打赏
分享
最新回复 (4)
雪    币: 3992
活跃值: (5639)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
badboyl 2 2024-5-15 21:27
2
0
好文
雪    币: 354
活跃值: (970)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
iaoedsz2018 2024-5-15 21:35
3
0
妙哇
雪    币: 3138
活跃值: (2861)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
dayday向上8 2 2024-5-16 10:04
4
0
看标题我还以为要上硬断+异常呢
雪    币: 160
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
phperl 2024-5-17 16:55
5
0
把amsicontext的前8个字节改写成0就可以绕过了,scanbuffer会返回failed,也不会导致crash
游客
登录 | 注册 方可回帖
返回