2021-8-20 11:20 上传
既然 syscalls 已恢复到放置 EDR 的挂钩之前设置的值,则可以继续执行,而 syscalls 上没有任何挂钩。EDR 的 Dll 仍然存在,但它不会从钩子接收任何遥测数据,因为它们不再存在。EDR 不知道它的钩子不再存在,因为通常没有执行完整性检查来确保它们仍然处于活动状态。
登录/注册后可看大图
Figure 14 Before Reloading Occurs Hooks Still in place_0.png (147.74 KB, 下载次数: 0)
下载附件
2021-8-20 11:20 上传
登录/注册后可看大图
Figure 15 After Reloading Hooks are Gone_0.png (215.45 KB, 下载次数: 0)
下载附件
2021-8-20 11:21 上传
这种 unhooking 方法非常有效,但是,更改内存区域的权限仍然会被检测,例如识别对 VirtualProtect 函数的调用。当 unhooking 攻击成功时,监控控制可以指示此攻击的存在。这可以通过使用其他技术覆盖内存部分来克服,绕过调用任何 Windows 函数来更改这些不可写内存区域的权限的需要。通过使用低级操作系统语言,我们可以在不修改执行、读取 (ER-) 权限的情况下覆盖和恢复系统函数的集合。
另一种技术涉及使用我们自己的程序集系统调用而不是依赖操作系统。这是避免触发 EDR 钩子的有效方法,因为 EDR 只 hook 它知道的内容,在这种情况下,它只知道系统 Dll 中存在的内容。这意味着我们可以通过创建我们自己的函数调用来设置寄存器以及我们自己的系统调用来避免检测到应用程序的内存部分,而不是在加载的系统 Dll 中。为此,我们需要包含设置的汇编代码,使用正确的值设置变量和寄存器并执行我们的 syscalls。这些汇编指令将包含在一个独立的汇编文件中,该文件将在我们编译 Payload 时加载到我们的代码中。系统调用值是动态的很重要,因为特定的系统调用 ID 值会根据 Windows 体系结构而变化。不同版本的 Windows 具有不同的系统调用,具体取决于操作系统,例如:
Windows Version Syscall Number
Windows 10 / Server 2016 0x18
Windows 8.1 / Server 2012 R2 0x17
如果你对此很感兴趣,并在开发自已的 syscalls 时,j00ru 的 Windows-Syscall 或许能给你提供更多帮助。大多数情况下代码看起来像下面这样:
登录/注册后可看大图
SourceZero_Red-Evolution-of-Detection-and-Response_Blog-Pt-1_Figure15_800x346-100_0.jpg (21.46 KB, 下载次数: 0)
下载附件
2021-8-20 11:23 上传
我们需要包含的下一段代码是我们自己版本的 WinAPI 函数,用于在我们的 syscalls 执行之前将寄存器与正确的值对齐,这是由于 syscalls 的低级特性。这些函数通常位于 kernelbase.dll 或 kernel32.dll 中。我们继续以 NTAllocateVirtualMemory 为例。
kernel_entry NTSYSCALLAPI NTSTATUS NtAllocateVirtualMemory(
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect