蓝队必读 - ​利用硬件断点规避 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-05-11

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

1 2 3 4 5

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

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

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top