From c65d8661e3a2b80524daa0256ecc504590dba056 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Tue, 8 Sep 2026 21:13:52 +0200 Subject: [PATCH 1/2] Track and expose Module Overloading evasion techniques --- hook_process.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 7 deletions(-) diff --git a/hook_process.c b/hook_process.c index eb2600f4..548aa7ec 100644 --- a/hook_process.c +++ b/hook_process.c @@ -791,7 +791,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtCreateSection, path_from_handle(FileHandle, FileName, UNICODE_STRING_MAX_BYTES); - LOQ_ntstatus("process", "PhopF", "SectionHandle", SectionHandle, "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes ? ObjectAttributes->ObjectName : NULL, "FileHandle", FileHandle, "FileName", FileName); + LOQ_ntstatus("process", "PhopiipF", "SectionHandle", SectionHandle, "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes ? ObjectAttributes->ObjectName : NULL, "SectionPageProtection", SectionPageProtection, "AllocationAttributes", AllocationAttributes, "FileHandle", FileHandle, "FileName", FileName); if (NT_SUCCESS(ret) && FileHandle && (DesiredAccess & SECTION_MAP_WRITE)) file_write(FileHandle); @@ -844,13 +844,36 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSection, NTSTATUS ret = Old_NtMapViewOfSection(SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, Win32Protect); DWORD pid = pid_from_process_handle(ProcessHandle); - UNICODE_STRING *module_name = get_module_name((ULONG_PTR)*BaseAddress); + UNICODE_STRING *module_name = NULL; + UNICODE_STRING dynamic_module_name; + wchar_t *filepath = NULL; + wchar_t *absolutepath = NULL; + + if (NT_SUCCESS(ret) && BaseAddress && *BaseAddress) { + module_name = get_module_name((ULONG_PTR)*BaseAddress); + if (!module_name) { + filepath = malloc(MAX_PATH * sizeof(wchar_t)); + if (filepath) { + if (GetMappedFileNameW(GetCurrentProcess(), *BaseAddress, filepath, MAX_PATH)) { + absolutepath = malloc(32768 * sizeof(wchar_t)); + if (absolutepath) { + ensure_absolute_unicode_path(absolutepath, filepath); + wchar_t *basename = get_dll_basename(absolutepath); + dynamic_module_name.Buffer = basename; + dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } + } + } + } + } if (!module_name) LOQ_ntstatus("process", "ppPpPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, "SectionOffset", SectionOffset, "ViewSize", ViewSize, "Win32Protect", Win32Protect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); else - LOQ_ntstatus("process", "ppPspPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + LOQ_ntstatus("process", "ppPopPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, "ModuleName", module_name, "SectionOffset", SectionOffset, "ViewSize", ViewSize, "Win32Protect", Win32Protect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); if (NT_SUCCESS(ret)) { @@ -864,6 +887,9 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSection, prevent_module_reloading(BaseAddress); } + if (filepath) free(filepath); + if (absolutepath) free(absolutepath); + return ret; } @@ -882,8 +908,37 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSectionEx, AllocationType, Win32Protect, Parameters, ParameterCount); DWORD pid = pid_from_process_handle(ProcessHandle); - LOQ_ntstatus("process", "ppPpPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, - "SectionOffset", SectionOffset, "ViewSize", ViewSize, "Win32Protect", Win32Protect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); + UNICODE_STRING *module_name = NULL; + UNICODE_STRING dynamic_module_name; + wchar_t *filepath = NULL; + wchar_t *absolutepath = NULL; + + if (NT_SUCCESS(ret) && BaseAddress && *BaseAddress) { + module_name = get_module_name((ULONG_PTR)*BaseAddress); + if (!module_name) { + filepath = malloc(MAX_PATH * sizeof(wchar_t)); + if (filepath) { + if (GetMappedFileNameW(GetCurrentProcess(), *BaseAddress, filepath, MAX_PATH)) { + absolutepath = malloc(32768 * sizeof(wchar_t)); + if (absolutepath) { + ensure_absolute_unicode_path(absolutepath, filepath); + wchar_t *basename = get_dll_basename(absolutepath); + dynamic_module_name.Buffer = basename; + dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } + } + } + } + } + + if (!module_name) + LOQ_ntstatus("process", "ppPpPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "SectionOffset", SectionOffset, "ViewSize", ViewSize, "Win32Protect", Win32Protect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); + else + LOQ_ntstatus("process", "ppPopPhs", "SectionHandle", SectionHandle,"ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "ModuleName", module_name, "SectionOffset", SectionOffset, "ViewSize", ViewSize, "Win32Protect", Win32Protect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); if (NT_SUCCESS(ret)) { if (g_config.injection) @@ -896,6 +951,10 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSectionEx, prevent_module_reloading(BaseAddress); } } + + if (filepath) free(filepath); + if (absolutepath) free(absolutepath); + return ret; } @@ -1242,8 +1301,29 @@ HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, MEMORY_BASIC_INFORMATION meminfo; DWORD OriginalNewAccessProtection = 0; UNICODE_STRING *module_name = NULL; - if (BaseAddress) + UNICODE_STRING dynamic_module_name; + wchar_t *filepath = NULL; + wchar_t *absolutepath = NULL; + + if (BaseAddress && *BaseAddress) { module_name = get_module_name((ULONG_PTR)*BaseAddress); + if (!module_name) { + filepath = malloc(MAX_PATH * sizeof(wchar_t)); + if (filepath) { + if (GetMappedFileNameW(GetCurrentProcess(), *BaseAddress, filepath, MAX_PATH)) { + absolutepath = malloc(32768 * sizeof(wchar_t)); + if (absolutepath) { + ensure_absolute_unicode_path(absolutepath, filepath); + wchar_t *basename = get_dll_basename(absolutepath); + dynamic_module_name.Buffer = basename; + dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } + } + } + } + } if (module_name && g_config.ntdll_protect || g_config.hook_protect) { if (NewAccessProtection == PAGE_EXECUTE_READWRITE && BaseAddress && NumberOfBytesToProtect && @@ -1309,6 +1389,9 @@ HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, "NumberOfBytesProtected", NumberOfBytesToProtect, "MemoryType", meminfo.Type, "NewAccessProtection", NewAccessProtection, "OldAccessProtection", OldAccessProtection, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); + if (filepath) free(filepath); + if (absolutepath) free(absolutepath); + return ret; } @@ -1322,7 +1405,30 @@ HOOKDEF(BOOL, WINAPI, VirtualProtectEx, BOOL ret; MEMORY_BASIC_INFORMATION meminfo; DWORD OriginalNewProtect = 0; - UNICODE_STRING *module_name = get_module_name((ULONG_PTR)lpAddress); + UNICODE_STRING *module_name = NULL; + UNICODE_STRING dynamic_module_name; + wchar_t *filepath = NULL; + wchar_t *absolutepath = NULL; + + if (lpAddress) { + module_name = get_module_name((ULONG_PTR)lpAddress); + if (!module_name) { + filepath = malloc(MAX_PATH * sizeof(wchar_t)); + if (filepath) { + if (GetMappedFileNameW(GetCurrentProcess(), lpAddress, filepath, MAX_PATH)) { + absolutepath = malloc(32768 * sizeof(wchar_t)); + if (absolutepath) { + ensure_absolute_unicode_path(absolutepath, filepath); + wchar_t *basename = get_dll_basename(absolutepath); + dynamic_module_name.Buffer = basename; + dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } + } + } + } + } if (module_name && g_config.ntdll_protect || g_config.hook_protect) { if (flNewProtect == PAGE_EXECUTE_READWRITE && lpAddress && dwSize && @@ -1386,6 +1492,9 @@ HOOKDEF(BOOL, WINAPI, VirtualProtectEx, LOQ_bool("process", "ppphhHs", "ProcessHandle", hProcess, "Address", lpAddress, "Size", dwSize, "MemType", meminfo.Type, "Protection", flNewProtect, "OldProtection", lpflOldProtect, "StackPivoted", is_stack_pivoted() ? "yes" : "no"); + if (filepath) free(filepath); + if (absolutepath) free(absolutepath); + return ret; } From 30d2c2651b392b7438faaba208038fa9be9cc036 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Tue, 8 Sep 2026 21:23:09 +0200 Subject: [PATCH 2/2] Fix use-after-free, NULL check, and format string issues in module overloading detection ## Issues Fixed 1. **Use-After-Free in Dynamic Module Name Resolution** - Fixed memory management bug where `dynamic_module_name.Buffer` pointed directly into freed `absolutepath` memory in: - NtMapViewOfSection - NtMapViewOfSectionEx - NtProtectVirtualMemory - VirtualProtectEx - Solution: Use stack-allocated basename_buffer instead of pointing into freed heap memory. Buffer now stays valid through logging calls. 2. **Missing NULL Check for get_dll_basename()** - Added NULL check before using basename to prevent potential crashes or invalid logging in all four functions. 3. **Format String Mismatch in NtCreateSection** - Fixed format string from "PhopiipF" (8 characters) to "PhopipF" (7 characters) - Was causing logging macro to misinterpret parameters when accessing FileHandle and FileName fields. 4. **Improved Memory Safety** - basename_buffer properly null-terminated with bounds checking - Prevents buffer overruns and use-after-free scenarios The fixes ensure module names are captured safely during module overloading detection without risk of memory corruption or crashes. --- hook_process.c | 54 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/hook_process.c b/hook_process.c index 548aa7ec..a8b70946 100644 --- a/hook_process.c +++ b/hook_process.c @@ -791,7 +791,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtCreateSection, path_from_handle(FileHandle, FileName, UNICODE_STRING_MAX_BYTES); - LOQ_ntstatus("process", "PhopiipF", "SectionHandle", SectionHandle, "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes ? ObjectAttributes->ObjectName : NULL, "SectionPageProtection", SectionPageProtection, "AllocationAttributes", AllocationAttributes, "FileHandle", FileHandle, "FileName", FileName); + LOQ_ntstatus("process", "PhopipF", "SectionHandle", SectionHandle, "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes ? ObjectAttributes->ObjectName : NULL, "SectionPageProtection", SectionPageProtection, "AllocationAttributes", AllocationAttributes, "FileHandle", FileHandle, "FileName", FileName); if (NT_SUCCESS(ret) && FileHandle && (DesiredAccess & SECTION_MAP_WRITE)) file_write(FileHandle); @@ -846,6 +846,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSection, DWORD pid = pid_from_process_handle(ProcessHandle); UNICODE_STRING *module_name = NULL; UNICODE_STRING dynamic_module_name; + wchar_t basename_buffer[MAX_PATH]; wchar_t *filepath = NULL; wchar_t *absolutepath = NULL; @@ -859,10 +860,14 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSection, if (absolutepath) { ensure_absolute_unicode_path(absolutepath, filepath); wchar_t *basename = get_dll_basename(absolutepath); - dynamic_module_name.Buffer = basename; - dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); - dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); - module_name = &dynamic_module_name; + if (basename) { + wcsncpy(basename_buffer, basename, MAX_PATH - 1); + basename_buffer[MAX_PATH - 1] = L'\0'; + dynamic_module_name.Buffer = basename_buffer; + dynamic_module_name.Length = wcslen(basename_buffer) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } } } } @@ -910,6 +915,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSectionEx, UNICODE_STRING *module_name = NULL; UNICODE_STRING dynamic_module_name; + wchar_t basename_buffer[MAX_PATH]; wchar_t *filepath = NULL; wchar_t *absolutepath = NULL; @@ -923,10 +929,14 @@ HOOKDEF(NTSTATUS, WINAPI, NtMapViewOfSectionEx, if (absolutepath) { ensure_absolute_unicode_path(absolutepath, filepath); wchar_t *basename = get_dll_basename(absolutepath); - dynamic_module_name.Buffer = basename; - dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); - dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); - module_name = &dynamic_module_name; + if (basename) { + wcsncpy(basename_buffer, basename, MAX_PATH - 1); + basename_buffer[MAX_PATH - 1] = L'\0'; + dynamic_module_name.Buffer = basename_buffer; + dynamic_module_name.Length = wcslen(basename_buffer) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } } } } @@ -1302,6 +1312,7 @@ HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, DWORD OriginalNewAccessProtection = 0; UNICODE_STRING *module_name = NULL; UNICODE_STRING dynamic_module_name; + wchar_t basename_buffer[MAX_PATH]; wchar_t *filepath = NULL; wchar_t *absolutepath = NULL; @@ -1315,10 +1326,14 @@ HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, if (absolutepath) { ensure_absolute_unicode_path(absolutepath, filepath); wchar_t *basename = get_dll_basename(absolutepath); - dynamic_module_name.Buffer = basename; - dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); - dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); - module_name = &dynamic_module_name; + if (basename) { + wcsncpy(basename_buffer, basename, MAX_PATH - 1); + basename_buffer[MAX_PATH - 1] = L'\0'; + dynamic_module_name.Buffer = basename_buffer; + dynamic_module_name.Length = wcslen(basename_buffer) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } } } } @@ -1407,6 +1422,7 @@ HOOKDEF(BOOL, WINAPI, VirtualProtectEx, DWORD OriginalNewProtect = 0; UNICODE_STRING *module_name = NULL; UNICODE_STRING dynamic_module_name; + wchar_t basename_buffer[MAX_PATH]; wchar_t *filepath = NULL; wchar_t *absolutepath = NULL; @@ -1420,10 +1436,14 @@ HOOKDEF(BOOL, WINAPI, VirtualProtectEx, if (absolutepath) { ensure_absolute_unicode_path(absolutepath, filepath); wchar_t *basename = get_dll_basename(absolutepath); - dynamic_module_name.Buffer = basename; - dynamic_module_name.Length = wcslen(basename) * sizeof(wchar_t); - dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); - module_name = &dynamic_module_name; + if (basename) { + wcsncpy(basename_buffer, basename, MAX_PATH - 1); + basename_buffer[MAX_PATH - 1] = L'\0'; + dynamic_module_name.Buffer = basename_buffer; + dynamic_module_name.Length = wcslen(basename_buffer) * sizeof(wchar_t); + dynamic_module_name.MaximumLength = dynamic_module_name.Length + sizeof(wchar_t); + module_name = &dynamic_module_name; + } } } }