Full DLL Unhooking with C++
EDR evasion
Last updated
EDR evasion
Last updated
It's possible to completely unhook any given DLL loaded in memory, by reading the .text section of ntdll.dll from disk and putting it on top of the .text section of the ntdll.dll that is mapped in memory. This may help in evading some EDR solutions that rely on userland API hooking.
The process for unhooking a DLL is as follows. Let's assume that the ntdll.dll is hooked and here is how we could unhook it:
Map a fresh copy of ntdll.dll from disk to process memory
Find virtual address of the .text section of the hooked ntdll.dll
get ntdll.dll base address
module base address + module's .text section VirtualAddress
Find virtual address of the .text section of the freshly mapped ntdll.dll
Get original memory protections of the hooked module's .text section
Copy .text section from the freshly mapped dll to the virtual address (found in step 3) of the original (hooked) ntdll.dll - this is the meat of the unhooking as all hooked bytes get overwritten with fresh ones from the disk
Apply original memory protections to the freshly unhooked .text section of the original ntdll.dll
Below is a simplified graph, illustrating the core concept of the technique, where a hooked .text section of ntdll.dll is replaced with a clean copy of .text section of ntdll.dll from disk:
Below code fully unhooks the ntdll.dll, although it could be modified to unhook any other DLL.
Note that the above code does not fix image base relocations. Although ntdll.dll does not have anything to be relocated within its .text section, it may be required when dealing with other dlls.
Thanks @mrgretzky for highlighting this.
See my notes about PE image relocations: https://ired.team/offensive-security/code-injection-process-injection/process-hollowing-and-pe-image-relocations#relocation