### Detect Dedicated Thread in LoadLibrary Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Detects new threads starting with their base address pointing to LoadLibrary functions in kernel32.dll or kernelbase.dll. This suggests DLL injection. Requires process and thread information. ```cpp // Detection logic in Detectors::DedicatedThread::Check std::string baseModule; Helpers::ModuleNameFromAddress(hProcess, (PVOID)baseAddr, baseModule); // Get addresses of LoadLibrary functions for comparison PVOID pLoadLibraryA = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); PVOID pLoadLibraryW = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); PVOID pLoadLibraryExA = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryExA"); PVOID pLoadLibraryExW = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryExW"); // Alert if thread starts in kernel32/kernelbase if (!_stricmp(baseModule.c_str(), "kernel32.dll") || !_stricmp(baseModule.c_str(), "kernelbase.dll")) { wprintf(L"! Process %S (%d) abnormally started a new thread in %S\n", processName.c_str(), dwPid, baseModule.c_str()); // Extra alert if thread points directly to LoadLibrary if (baseAddr == pLoadLibraryA || baseAddr == pLoadLibraryW || baseAddr == pLoadLibraryExA || baseAddr == pLoadLibraryExW) { wprintf(L"\t !! Thread is abnormally started in a LoadLibrary function :o\n"); } } // Example output: // ! Process victim.exe (7890) abnormally started a new thread in kernel32.dll // !! Thread is abnormally started in a LoadLibrary function :o ``` -------------------------------- ### Hunt-Weird-ImageLoads Command Line Options Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Use command-line arguments to enable specific detectors for monitoring suspicious ImageLoad and ThreadStart events. Multiple detectors can be combined. ```bash # Display help and available options Hunt-Weird-ImageLoads.exe ``` ```bash # Enable all detection capabilities Hunt-Weird-ImageLoads.exe --all ``` ```bash # Enable specific detectors Hunt-Weird-ImageLoads.exe --rx # Detect private RX (Read-Execute) memory regions in callstack ``` ```bash Hunt-Weird-ImageLoads.exe --rwx # Detect private RWX (Read-Write-Execute) memory regions ``` ```bash Hunt-Weird-ImageLoads.exe --stomped # Detect stomped/modified modules in callstack ``` ```bash Hunt-Weird-ImageLoads.exe --proxy # Detect module proxying via ntdll -> kernel32!LoadLibrary ``` ```bash Hunt-Weird-ImageLoads.exe --dedicatedthread # Detect threads starting at LoadLibrary functions ``` ```bash # Combine multiple detectors Hunt-Weird-ImageLoads.exe --proxy --dedicatedthread --rwx ``` -------------------------------- ### Configure ETW Trace for Process Events Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Sets up an ETW trace using krabsetw to monitor ImageLoad and ThreadStart events from the Microsoft-Windows-Kernel-Process provider. Requires krabsetw library. ```cpp // Setting up the ETW trace with stack trace capture krabs::user_trace userTrace(L"Hunt-Weird-Imageloads"); krabs::provider<>* providerProcess = new krabs::provider<>(L"Microsoft-Windows-Kernel-Process"); // Enable thread and image load keywords providerProcess->any(0x20 | 0x40); // WINEVENT_KEYWORD_THREAD | WINEVENT_KEYWORD_IMAGE // Critical: Enable stack trace capture for each event providerProcess->trace_flags(providerProcess->trace_flags() | EVENT_ENABLE_PROPERTY_STACK_TRACE); // Set up event filters with callbacks krabs::event_filter* imageLoad = new krabs::event_filter(krabs::predicates::id_is(5)); // ImageLoad krabs::event_filter* threadStart = new krabs::event_filter(krabs::predicates::id_is(3)); // ThreadStart imageLoad->add_on_event_callback(OnImageLoad); threadStart->add_on_event_callback(OnThreadStart); providerProcess->add_filter(*imageLoad); providerProcess->add_filter(*threadStart); userTrace.enable(*providerProcess); userTrace.start(); // Begin monitoring ``` -------------------------------- ### LoadLibrary via Dedicated Thread Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt This C code creates a dedicated thread with LoadLibrary as the entry point for DLL loading. It waits for the thread to complete before returning the module handle. This technique is considered quite abnormal. ```c // NewThreadLoadLibrary - Dedicated Thread for DLL Loading // This technique creates a thread with LoadLibrary as the entry point HMODULE MyLoadLibrary(PCSTR mName) { HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, (LPVOID)mName, 0, NULL); WaitForSingleObject(hThread, INFINITE); return GetModuleHandleA(mName); } ``` -------------------------------- ### Command-line Arguments for Alerts Source: https://github.com/theflink/hunt-weird-imageloads/blob/main/Readme.md These arguments control which types of alerts are activated. Use '--all' to enable all alerts. ```bash --all activates all alerts --rx alerts on private rx regions in callstack --rwx alerts on private rwx regions in callstack --stomped alerts on stomped modules in callstack --proxy alerts on abnormal calls to kernel32!loadlibrary from ntdll --dedicatedthread alerts on thread with baseaddr on loadlibrary* ``` -------------------------------- ### Detect Module Proxying with LoadLibrary Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Identifies when LoadLibrary is called indirectly through ntdll.dll, indicating a potential module proxying technique. Requires call stack analysis. ```cpp // Detection logic in Detectors::ModuleProxying::Check for (auto it = stack.begin(); it != stack.end(); ++it) { std::string symbol; Helpers::SymbolNameFromAddress(hProcess, (PVOID)*it, symbol); // Find LoadLibrary in the callstack if (symbol.find("LoadLibrary") != std::string::npos) { std::string callingModule; Helpers::ModuleNameFromAddress(hProcess, (PVOID)*(it + 1), callingModule); // IOC: LoadLibrary was called directly from ntdll (proxied call) if (!_stricmp(callingModule.c_str(), "ntdll.dll")) { wprintf(L"! Process %S (%d) loaded %s by proxying loadlibrary through ntdll\n", processName.c_str(), dwPid, imageName.c_str()); } } } // Example output: // ! Process evasive.exe (3456) loaded wininet.dll by proxying loadlibrary through ntdll ``` -------------------------------- ### Proxy LoadLibrary via RtlQueueWorkItem Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt This C code proxies LoadLibrary through ntdll to hide the caller. It queues LoadLibraryA to be called from ntdll's thread pool. Ensure ntdll.dll is accessible. ```c // WorkItemLoadLibrary - Module Proxying via RtlQueueWorkItem // This technique proxies LoadLibrary through ntdll to hide the caller typedef NTSTATUS (NTAPI* RtlQueueWorkItem)(PVOID, PVOID, ULONG); HMODULE MyLoadLibrary(PCSTR mName) { RtlQueueWorkItem _RtlQueueWorkItem = (RtlQueueWorkItem) GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlQueueWorkItem"); // Queue LoadLibraryA to be called from ntdll's thread pool _RtlQueueWorkItem (LoadLibraryA, (PVOID)mName, WT_EXECUTEDEFAULT); Sleep(1000); // Wait for load to complete return GetModuleHandleA(mName); } ``` -------------------------------- ### PrivateRWX Detector Logic Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Detects private memory pages with Read-Write-Execute protection in the call stack during DLL load. RWX memory is uncommon in legitimate applications. ```cpp // Detection logic in Detectors::PrivateRWX::Check MEMORY_BASIC_INFORMATION mbi = { 0 }; VirtualQueryEx(hProcess, (LPCVOID)pAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // Alert if memory is private and has RWX permissions if (mbi.Type == MEM_PRIVATE && mbi.Protect == PAGE_EXECUTE_READWRITE) { wprintf(L"! Process %S (%d) loaded %s and callstack contains RWX Page: 0x%p\n", processName.c_str(), dwPid, imageName.c_str(), (PVOID)pAddr); } // Example output: // ! Process suspicious.exe (5678) loaded payload.dll and callstack contains RWX Page: 0x00007FF800001000 ``` -------------------------------- ### PrivateRX Detector Logic Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Detects private memory pages with Read-Execute protection in the call stack during DLL load. This can indicate shellcode execution or code injection. ```cpp // Detection logic in Detectors::PrivateRX::Check // For each address in the call stack: MEMORY_BASIC_INFORMATION mbi = { 0 }; VirtualQueryEx(hProcess, (LPCVOID)pAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // Alert if memory is private (not mapped from a file) and executable if (mbi.Type == MEM_PRIVATE && mbi.Protect == PAGE_EXECUTE_READ) { // IOC: Private RX page found in callstack during DLL load wprintf(L"! Process %S (%d) loaded %s and callstack contains RX Page: 0x%p\n", processName.c_str(), dwPid, imageName.c_str(), (PVOID)pAddr); } // Example output: // ! Process malware.exe (1234) loaded evil.dll and callstack contains RX Page: 0x00007FF812340000 ``` -------------------------------- ### ModuleStomped Detector Logic Source: https://context7.com/theflink/hunt-weird-imageloads/llms.txt Detects modified DLLs in the call stack by checking if image-backed memory pages are no longer shared. This indicates module stomping. ```cpp // Detection logic in Detectors::ModuleStomped::Check // Uses Helpers::IsModuleStomped to check each callstack address BOOL IsModuleStomped(HANDLE hProcess, PVOID pAddr) { MEMORY_BASIC_INFORMATION mbi = { 0 }; PSAPI_WORKING_SET_EX_INFORMATION workingSets = { 0 }; VirtualQueryEx(hProcess, (LPCVOID)pAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // Only check image-backed memory (loaded DLLs) if (mbi.Type != MEM_IMAGE || mbi.AllocationProtect == PAGE_NOACCESS) return FALSE; workingSets.VirtualAddress = mbi.BaseAddress; K32QueryWorkingSetEx(hProcess, &workingSets, sizeof(PSAPI_WORKING_SET_EX_INFORMATION)); // If page is not shared, the module has been modified (stomped) return (workingSets.VirtualAttributes.Shared == 0); } // Example output: // ! Process injected.exe (9012) loaded target.dll and callstack contains stomped module: ntdll.dll ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.