Delay load libraries to mitigate WoW64 dependency - #202
Conversation
|
Here is the exact technical breakdown and why their idea is the perfect final piece to the puzzle: 1. The Impact of Delay-Loading on HooksBecause we added Capemon's hooking engine uses 2. The Solution: Conditionally Force-Loading in DllMainBy manually calling
// Note: In capemon.c, the variable is currently called "is_64bit_os"
// but it is populated directly by IsWow64Process.
// - In a Native x64 process: is_64bit_os == FALSE
// - In a WoW64 process (Heavens Gate): is_64bit_os == TRUE
if (!is_64bit_os) {
// We are in a FULL native 64-bit process.
// Eagerly load the delayed DLLs so set_hooks() catches them immediately.
LoadLibraryW(L"advapi32.dll");
LoadLibraryW(L"user32.dll");
LoadLibraryW(L"ws2_32.dll");
LoadLibraryW(L"crypt32.dll");
LoadLibraryW(L"shlwapi.dll");
LoadLibraryW(L"ole32.dll");
LoadLibraryW(L"shell32.dll");
LoadLibraryW(L"setupapi.dll");
LoadLibraryW(L"oleaut32.dll");
LoadLibraryW(L"netapi32.dll");
LoadLibraryW(L"bcrypt.dll");
} else {
// We are in WoW64 mode using Heavens Gate!
// Do nothing. Leave them delay-loaded so we don't crash the early
// loader thread. When the WoW64 process loads them later, Capemon's
// DllLoadNotification callback will catch them and hook them safely.
}
// Proceed to call set_hooks();3. Safety Check: Loader LockUsually, calling |
… 64bit processes prior to hooking
…l dll range mapping
…ain loader-lock during execution injection
|
The reason By adding the The Dependency Initialization Race:Because we delay-loaded The Solution: Deferred Initialization vs Pure NTAPIWe had two options to fix this: rewrite the setup algorithms to exclusively utilize raw We removed the hazardous
This guarantees NO non-native loader lock subsystems ever trigger inside the remote thread context, ensuring perfectly stable delay-load transitions. |
The reason
capemon_x64.dllwas failing (while the stripped downcapemin_x64.dllsucceeded via HeavensGate.h) is because the full Capemon depends heavily on higher-level libraries likeadvapi32.dll,ws2_32.dll,crypt32.dll,shlwapi.dll,ole32.dll,shell32.dll,setupapi.dll,oleaut32.dll,netapi32.dll, andbcrypt.dll. In the early process initialization phase (CREATE_SUSPENDED), the Windows loader will refuse to loadcapemon_x64.dllbecause it cannot resolve those specific imports, causing a silent crash or load failure.By adding the
<DelayLoadDLLs>configuration anddelayimp.libstrictly to the x64 Native configurations, we successfully deferred the resolution of those external modules. Because they are mapped as Delay-Loaded, the Windows image loader ignores them entirely whenHeavensGate.hnatively injectscapemon_x64.dll.The Dependency Initialization Race:
Because we delay-loaded
advapi32.dllanduser32.dll, any APIs calling those components (GetUserNameA,ConvertSidToStringSidW) invoke the MSVC delay-loader which attempts toLoadLibraryWinside the current context.Executing
LoadLibraryWinside embryonic injection threads fundamentally crashes because the NT kernel hasn't properly executedLdrpInitializeProcessfor the target processes, halting subsystem bootstrapping (yielding Error0x13d/1114 ERROR_DLL_INIT_FAILED).The Solution: Deferred Initialization
We removed the hazardous
hkcu_init()andlog_init()execution fromcapemon.c'sDllMain. Both routines are safely routed to execute lazily usingInterlockedCompareExchangebarriers:log_init(...)executes seamlessly insidewrite_log_dataexactly when the firstlog_apihook invokes.hkcu_init()executes securely right at the point wheng_hkcu.hkcu_stringis sequentially queried inside thenormalize_registry_pathmapping procedures.This guarantees NO non-native loader lock subsystems ever trigger inside the remote thread context!
Hook Resolution on Delayed Libraries
If these DLLs (like
advapi32.dll) are bypassed duringcapemon's initialization, how are their hooks planted?Because
GetModuleHandle("advapi32.dll")returnsNULLduringset_hooks(), the hook resolution effectively skips it gracefully without causing any crashes.Later, when malware actually executes an imported function, MSVC or the OS evaluates
LoadLibrary. When the DLL boots inside a fully native host, the Windows Loader triggers Capemon's natively implementedLdrRegisterDllNotificationlistener (New_DllLoadNotification()).This flawlessly receives the module load event and invokes
set_hooks_dlldynamically, mapping all active hooks perfectly transparently without requiring strict eager mapping loops insideDllMain!