蓝队必读 - ​利用硬件断点规避 EDR检测的技术分析

近日,塞讯安全实验室发现了一项“利用硬件断点来规避EDR检测”的新技术,该技术被各黑客组织广泛利用。塞讯验证安全专家对此进行了详细深入的分析总结,以帮助企业安全团队更透彻地了解攻击者。

技术简介

“利用硬件断点来规避EDR检测”技术又被称为Blindside技术,该技术通过加载一个不受监控且未被挂钩的 DLL文件,且不挂钩特定函数,并运用允许运行任意代码的调试技术来实现EDR检测的规避。该调试技术一般在调试器中被广泛应用。

Blindside技术原理

2.1 硬件断点

在Blindside技术中需要使用硬件断点的相关知识,而且硬件断点是和CPU紧密相关的。接下来就先介绍硬件断点和硬件断点寄存器。OS/CPU提供了8个寄存器来供硬件断点使用,其中DR0-DR7是系统提供的硬件断点寄存器。与软件断点不同,硬件断点可用于设置“内存断点”或当任何指令尝试读取、写入或执行特定内存地址时触发的断点(取决于断点配置)。硬件断点的数量是有限的,允许最多一次设置4个硬件断点。硬件断点寄存器,也叫做调试寄存器,如下图所示。

其中,DR0 - DR3 用于保存断点的线性地址,也叫做“调试地址寄存器”。当其中一个寄存器中的地址与指令匹配时,将触发断点。DR4 - DR5是保留调试寄存器。

DR6是调试状态寄存器,主要作用是当CPU检测到匹配断点条件的断点或有其他调试事件发生时,用来向调试器的断点异常处理程序传递断点异常的详细信息。只有在生成异常时才会更新此寄存器。

该寄存器用于表示进入陷阱的原因,各个位的含义如下:

B0 B3位:表示的是如果其中任何一个位置位,则表示的是相应的DR0 - DR3断点引发的调试陷阱

BD位:表示的是GD(DR7)位置位情况下访问调试寄存器引发的陷阱

BT位:表示的是TSS任务切换时,若设置了T标志位,会引起调试异常,并使得BT位置位

BS位:表示的是单步中断引发的断点。即EFLAGS的TF置位时引发的调试陷阱。硬件断点抛出的异常也是单步异常

DR7 被称为“调试控制寄存器”。其中,L0、L1、L2、L3分别代表DR0、DR1、DR2、DR3是否启用,G0-G3可以忽略。

L/G:局部/全局。

GD:保护标志。

LE和GE:为了兼容性,Intel建议使用精确断点时把LE和GE都设置为1。(使用精确断点标志,P6及之后的CPU不支持该标志)

R/W0和LEN0 - R/W3和LEN3 描述的是硬件断点的类型以及长度信息。

// 00 只执行
// 01 写入数据断点
// 10 I/O端口断点(只用于pentium+,需设置CR4的DE位,DE是CR4的第3位 )
// 11 读或写数据断点

// 00 1字节
// 01 2字节
// 10 保留
// 11 4字节

对于 Blindside 技术,DR7 是最关键的寄存器,因为它控制每个断点并设置断点条件。

2.2 调试异常

当涉及到硬件断点异常时,会出现两种情况:调试异常(#DB)和断点异常(#BP)。

对于 Blindside 技术,调试异常 (#DB) 是最重要的。当触发断点时,执行将被重定向到处理程序。Blindside 技术中的异常只有在单步异常时才会被触发。

首先需要建立断点的处理程序。

handler函数首先检查EXCEPTION_POINTERS结构的ExceptionRecord成员中的ExceptionCode是否为EXCEPTION_SINGLE_STEP(单步异常)。如果是单步异常,则将检查ExceptionInfo结构的 ContextRecord 成员中的指令指针 (Rip) 是否等于Dr0的值。如果也是这样,该函数将会执行一些操作,比如打印异常信息等。

最后,该函数设置恢复标志 (RF),并返回 EXCEPTION_CONTINUE_EXECUTION 以指示应继续执行。如果ExceptionCode不是EXCEPTION_SINGLE_STEP,则该函数返回 EXCEPTION_CONTINUE_SEARCH 以指示应继续搜索处理程序。

接下来需要设置硬件断点。

3Blindside实现过程

3.1 Blindside实现原理

Blindside技术的实现原理是通过在调试模式下创建进程,在 LdrLoadDll 设置硬件断点,并强制加载 ntdll.dll,而不加载其他的dll文件,强制加载的 ntdll.dll 是没有被hook的,最后将强制加载的 ntdll.dll 内存复制到现有进程并卸载所有被hook的函数调用。

通过利用Blindside技术,使用硬件断点来hook LdrLoadDLL 来阻止加载额外的 dll 文件,并创建一个只有 ntdll 且未被hook的进程。


3.2 Blindside实现过程

创建的新进程是目标进程的子进程,和目标进程具备相同的 ntdll 基址以及 LdrLoadDll 的地址也是相同的。

定位到 LdrLoadDll 地址后设置硬件断点。

接下来,该函数调用 SetThreadContext() 函数将更新的上下文设置到线程。然后它进入一个无限循环,使用 WaitForDebugEvent() 函数等待调试事件。

当接收到调试事件时,函数会检查ExceptionCode是否为 EXCEPTION_SINGLE_STEP 的异常调试事件。如果是,该函数将使用 GetThreadContext() 函数检索线程的当前上下文,并检查异常地址是否与指定地址匹配。

如果异常地址与指定地址匹配,函数将重置 Dr0、Dr6 和 Dr7 寄存器并且不返回任何内容,这样做是为了阻止 LdrLoadDll 加载其他 DLL。否则,它会重置断点并使用 DBG_CONTINUE 参数调用 ContinueDebugEvent() 函数来继续执行。这个循环一直持续到 WaitForDebugEvent() 返回 0,表示没有更多的调试事件。

将 ntdll 的内存复制到目标进程中并取消hook任何系统调用。

首先获取到了NtReadVirtualMemory函数和VirtualProtect函数地址,通过NtReadVirtualMemory函数读取未被hook的ntdll内存,接下来就是遍历找到ntdll的.text段的虚拟地址,将保护改为PAGE_EXECUTE_READWRITE,将新映射缓冲区(freshNtdll)的.text段复制到被hook版本的ntdll中,这将导致挂钩被覆盖。

恢复内存保护以及结束不再使用的进程。

结合其他技术实现dump lsass

4.1 结合RPC技术

RPC,全称“Remote Procedure Call”,即远程过程调用,RPC在Windows上的设计是一种强大、健壮、高效且“安全”的进程间通信 (IPC) 机制,它支持数据交换和调用驻留在不同进程中的功能。

RPC技术主要是通过RPC控制lsass进程来加载SSP DLL实现dump lsass。其中SSP(Security Support Provider)是一个DLL,允许开发者提供一些回调函数,以便在特定认证和授权事件期间调用,而通过模拟AddSecurityPackage函数调可以实现让RPC向lsass发送信号加载我们自己定义的SSP DLL文件,通过自定义的SSP DLL文件来dump lsass内存。

在使用RPC技术需要使用一个API函数,即AddSecurityPackage函数,该函数主要的作用是向lsass发送RPC调用信号加载一个新的SSP DLL。而AddSecurityPackage函数注册SSP的具体过程是在Secur32.dll和sspcli.dll文件中完成的。在AddSecurityPackage函数中主要通过NdrClientCall3函数来实现RPC调用。

下面就具体分析真实的调用过程:

sub_1800141D0函数调用sub_180004304函数。

sub_180004304函数调用sub_180006760函数。

最终在sub_180006760函数调用的NdrClientCall3函数,由下图可知NdrClientCall3函数的参数信息。

下面的代码用来构造SecurityPackage包。

用来创建RPC连接字符串以及RPC句柄。其中需要SSPI RPC服务器在LSASS过程中使用的具体端点,该字符串是保存在sspisrv.dll文件中的SspiSrvInitialize()导出函数。

SspiSrvInitialize函数调用RpcServerUseProtseqEpW和RpcServerUseProtseqEp函数告诉RPC运行时库使用具有指定端点组合指定的协议序列,主要用于接收远程过程调用,如下图所示,lsasspirpcSSPI RPC服务器在LSASS过程中使用的具体端点就是lsasspirpc。

通过调用Proc0_SspirConnectRpc和Proc3_SspirCallRpc函数完成对AddSecurityPackage函数的直接调用。

其中Proc0_SspirConnectRpc和Proc3_SspirCallRpc函数是对NdrClientCall3函数的封装,NdrClientCall3函数主要负责RPC的调用。

其中自定义SSP DLL文件使用了两种不同的函数分别进行测试

第一种:MiniDump函数

第二种:MiniDumpWriteDump函数

火绒和360安全卫士为最新版。

静态查杀以及动态执行火绒没有报警。

静态查杀以及动态执行火绒没有报警,云查杀也没有报警。

测试没有使用Blindside技术,直接利用RPC技术则会直接拦截和查杀。

缓解措施

5.1SetThreadContext函数

监视 SetThreadContext 函数的使用。通过检查攻击者是否把地址写入到调试地址寄存器 (DR0 - DR3) 中,来确定硬件断点是否被滥用。

5.2 检测调试功能

当使用调试功能时,可以检测调试寄存器 (DR0 - DR3) 是否存在可疑功能。如果既有调试功能,在调试寄存器中又存在数据内容,则可能存在恶意行为。

需要通过对多种行为监控来确定是否使用Blindside技术,而不是单纯的通过某一种行为确定恶意。

模拟攻击库更新

塞讯安全度量验证平台已将此技术纳入模拟攻击库,在平台内搜索“Blindside”即可获得相关攻击模拟实验,从而验证安全防御体系是否能够有效应对这一攻击手段。


推荐阅读
2023年7个值得注意的勒索软件威胁预测

OWASP中国安全技术论坛回顾|安全验证如何验证Web安全

塞讯验证入选ISC 2022数字安全创新能力百强

公众号:塞讯验证

展开阅读全文

页面更新:2024-04-25

标签:断点   硬件   寄存器   技术   函数   进程   加载   异常   内存   地址

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top