During the development of ZAIUX® Evo we are performing several benchmark tests in order to evaluate the actual level of evasion implemented in the TTPs (Tactics, Techniques and Procedures) executed by our solution.
Unfortunately, we found out that most of EDR/XDR solutions are almost or totally ineffective against modern attack vectors. Only few vendors put in place effective strategies to detect and mitigate malwares or first stage droppers.
According to our experience, based on several Penetration Tests, Sentinel One is one of the best EDR currently available on the market. It puts in place various hooking mechanisms: not only in common libraries but also in the PEB of the process and in few other places. For this reason and for the purpose of this article, we decided to evaluate the ZAIUX® Evo Implant against this security solution.
Most of C2 shellcodes available in commercial and/or open-source solutions rely on resolving KERNEL32.DLL and NTDLL.DLL addresses by parsing the Process Environment Block (PEB).
As we can see in the following screenshots, Sentinel One hooks the PEB by creating two “fake” entries and applies a PAGE_GUARD on the executable sections of the “fake” DLLs.
We can notice the two fake entries of NTDLL (ntd1l.dll) at the base address: 0x1400fa40000, and KERNEL32 (Kern3l32.dll) at the base address: 0x1400f930000 .
The PAGE_GUARD (+G) is applied on the executable section (RX). The RX section is located in the Base Address + an offset of 0x1000:
Since the shellcode needs to resolve the address of NTDLL and/or KERNEL32 in order to perform the next offensive operation, let us examine a typical way of how malware authors achieve this:
Typically, the first two libraries loaded when the process is created are ntdll.dll and kernel32.dll (in this exact order). We can leverage this behaviour, parse the Process Environment Block and walk through the InMemoryOrderModuleList, in order to fetch the desired addresses.
Here is an example of how to retrieve the NTDLL Base Address using Assembly code:
But what happens when the PEB itself is hooked by the EDR? (Like in the context of this lab)
When the shellcode tries to invoke a function coming from this page guarded memory region, an exception will be raised: the exception is then caught by the EDR via Vectored Exception Handler. Afterwards the process is immediately killed by the EDR itself.
How does ZAIUX® Evo defeat this defense mechanism?
Although this mechanism might seem rather advanced, it is not a novel technique, and we can adopt several strategies to bypass it. In this article we will present two POCs which can be leveraged to achieve our goal.
- This is a proof-of-concept C-code to detect and remove the PAGE_GUARD placed by the EDR. After the PAGE_GUARD has been removed, we can resolve the needed functions without worrying about the hooks, since this “fake” libraries are not hooked.
In this example we are going to resolve the Sleep function. After removing the PAGE_GUARD, we can invoke the function located in kern3l32.dll which was originally loaded by the EDR.
- The second solution presented here is to walk through the InMemoryOrderModuleList. But instead of taking the first or second element, we will perform a check on the “BaseDllName” (the name of the loaded module). In order not to be fooled by the entry created by the EDR, it is important to perform the check using a function which supports wide-character strings. If the comparison between our desired module name and the entry in the ModuleList is successful, we can feel safe and get our DllBase.
In this first article we have presented two different options to evade PEB hooks, but there are more effective strategies that we can put in place.
In the next articles we are going to examine other defence mechanisms used by EDR/XDR and see how we can bypass them. ZAIUX® Evo supports different techniques and will apply the more appropriate ones based on each situation. Thanks to these features, ZAIUX® Evo users will be provided with a modern solution in order to evaluate their resilience against modern attack vectors in a real-world scenario.