首页 >> 网络安全 >>渗透测试 >> 使用SharpBlock的无补丁AMSI旁路
详细内容

使用SharpBlock的无补丁AMSI旁路

时间:2020-11-17        阅读

对于那些关注我的个人博客文章创建EDR和绕过它的人,我开发了一种名为SharpBlock的新工具。该工具实现Windows调试器,以防止EDR或任何其他DLL加载到SharpBlock启动的进程中。

SharpBlock的初始版本中缺少的一项功能是能够绕过AMSI。

当前,有几种AMSI旁路可用于逃避最新和最大的恶意软件有效负载。有些涉及修改的有效载荷本身就像@HackingDave在他的视频的第一部分展示了这里,和其他涉及修补其AmsiScanBuffer代码CyberArk报道,在2018年回来。

最初,我的计划只是按照CyberArk演示的相同方式对AmsiScanBuffer代码进行修补,但是在我的研究过程中,我还遇到了F-Secure的博客,其中包括Hunting for AMSI绕过因此,出于绕过EDR的精神,我开始了绕过AMSI而不需要修补代码的道路。

SharpBlock调试器

SharpBlock通过实现调试器来运行,该调试器侦听DLL加载事件并阻止DLL入口点执行。到目前为止,它还不是真正成熟的调试器,因为它只对特定事件感兴趣。这让我开始思考,是否可以扩展SharpBlock的调试器功能并自动执行在代码内设置断点和更改返回值的行为,而无需修补代码。

对于非开发人员而言,断点本质上是放在特定代码或指令行上的书签,当执行到该特定点时,该书签将暂停程序。这使开发人员可以检查该程序当时在做什么。然后,开发人员可以检查和修改程序中的变量并返回值,然后在就绪后继续执行。

对于x86 / x86_64上的本机编译程序,有两种实现断点的方法:软件和硬件。软件断点是没有问题的,因为这实际上涉及修补我们打算放置断点的代码,从而使AMSIDetection等工具可以检测到我们的ASMI旁路。这样就给我们留下了硬件断点。在Intel / AMD CPU上有一组特殊的调试寄存器,每个线程最多允许4个硬件断点。

有问题的寄存器编号为Dr0至Dr7。Dr0-Dr3存储我们的断点地址,而Dr6和Dr7是控制寄存器,用于启用断点并确定在遇到断点时触发了哪些断点。一旦在特定线程上设置了DR寄存器,当指令指针即将在断点地址执行指令时,CPU将触发一个int 1中断(单步),然后由调试器捕获。

EnableBreakpoint的SharpBlock实现:

1.jpg

Amsi初始化旁路

AmsiScanBuffer修补程序是有效的旁路,实际上,可以在进程开始后很长时间使用它。另一方面,SharpBlock从一开始就控制该过程,因此考虑到这一点,我想知道是否可以尽早禁用AMSI并尽可能多地清除以免被发现。

AmsiScanBuffer需要在调用之前创建上下文,这是使用AmsiInitialize API完成的。作为我的EDR研究的一部分,我注意到某些解决方案支持完全禁用AMSI扫描界面。禁用后,AmsiInitialize函数将返回错误0x80070002,这意味着由于未创建有效上下文,因此从未调用过AmsiScanBuffer。这就是SharpBlock的计划,在AmsiInitialize上设置一个断点,然后更新返回值以防止创建有效的上下文。

当达到断点时,SharpBlock将被EXCEPTION_DEBUG_EVENT中断。异常代码包含值0x80000004,它是SINGLE_STEP异常的常量。到那时,我们可以查询触发异常的线程上下文,该上下文会在断点时返回所有寄存器状态。

击中AmsiInitialize断点时相关寄存器的状态:

2.jpg

绕过的目的是将当前指令指针改回到AmsiInitialize的调用者,并用0x8007002更新返回值以指示AMSI当前处于禁用状态。我们实质上要模拟的是RET指令,这样实际上不会调用AmsiInitialize。为此,我们需要在线程上下文上更新3个独立的任务。

  • 第一种是将当前指令指针更新为调用者。这是通过读取RSP当前指向的内存地址来实现的,因为在函数的第一条指令中,这将是返回地址。

  • 第二种是将RAX寄存器设置为我们的返回值0x8007002

  • 第三是增加堆栈指针,使其指向与实际执行RET指令相同的位置。

DisableAMSI的SharpBlocks实现:

3.jpg

上面的代码中使用的Context64类是本机API的GetThreadContext和SetThreadContext的轻包装,它们实质上使应用程序能够查询和更改线程及其寄存器的当前状态。名为AmsiInitialize的线程现在处于指示AMSI已被禁用且未创建任何上下文的状态。

清理

我可以想到的一种检测此绕过的方法是定期检索所有线程的上下文,并查看AmsiInitialize上是否设置了任何断点。为了解决这个问题,在恢复调试后的程序之前,我们还需要清理。由于我们不再需要断点,因此我们可以遍历所有调试对象的线程并清除断点。

清除所有硬件断点:

4.jpg

可在GitHub上找到SharpBlock的最新代码,其中包括AMSI旁路方法。

https://github.com/CCob/SharpBlock


.
更多

1589982338979126.png


ots网络社区

www.ots-sec.cn

联系方式
更多

投稿邮箱:1481840992@qq.com

交流群2群:622534175

ots网络社区3群:1078548359

关注我们
更多
技术支持: 建站ABC | 管理登录