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

1 技术简介

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

2 Blindside技术原理

2.1 硬件断点

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

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

  • DR6寄存器解析

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

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

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

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

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

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

  • DR7寄存器解析

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 描述的是硬件断点的类型以及长度信息。

  • R/W0到R/W3:指定各个断点的触发条件。它们对应于DR0到DR3中的地址以及DR6中的4个断点条件标志。

// 00 只执行

// 01 写入数据断点

// 10 I/O端口断点(只用于pentium+,需设置CR4的DE位,DE是CR4的第3位 )

// 11 读或写数据断点

  • LEN0到LEN3:指定在调试地址寄存器DR0到DR3中指定的地址位置的大小。

  • 注意事项:

  • 如果R/Wx位为0,则LENx位也必须为0,否则会产生不确定的行为。R/Wx位为0是硬件执行断点。

  • 设置的地址要和长度对齐。

// 00 1字节

// 01 2字节

// 10 保留

// 11 4字节

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

2.2 调试异常

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

  • 调试异常(#DB):当除INT 3指令以外的调试事件发生时,会导致此异常

  • 断点异常(#BP):INT 3指令执行时会导致此异常,CPU转到该异常的处理例程。异常处理例程会进一步将异常分发给调试器软件

对于 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 以指示应继续搜索处理程序。

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

3 Blindside实现过程

3.1 Blindside实现原理

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

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

3.2 Blindside实现过程

  • 调试模式创建进程

  • 定位 LdrLoadDll 进程地址

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

  • 设置硬件断点

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

  • 等待断点触发

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

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

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

  • 加载内存并覆盖hook

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

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

  • 清理并恢复

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

4 结合其他技术实现dump lsass

4.1 结合RPC技术

  • 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的具体过程是在Secur_32.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 缓解措施

5.1SetThreadContext函数

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

5.2 检测调试功能

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

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

6 模拟攻击库更新

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值