2021-8-20 11:12 上传
二、为什么 EDRs 喜欢在用户模式下 hook
虽然内核模式是最高级访问类型,但它确实存在一些缺点,使 EDR 的有效性变复杂。在内核模式下,可见性非常有限,因为在用户模式下才有几个数据点可用。此外,基于第三方内核的驱动程序通常很难开发,如果不进行适当的审查,可能会导致系统不稳定。内核通常被认为是最脆弱的部分,内核模式代码中的任何出错都将导致问题发生,甚至使系统完全崩溃。
攻击者更青睐于用户模式,在用户模式下是无法直接访问底层硬件。在用户模式下运行的代码必须使用应用程序与硬件交互的 API 函数,从而提高稳定并减少系统级别的崩溃 (因为应用程序崩溃一般不会影响系统)。因此,在用户模式下运行的程序不需要给予太多的权限,这样还稳定。可以说,很多 EDR 产品严重依赖于用户模式下的 Hook 而不是内核模式下的 Hook,这让攻击者很感兴趣。
在用户模式下可以对进程进行下钩子操作,因此可以控制它们。由于应用程序在用户的上下文中运行,这意味着加载到进程中的所有内容都可以由用户以某种方式进行操作。需要注意的是,内存的一些敏感区域设置为 Execute,Read (ER-),可以防止对这些区域进行修改。我们将在下面讨论一些技术来解决这个问题。
三、在内存中绕过 EDRs
在我们寻找内存钩子之前,我们需要识别 EDR 的 Dll,这是缩小范围的关键,因为一个简单的应用程序可以加载许多不同的 Dll,并且它们可以根据进程需要的功能进行更改。例如,任何 Windows 套接字连接都需要 ws2_32.dll。
识别 EDR 的 Dll 就像查看 Dll 的名称或描述一样简单,其他技术可能涉及查找 Dll 的路径或查看 Dll 的代码签名证书。有几个很棒的工具可以做到这一点,但对于我们这个案例,将使用 ProcessHacker2,一个免费的进程监控软件。正如我们所看到的,加载多个 Dll,但其中一个在名称和描述上都很突出,因为名称包含 EDR 产品的名称,而描述表明了其用途。
登录/注册后可看大图
Figure 6 Execution flow of a Procedure EDR Hooked_0.png (244.38 KB, 下载次数: 0)
下载附件
2021-8-20 11:14 上传
现在我们已经确定了 EDR Dll 了,下一步是去搜索这些钩子。为此,我们需要更深入地了解这些系统级函数以及它们如何在堆栈上运行。如果我们使用开源调试器 x64dbg 看一下,可以看到每个 Dll 都有一系列导出函数,这些是应用程序可以利用的功能。
登录/注册后可看大图
Figure 7 Sample Export Functions of Ntdll_0.png (462 KB, 下载次数: 0)
下载附件
2021-8-20 11:15 上传
我们知道 syscalls 是应用程序访问内核执行低级指令的唯一途径。在 x64 体系结构中,每个 syscall 都应以当前存储在 RCX 中的值移至 R10 开始 (mov r10, rcx),然后将一个十六进制值移入 EAX 寄存器中,这个十六进制值是一个系统服务号,对于每个 syscall 都是唯一的。内核不知道实际执行的是什么指令,只是查找唯一的 syscall ID 来确定要执行的相应指令。在此示例中,可以看到典型的 syscall 在程序集中的大致样子。SYSCALL_ID 对于该特殊 syscall 始终是唯一的。
mov r10, rcx
mov eax, (SYSCALL_ID)
test byte ptr ds:[7FFE0308],1
jne ntdll (ADDRESS)
syscall
ret
int 2E