利用硬件断点逃避端点检测和响应 (EDR) 平台和其他控制系统的监控并不是一个新概念。威胁行为者和研究人员都曾利用断点注入命令并执行恶意操作。
使用 Windows 事件跟踪 (ETW) 和 Windows 反恶意软件扫描接口 (AMSI) 的概念验证 (PoC) 技术已经存在一段时间了。其中包括由@rad9800创建的 TamperingSyscalls和由EthicalChaos创建的进程内无补丁 AMSI 绕过等深入工作 - 但在这两种情况下,攻击都是通过挂接当前进程内存中的特定函数来操纵它以达到非预期目的来执行的。
Cymulate 攻击研究小组能够将该方法扩展为一种名为“Blindside”的新技术,从而使该方法能够更广泛地发挥作用。Blindside技术不是挂接特定函数,而是加载不受监控且未挂接的 DLL,并利用可以运行任意代码的调试技术。
这使得在许多商业 EDR 和 XDR 平台的监视之外执行代码具有更大的灵活性。
硬件断点和调试寄存器 (DR0-DR7) 概述
由于 Blindside 依赖于硬件断点,因此了解这些断点和调试寄存器的功能至关重要。
什么是硬件断点和调试寄存器?
x86 和 x64 处理器均提供硬件断点,包含八个调试寄存器:DR0 – DR7。这些寄存器的长度为 32 位或 64 位(具体取决于处理器类型),用于控制调试操作的监控。
与 Windows 开发人员更熟悉的软件断点不同,硬件断点允许“内存断点”,当指令尝试读取、写入或执行指定的内存地址时触发(基于断点配置)。但是,限制是任何时候只能激活几个硬件断点。
调试寄存器(DR0-DR7)的功能
DR0-DR3:保存断点的线性地址,称为调试地址寄存器。当指令与其中一个寄存器中的地址匹配时,断点就会触发。
DR4-DR5:这些是保留的调试寄存器,在本技术中未使用。
DR6:称为调试状态寄存器,它报告上次异常期间采样的调试条件。
DR7:调试控制寄存器在 Blindside 技术中至关重要,因为它控制每个断点及其条件。
这些调试寄存器的主要功能是设置和监控最多 4 个编号为 0 到 3 的断点。对于每个断点,可以指定以下信息:
断点发生的线性地址。
断点位置的长度(1、2 或 4 个字节)。
该操作将在生成调试异常的地址执行。
断点是否启用。
生成调试异常时断点条件是否存在。
调试异常
当谈到硬件断点中的异常时,这里有两种后果:调试异常 (#DB) 和断点异常 (#BP)。对于 Blindside 技术而言,调试异常 (#DB) 是最重要的。触发断点时,执行将重定向到处理程序 - 通常是调试器程序或更广泛的软件系统的一部分。需要注意的是,Blindside 技术中的异常只有在单步异常时才会被触发。
设置盲区技术
步骤 1:断点处理程序
在准备使用该技术时,第一个要求是建立一个断点处理程序。以下是 C++ 中处理程序的一个示例:
该函数首先检查 EXCEPTION_POINTERS 结构的 ExceptionRecord 成员中的异常代码是否为 EXCEPTION_SINGLE_STEP,这表明发生了单步异常。如果是,该函数接着检查该结构的 ContextRecord 成员中的指令指针 (Rip) 是否等于第一个调试寄存器 (Dr0) 的值。如果也是这样,该函数将打印有关异常的一些信息,包括异常地址、某些寄存器的值以及堆栈指针 (Rsp) 的值。
最后,该函数设置恢复标志 (RF),并返回 EXCEPTION_CONTINUE_EXECUTION 以指示应继续执行。如果异常代码不是 EXCEPTION_SINGLE_STEP,则该函数返回 EXCEPTION_CONTINUE_SEARCH 以指示应继续搜索处理程序。
技术设置第 2 部分:设置断点
配置处理程序来处理异常后,准备的下一步是创建实际的断点。
像以前一样使用 C++,下面是断点配置的示例:
此函数有两个参数。第一个是系统应在其上设置断点的地址,第二个是启用或禁用断点。然后,该技术获取正在执行的指定线程的当前上下文并将其存储在上下文变量中。如果 setBP 变量为真,则代码将 DR0 设置为攻击者希望在其上设置断点的地址。请注意,如果需要,该技术也可以使用 Dr1、Dr2 或 Dr3 来存储地址。此后,执行将 Dr7 的第一位设置为 1 以启用断点,并清除位 16 和 17 以中断执行。
相反,如果 setBP 变量为 false,代码将清除 Dr0,并对 Dr7 的第一位执行相同操作。最后,代码设置线程的上下文以便更新。
利用盲区
在研究这个主题时,Cymulate 回顾了许多研究专业人员创建的有关通用方法的重要工作。Cymulate 攻击研究小组意识到,一种与已知技术不同的技术可以在调试模式下创建一个新进程,在 LdrLoadDll 上设置断点,并强制仅加载 ntdll.dll。这会产生一种情况,即结果是干净的 ntdll 版本,没有挂钩。然后,攻击者可以将干净的 ntdll 的内存复制到现有进程并解除所有先前挂钩的系统调用。
当进程首次创建时,ntdll.dll 会自动加载,但其他 dll 也会发挥作用。通过利用这种技术,断点通过挂接 LdrLoadDLL 来阻止其他 dll 的加载,并创建一个仅具有 ntdll 的独立、未挂接状态的进程。
穿越盲区技术
查看整个过程时,应用 Blindside 技术可以允许未监视的进程在 Windows 会话的上下文中运行,如下所示:
步骤 1:在调试模式下创建一个新进程
第 2 步:找到 LdrLoadDll 的进程地址
因为创建的进程是目标子进程,所以它将具有相同的 ntdll 基地址和相同的 LdrLoadDll 地址。这意味着必须识别 LdrLoadDll 的地址。
步骤 3:设置断点
找到LdrLoadDll地址后,下一个需要的函数是在远程进程上放置断点。
该函数接受两个参数:应设置断点的地址和应设置断点的线程的句柄。
该函数首先初始化一个 CONTEXT 结构,并将其 ContextFlags 成员设置为 CONTEXT_DEBUG_REGISTERS 和 CONTEXT_INTEGER 的按位或,这指定该结构应填充线程的当前调试寄存器和整数寄存器。然后它将第一个调试寄存器 (Dr0) 的值设置为指定地址,并设置 Dr7 寄存器的第 0 位以启用断点。
步骤 4:等待断点触发
接下来,该函数调用 SetThreadContext() 函数将更新后的上下文应用于线程。然后,它进入一个无限循环,使用 WaitForDebugEvent() 函数等待调试事件。当收到调试事件时,该函数检查它是否是异常调试事件,异常代码为 EXCEPTION_SINGLE_STEP。如果是,该函数使用 GetThreadContext() 函数检索线程的当前上下文,并检查异常地址是否与指定的地址匹配。
如果异常地址与指定地址匹配,则该函数将重置 Dr0、Dr6 和 Dr7 寄存器并且不返回任何内容,这样做是为了阻止 LdrLoadDll 加载其他 DLL。否则,它将重置断点并通过使用 DBG_CONTINUE 参数调用 ContinueDebugEvent() 函数继续执行。此循环持续到 WaitForDebugEvent() 返回 0,表示没有更多可用的调试事件。
步骤 5:内存加载和解除挂钩
然后需要将 ntdll 的内存复制到目标进程中并解除所有系统调用。
此函数有一个参数,即创建的调试进程的句柄。调试进程的基址将与 ntdll 基址相同。使用 NtReadVirtualMemory 读取 ntdll 的内存后,freshNtdll(分配的缓冲区将存储该内存信息。现在可以安全地终止原始进程,因为不再需要它了。
步骤 6:覆盖钩子
接下来需要遍历所有内容来找到ntdll的.text部分的虚拟地址,将保护改为PAGE_EXECUTE_READWRITE,并将新映射缓冲区(freshNtdll)的.text部分复制到原来被钩住的ntdll版本中,这将导致钩子被覆盖。
步骤 7:清理
完成此技术的最后一步是恢复原始保护。
减轻盲区
Blindside 技术并非不受缓解措施影响。尽管它可以绕过依赖钩子检测行为的 EDR(端点检测和响应)解决方案,但有几种策略可以降低其有效性,并在使用时向安全团队发出警报。
1. 监控 SetThreadContext 函数使用情况
第一种缓解方法是监视 SetThreadContext 函数的使用情况。该函数经常被滥用于恶意目的。通过检查上下文,安全团队可以确定攻击者是否将地址放在调试地址寄存器 (DR0-DR3) 之一内。任何写入这些寄存器的意外数据都是被入侵的强烈指标。当与新 DLL 实例或其他指标的证据相结合时,此活动可以促使反恶意软件解决方案采取行动。
2. 跟踪可疑的调试函数和寄存器
另一种方法是监控调试功能以检测恶意活动的迹象。当这些功能运行时,EDR 解决方案应主动检查 DR0-DR3 寄存器是否存在可疑行为。如果发现此类活动,则表明存在潜在威胁。
3. 调整 EDR 设置以实现更好的检测
尽管 Blindside 可以在默认设置下绕过 EDR 平台,但调整协议和配置文件可以使这些工具更有效地监控 DR0-DR3 寄存器。如果这些寄存器中的任何一个包含可疑地址,则表明某个进程可能正在尝试挂载到它们。
EDR 技术可以将这些操作与其他恶意活动关联起来,例如尝试创建未挂钩的 DLL。通过适当的设置和配置,EDR 可以阻止攻击并在攻击升级之前终止违规进程。
结论
在研究该技术的可行性时,Cymulate 进攻研究小组验证了该技术对市面上多种 EDR 和 XDR 平台的有效性。该实验的结果是,许多(但不是全部)EDR/XDR 系统都可以使用 Blindside 绕过。
由于保密要求,Cymulate 不会透露哪些 EDR/XDR 工具存在漏洞,哪些不存在漏洞,但已通知接受测试的供应商。此外,在公布该技术细节之前,Cymulate 提交了一份 Microsoft 安全响应中心报告,让 Microsoft 了解 Blindside 技术。截至本文发表时,Microsoft 拒绝发表评论。
Cymulate 进攻研究小组希望,针对当前版本的 Windows(桌面版和服务器)和多个 EDR/XDR 产品确定 Blindside 技术的可行性和有效性,这将导致将来重新审视硬件断点处理。
参考
https://www.intel.com/content/dam/support/us/en/documents/processors/pentium4/sb/253669.pdf
https://ling.re/hardware-breakpoints/
https://github.com/rad9800/TamperingSyscalls
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里