Worried about EDR hooking catching you out?

This post and subsequent code snippets will help you quickly assess whether EDR is loaded into your process (without a debugger) and performing user-level hooking on important functions that you may wish to use, e.g. process migration using ZwOpenProcess and ZwCreateThreadEx.

When red teaming in a new environment we always need to perform situation awareness. Usually for us once we’ve done all the safety checks we want to know more about the system and current defences in place so we don’t trip over the barb wire and set off all the alarms in the first migration command or persistence mechanism. A great tool written by @PwnDexter already does some amazing initial checks for EDR existence and worth having in your armoury if you dont already.

However, once we know we have EDR in our midst, we then want to know if some of the common migration methods will get caught if we don’t know already know by previous experience or other research we have done. When doing research I would open up a debugger and check the API calls to see if there is a jmp rather than a SysCall like below and thats usually an indication its being hooked by another DLL.

The biggest problem with this is when on target we don’t have the luxury of whipping out a debugger as the user would get pretty suspicious so we want to do this in the background to achieve the same quick results and the main reason I wrote a simple gist to check the memory location of a given API call and provide their assembly instructions at that memory location by reading memory.

You can then take the output from the ASM section above and convert this into assembly instructions which you can use to check against the actual SysCall that should be happening for that function.

Here is a little list of typical functions we look for when checking for user-land hooking but there maybe loads more you may want to look for:

  • NtAllocateVirtualMemory
  • ZwOpenProcess
  • NtCreateProcessEx
  • VirtualAllocEx
  • NtWriteVirtualMemory
  • ZwCreateThreadEx
  • NtCreateThreadEx
  • NtReadVirtualMemory
  • ZwAllocateVirtualMemory
  • ZwCreateUserProcess
  • ZwCreateProcess
  • ZwCreateUserProcess
  • ZwCreateProcess
  • NtFreeVirtualMemory
  • NtProtectVirtualMemory
  • ZwQueueApcThread
  • NtQueueApcThreadEx

There are loads of ways to unhook different SysCalls or make use of SysCalls directly, but i’ll leave that up to the reader to go beyond this POC. Its definitely worth reading this post from Jackson_T which can make SysCalls direct so you don’t have to worry about user-land hooking.

Published by benpturner

Red Teamer (CCSAS|CCSAM) | Creator of PoshC2 | Powershell / C# Enthusiast | Passionate about Security!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s