Best EDR Of The Market

You gotta worry bout’ them malicious processes…
你得担心他们的恶意进程……

TL;DR TL;博士

The Best EDR Of The Market (BEOTM) is an open source EDR designed to serve as a testing ground for understanding and bypassing some of the detection mechanisms employed by many well-known EDRs. These methods focus on the dynamic analysis of a process and its states (memory, call stack, heap, API calls, etc.).
市场最佳 EDR (BEOTM) 是一个开源 EDR,旨在作为了解和绕过许多知名 EDR 采用的一些检测机制的试验场。这些方法侧重于对进程及其状态(内存、调用堆栈、堆、API 调用等)进行动态分析。

The purpose of this article is not to delve too deeply into details of these methods that are fully covered in other articles (which I may not explain any better), but to give a brief overview of how these methods are implemented in BEOTM.
本文的目的不是要深入研究这些方法的细节,这些方法在其他文章中已经完全介绍过(我可能不会更好地解释),而是简要概述这些方法如何在 BEOTM 中实现。


Best EDR Of The Market



DLL Hooking ⚔️ DLL 挂钩 ⚔️

BEOTM performs DLL injection at multiple levels of abstraction, hooking sensitive functions such as those used for memory allocation, process or thread creation/manipulation, changing memory pools access rights, etc. This hooking is achieved by injecting the DLL into the target process.
BEOTM 在多个抽象级别执行 DLL 注入,挂钩敏感函数,例如用于内存分配、进程或线程创建/操作、更改内存池访问权限等的函数。此挂钩是通过将 DLL 注入目标进程来实现的。

Once injected, the DLL will redirect calls from hooked functions to its own internal routines to inspect their content and then decide whether or not to proceed with the call by invoking the original routine.
注入后,DLL 会将调用从挂钩函数重定向到其自己的内部例程,以检查其内容,然后通过调用原始例程来决定是否继续调用。


Obviously, the purpose of implementing this technique in BEOTM is not to analyze the parameters of each function, primarily for performance reasons: BEOTM distinguishes itself from the typical architecture in serving as both an agent and an analyzer/scheduler of responses. In contrast, a typical EDR would send the captured data to an external entity, which would then be responsible for orchestrating the response. On the other hand, it would have been much more resource-intensive to initiate an analysis for each API call made by a targeted program.
显然,在 BEOTM 中实现此技术的目的不是分析每个函数的参数,主要是出于性能原因:BEOTM 与典型架构的区别在于既充当代理又充当响应的分析器/调度器。相比之下,典型的 EDR 会将捕获的数据发送到外部实体,然后由外部实体负责协调响应。另一方面,对目标程序发出的每个 API 调用启动分析会占用更多资源。

Moreover, bypassing this mechanism primarily involves preventing the routines from being intercepted by the injected DLL. Thus, the EDR either limits itself (for now) by showing a message through the standard output (for NTDLL hooks) or by displaying a MessageBox (for Kernelbase/Kernel32 hooks) alerting that the routine has been intercepted.
此外,绕过此机制主要涉及防止例程被注入的 DLL 截获。因此,EDR 要么通过标准输出(对于 NTDLL 挂钩)显示消息,要么通过显示 MessageBox(对于 Kernelbase/Kernel32 挂钩)来限制自身,提醒例程已被截获。

I am currently studying the feasibility of RPC communication between the injected DLL and the EDR as an enhancement.
我目前正在研究注入的 DLL 和 EDR 之间 RPC 通信的可行性,作为增强功能。


NT-Level hooking VS Reflective DLL Loader:
NT 级挂钩 VS 反射 DLL 加载器:


Best EDR Of The Market


Kernel32-Level hooking VS benign process:
Kernel32级挂钩VS良性进程:


Best EDR Of The Market


If you’re wondering why interceptions at the NT level only return a message to the standard output, unlike interceptions at the Kernel32 level, it’s because the NT level is much more sensitive, being very low-level: Displaying a large messagebox could interfere with or corrupt the interception.
如果您想知道为什么 NT 级别的拦截只将消息返回到标准输出,而不像 Kernel32 级别的拦截,这是因为 NT 级别的拦截要敏感得多,非常低级:显示大型消息框可能会干扰或损坏拦截。


Hooked Routines/Functions
挂钩例程/函数

The functions that are hooked by the EDR through the injected DLLs are described in the "TrigerringFunctions.json" file. The release version of BEOTM includes precompiled DLLs, but you can still compile the DLLs from the repo sources with the functions you want to intercept. 🪝
"TrigerringFunctions.json" 文件中描述了 EDR 通过注入的 DLL 挂钩的函数。BEOTM 的发行版包括预编译的 DLL,但你仍然可以使用要截获的函数从存储库源编译 DLL。🪝


BEOTM’s injectable DLLs rely on Microsoft Detours as an interface for API calls interception.
BEOTM 的可注入 DLL 依赖于 Microsoft Detours 作为 API 调用拦截的接口。


Best EDR Of The Market
A deep overview of what happens when NtAllocateVirtualMemory is intercepted by the DLL:
深入概述被 DLL 截获时 NtAllocateVirtualMemory 会发生什么情况:


Best EDR Of The Market



Threads Call Stack Monitoring ⚔️​
线程调用堆栈监控 ⚔️

This method involves the continuous monitoring of the RIP instruction register of each thread. When the RIP register points to the address of an exported routine/function from any DLL or to the address of an area contained in the implementation of this export, and the user has specified in the TrigerringFunctions.json file that they want to monitor this routine/function, the thread is paused, and its call stack is unwound. All parameters of all routines it stacks are analyzed. If a sequence of bytes in a parameter matches a predefined pattern in the YaroRules.json file, the process is stopped, and an alert is issued! 🚨
此方法涉及对每个线程的 RIP 指令寄存器的持续监视。当 RIP 寄存器指向从任何 DLL 导出的例程/函数的地址或此导出的实现中包含的区域的地址,并且用户在 TrigerringFunctions.json 文件中指定了要监视此例程/函数时,线程将暂停,其调用堆栈将展开。分析它堆叠的所有例程的所有参数。如果参数中的字节序列与 YaroRules.json 文件中的预定义模式匹配,则进程将停止,并发出警报!🚨

Unlike DLL hooking & IAT hooking, there is indeed a response with this method: You can specify in the TrigerringFunctions.json file which functions you want to monitor at the thread call stack level and you can define the patterns you want to identify in YaroRules.json.
与DLL挂钩和IAT挂钩不同,这种方法确实有一个响应:您可以在 TrigerringFunctions.json 文件中指定要在线程调用堆栈级别监视的函数,并且可以定义要在 YaroRules.json 中标识的模式。


Threads Call Stack Monitoring VS NT-Level XOR-Encrypted Shellcode Loader :
线程调用堆栈监控 VS NT 级 XOR 加密的 shellcode 加载器:


Best EDR Of The Market


Threads Call Stack Monitoring VS Reflective DLL Loader:
线程调用堆栈监视 VS 反射式 DLL 加载器:


Best EDR Of The Market



Let’s take a look at a low level of what happens, here’s a simple program that allocates a virtual memory pool of 4096 bytes through VirtualAlloc :
让我们看一下发生的低级别情况,这是一个简单的程序,它通过 VirtualAlloc 分配一个 4096 字节的虚拟内存池:

int main() {
    size_t memSize = 4096; // 4 Ko

    LPVOID pMemory = VirtualAlloc(nullptr, memSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    return 0;
}

The values of the four parameters are transmitted to registers r8, r9, rcx and rdx which will be then passed to the stack :
四个参数的值被传输到寄存器 r8、r9、rcx 和 rdx,然后这些寄存器将被传递到堆栈:

KERNELBASE!VirtualAlloc+0x22:
00007ffb`9bdd1402 4183e0c0        and     r8d,0FFFFFFC0h
00007ffb`9bdd1406 44894c2428      mov     dword ptr [rsp+28h],r9d
00007ffb`9bdd140b 4489442420      mov     dword ptr [rsp+20h],r8d
00007ffb`9bdd1410 4c8d4c2448      lea     r9,[rsp+48h]
00007ffb`9bdd1415 4533c0          xor     r8d,r8d
00007ffb`9bdd1418 488d542440      lea     rdx,[rsp+40h]
00007ffb`9bdd141d 498d48ff        lea     rcx,[r8-1]
00007ffb`9bdd1421 48ff1500ea1f00  call    qword ptr [KERNELBASE!_imp_NtAllocateVirtualMemory (00007ffb`9bfcfe28)]
00007ffb`9bdd1428 0f1f440000      nop     dword ptr [rax+rax]
00007ffb`9bdd142d 85c0            test    eax,eax
00007ffb`9bdd142f 780b            js      KERNELBASE!VirtualAlloc+0x5c (00007ffb`9bdd143c)
                        

These same parameters will be passed to the underlying NtAllocateVirtualMemory:
这些相同的参数将被传递给底层 NtAllocateVirtualMemory :


Best EDR Of The Market


If we set a breakpoint at ntdll!NtAllocateVirtualMemory on the shellcode loader, and unroll the call stack when the breakpoint is reached, you’ll see that an address is passed as a parameter to the routine, corresponding to a pointer to the xor-decrypted shellcode.
如果我们在 shellcode 加载器上 ntdll!NtAllocateVirtualMemory 设置了一个断点,并在到达断点时展开调用堆栈,你将看到一个地址作为参数传递给例程,对应于指向 xor 解密的 shellcode 的指针。


Best EDR Of The Market


Here’s a global conditional diagram of how threads call stack monioring works on BEOTM :
下面是线程调用堆栈监控如何在 BEOTM 上工作的全局条件图:


Best EDR Of The Market



Import Address Table (IAT) Hooking ⚔️
导入地址表 (IAT) 挂钩 ⚔️

This method operates at the Import Address Table (IAT) level of the target process by overwriting the addresses of legitimate imports with the addresses of exports from an injected DLL. While it may seem similar to DLL hooking due to the injection of a DLL, it is not the case at all, as this method does not involve a ‘jmp’ instruction to a trampoline function.
此方法在目标进程的导入地址表 (IAT) 级别运行,方法是使用注入的 DLL 中的导出地址覆盖合法导入的地址。虽然由于注入了 DLL,它看起来类似于 DLL 挂钩,但事实并非如此,因为此方法不涉及对蹦床函数的“jmp”指令。


Best EDR Of The Market



A MessageBox is shown for each intercepted function.
每个截获的函数都会显示一个 MessageBox。


IAT-hooking VS Reflective DLL Loader:
IAT-hooking VS 反射式 DLL 加载器:


Best EDR Of The Market


Some might (perhaps) wonder, as I did, how the registers are preserved with this interception method to be later analyzed, even with the addition of a MessageBox or any instruction that could potentially corrupt the register values and distort the parameter values. Well, all it takes is firing up IDA to get the answer: this method does not prevent the preservation and backup of the values of the registers r8, r9, rcx, and rdx into other registers (rbx, rdi, rsi). 👍
有些人可能(也许)像我一样想知道,如何使用这种拦截方法保留寄存器以供以后分析,即使添加了 MessageBox 或任何可能损坏寄存器值并扭曲参数值的指令。好吧,只需启动 IDA 即可获得答案:此方法不会阻止将寄存器 r8、r9、rcx 和 rdx 的值保存和备份到其他寄存器(rbx、rdi、rsi)中。👍


Best EDR Of The Market



SSN Crushing🥊 SSN破碎🥊

Well, that’s one is purely imaginative and not realistic at all, it simply consists in crushing/overriding the value of the Syscall / SSN (System Service Number) at the NT-level with 0x21.
好吧,这是一个纯粹是想象力的,根本不现实,它只是在 NT 级别用0x21粉碎/覆盖 Syscall / SSN(系统服务编号)的值。

This will cause the process to stop working in most cases if you touch important routines, either because the program has detected an integrity error in the ntdll checksum it has loaded into memory or because the syscall has simply been corrupted.
在大多数情况下,如果触摸重要的例程,这将导致进程停止工作,因为程序在已加载到内存中的 ntdll 校验和中检测到完整性错误,或者因为系统调用已损坏。


Best EDR Of The Market


So what’s the point of that ? Simply for making you try, from an attacker point of view, to revert the value of the syscall and override it with its real value that you would have fetched by any mean. 😉
那么这有什么意义呢?只是为了让你尝试,从攻击者的角度来看,恢复系统调用的值,并用你无论如何都会获取的实际值覆盖它。😉


Yaro rules 🔍​ Yaro 规则 🔍

The YaroRules.json file contains nothing more than the patterns you wish to identify. You can have fun searching for interesting patterns common to many shellcodes/payloads, like in this example that identifies patterns related to accessing the PEB and traversing LDR entries for a metasploit-generated reverse TCP shellcode.
YaroRules.json 文件只包含要标识的模式。您可以愉快地搜索许多 shellcode/payload 共有的有趣模式,例如在此示例中,该示例标识了与访问 PEB 和遍历 LDR 条目以获取 metasploit 生成的反向 TCP shellcode 相关的模式。


Best EDR Of The Market



You could also add certain patterns of known malicious artifacts (e.g., Mimikatz). I will probably take a moment to do that as well
您还可以添加已知恶意项目的某些模式(例如,Mimikatz)。我可能也会花点时间做这件事


YaroRules.json contains 5 default patterns corresponding to the pattern of accessing the PEB and PEB_LDR_DATA entries for a reverse_tcp shellcode generated by Metasploit. There are also 3 other patterns corresponding to areas in the DOS header of a PE-format object.
YaroRules.json 包含 5 个默认模式,对应于 Metasploit 生成的 reverse_tcp shellcode 的 PEB 和PEB_LDR_DATA条目的访问模式。还有 3 种其他模式对应于 PE 格式对象的 DOS 标头中的区域。


{
	"Patterns": [
		"d2 65 48 8b 52 60 48 8b 52 18 48 8b 52 20 48 8b 72 50 48",
		"49 be 77 73 32 5f 33 32 00 00",
		"4d 5a",
		"4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
		"00 F0 00 00 00 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 6D 6F 64 65 2E"
	]
}

 

Epilogue 结语

I tried to provide a very quick overview of the techniques implemented in BEOTM without going into details about the bypassing methods for each defense mechanism shown here.
我试图对 BEOTM 中实现的技术进行非常快速的概述,而不详细介绍此处所示的每种防御机制的绕过方法。

I am far from being an expert in EDR evasion or defense mechanisms, but I thought it would be fun and instructive to build my own EDR that implements techniques whose bypassing is within reach for anyone with a basic knowledge of low-level programming and Windows internals. If interested, do not hesitate to delve into the source code of the EDR and take a look at the ways in which the user-mode defensive mechanisms are implemented, particularly with regard to remote processes memory access. 😉🏴‍☠️​
我远不是 EDR 规避或防御机制方面的专家,但我认为构建我自己的 EDR 会很有趣且很有启发性,该 EDR 实现了任何具有低级编程和 Windows 内部基本知识的人都可以绕过的技术。如果有兴趣,请随时深入研究 EDR 的源代码,并了解用户模式防御机制的实现方式,尤其是在远程进程内存访问方面。😉🏴‍☠️​


I’m still learning so if you have a comment or observation on this article, feel free to contact me, my email addresses are on my Github profile 😸
我仍在学习,所以如果您对本文有任何评论或意见,请随时与我联系,我的电子邮件地址在我的 Github 个人资料😸中

原文始发于Yazid’s notes:Best EDR Of The Market

版权声明:admin 发表于 2023年11月21日 下午10:13。
转载请注明:Best EDR Of The Market | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...