From f012b2210133edf05ab711978595efdd6942fc4d Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 11 Nov 2025 21:22:00 -0700 Subject: [PATCH] LoadLibraryA: Skip import resolution & DllMain for EXEs --- CMakeLists.txt | 1 + dll/kernel32/libloaderapi.cpp | 10 ++--- dll/kernel32/synchapi.cpp | 14 +++++++ dll/ws2.cpp | 10 +++++ src/loader.cpp | 6 ++- src/modules.cpp | 69 ++++++++++++++++++----------------- src/modules.h | 1 + 7 files changed, 72 insertions(+), 39 deletions(-) create mode 100644 dll/ws2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 43694ae..56297a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ add_executable(wibo dll/user32.cpp dll/vcruntime.cpp dll/version.cpp + dll/ws2.cpp src/access.cpp src/async_io.cpp src/errors.cpp diff --git a/dll/kernel32/libloaderapi.cpp b/dll/kernel32/libloaderapi.cpp index 91bf07b..a1b3ba3 100644 --- a/dll/kernel32/libloaderapi.cpp +++ b/dll/kernel32/libloaderapi.cpp @@ -153,7 +153,7 @@ DWORD WINAPI GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("FindResourceA %p %p %p\n", hModule, lpName, lpType); + DEBUG_LOG("FindResourceA(%p, %s, %s)\n", hModule, lpName, lpType); auto type = wibo::resourceIdentifierFromAnsi(lpType); auto name = wibo::resourceIdentifierFromAnsi(lpName); return findResourceInternal(hModule, type, name, std::nullopt); @@ -161,7 +161,7 @@ HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) { HRSRC WINAPI FindResourceExA(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD wLanguage) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("FindResourceExA %p %p %p %u\n", hModule, lpName, lpType, wLanguage); + DEBUG_LOG("FindResourceExA(%p, %s, %s, %u)\n", hModule, lpName, lpType, wLanguage); auto type = wibo::resourceIdentifierFromAnsi(lpType); auto name = wibo::resourceIdentifierFromAnsi(lpName); return findResourceInternal(hModule, type, name, wLanguage); @@ -169,7 +169,7 @@ HRSRC WINAPI FindResourceExA(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD HRSRC WINAPI FindResourceW(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("FindResourceW %p\n", hModule); + DEBUG_LOG("FindResourceW(%p, %p, %p)\n", hModule, lpName, lpType); auto type = wibo::resourceIdentifierFromWide(lpType); auto name = wibo::resourceIdentifierFromWide(lpName); return findResourceInternal(hModule, type, name, std::nullopt); @@ -177,7 +177,7 @@ HRSRC WINAPI FindResourceW(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) { HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("FindResourceExW %p %u\n", hModule, wLanguage); + DEBUG_LOG("FindResourceExW(%p, %p, %p, %u)\n", hModule, lpName, lpType, wLanguage); auto type = wibo::resourceIdentifierFromWide(lpType); auto name = wibo::resourceIdentifierFromWide(lpName); return findResourceInternal(hModule, type, name, wLanguage); @@ -185,7 +185,7 @@ HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WO HGLOBAL WINAPI LoadResource(HMODULE hModule, HRSRC hResInfo) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("LoadResource %p %p\n", hModule, hResInfo); + DEBUG_LOG("LoadResource(%p, %p)\n", hModule, hResInfo); if (!hResInfo) { setLastError(ERROR_RESOURCE_DATA_NOT_FOUND); return GUEST_NULL; diff --git a/dll/kernel32/synchapi.cpp b/dll/kernel32/synchapi.cpp index a93add7..3769a53 100644 --- a/dll/kernel32/synchapi.cpp +++ b/dll/kernel32/synchapi.cpp @@ -1125,10 +1125,12 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL HOST_CONTEXT_GUARD(); DEBUG_LOG("InitOnceBeginInitialize(%p, %u, %p, %p)\n", lpInitOnce, dwFlags, fPending, lpContext); if (!lpInitOnce) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (dwFlags & ~(INIT_ONCE_CHECK_ONLY | INIT_ONCE_ASYNC)) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1137,6 +1139,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL if (dwFlags & INIT_ONCE_CHECK_ONLY) { if (dwFlags & INIT_ONCE_ASYNC) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1145,6 +1148,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL if (fPending) { *fPending = TRUE; } + DEBUG_LOG("-> ERROR_GEN_FAILURE\n"); setLastError(ERROR_GEN_FAILURE); return FALSE; } @@ -1186,6 +1190,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL } case 1: { // synchronous initialization in progress if (dwFlags & INIT_ONCE_ASYNC) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1222,6 +1227,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL } case 3: { // async pending if (!(dwFlags & INIT_ONCE_ASYNC)) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1240,20 +1246,24 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon HOST_CONTEXT_GUARD(); DEBUG_LOG("InitOnceComplete(%p, %u, %p)\n", lpInitOnce, dwFlags, lpContext); if (!lpInitOnce) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (dwFlags & ~(INIT_ONCE_ASYNC | INIT_ONCE_INIT_FAILED)) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } const bool markFailed = (dwFlags & INIT_ONCE_INIT_FAILED) != 0; if (markFailed) { if (lpContext) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (dwFlags & INIT_ONCE_ASYNC) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1261,6 +1271,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon const GUEST_PTR contextValue = static_cast(reinterpret_cast(lpContext)); if (!markFailed && (contextValue & kInitOnceReservedMask)) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1274,6 +1285,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon case 1: { auto syncState = getInitOnceState(lpInitOnce); if (!syncState) { + DEBUG_LOG("-> ERROR_GEN_FAILURE\n"); setLastError(ERROR_GEN_FAILURE); return FALSE; } @@ -1292,6 +1304,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon } case 3: if (!(dwFlags & INIT_ONCE_ASYNC)) { + DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n"); setLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1300,6 +1313,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon } return TRUE; default: + DEBUG_LOG("-> ERROR_GEN_FAILURE\n"); setLastError(ERROR_GEN_FAILURE); return FALSE; } diff --git a/dll/ws2.cpp b/dll/ws2.cpp new file mode 100644 index 0000000..76cfb8b --- /dev/null +++ b/dll/ws2.cpp @@ -0,0 +1,10 @@ +#include "modules.h" + +extern const wibo::ModuleStub lib_ws2 = { + (const char *[]){ + "WS2_32", + nullptr, + }, + nullptr, + nullptr, +}; diff --git a/src/loader.cpp b/src/loader.cpp index b846706..ea6e69c 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -19,6 +19,8 @@ #include #include +constexpr uint16_t IMAGE_FILE_DLL = 0x2000; + struct PEHeader { uint8_t magic[4]; // "PE\0\0" uint16_t machine; @@ -372,6 +374,7 @@ bool loadPEFromSource(wibo::Executable &executable, const PeInputView &source, b DEBUG_LOG("loadPE: unreasonable section count %u\n", header.numberOfSections); return false; } + executable.isDll = !!(header.characteristics & IMAGE_FILE_DLL); constexpr size_t kOptionalHeaderMinimumSize = offsetof(PE32Header, reserved) + sizeof(PEImageDataDirectory); if (header.sizeOfOptionalHeader < kOptionalHeaderMinimumSize) { @@ -440,9 +443,10 @@ bool loadPEFromSource(wibo::Executable &executable, const PeInputView &source, b initialProtect, MEM_IMAGE); } if (allocStatus != wibo::heap::VmStatus::Success) { - DEBUG_LOG("Image mapping failed (status=%u)\n", static_cast(allocStatus)); + DEBUG_LOG("loadPE: mapping failed (status=%u)\n", static_cast(allocStatus)); return false; } + DEBUG_LOG("loadPE: mapping succeeded (base=%p, size=%zu)\n", allocatedBase, allocationSize); std::unique_ptr imageGuard(allocatedBase); executable.imageBase = allocatedBase; diff --git a/src/modules.cpp b/src/modules.cpp index d7390d8..67622d8 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -40,6 +40,7 @@ extern const wibo::ModuleStub lib_ole32; extern const wibo::ModuleStub lib_user32; extern const wibo::ModuleStub lib_vcruntime; extern const wibo::ModuleStub lib_version; +extern const wibo::ModuleStub lib_ws2; // setup.S template void stubThunk(); @@ -186,7 +187,7 @@ LockedRegistry registry() { reg.initialized = true; const wibo::ModuleStub *builtins[] = { &lib_advapi32, &lib_bcrypt, &lib_kernel32, &lib_lmgr, &lib_mscoree, &lib_ntdll, - &lib_ole32, &lib_rpcrt4, &lib_user32, &lib_vcruntime, &lib_version, + &lib_ole32, &lib_rpcrt4, &lib_user32, &lib_vcruntime, &lib_version, &lib_ws2, #if WIBO_HAS_MSVCRT &lib_msvcrt, #endif @@ -1173,39 +1174,41 @@ static ModuleInfo *loadModuleInternal(const std::string &dllName) { ModuleInfo *raw = info.get(); reg->modulesByKey[key] = std::move(info); registerExternalModuleAliases(*reg, dllName, raw->resolvedPath, raw); - reg.lock.unlock(); - ensureExportsInitialized(*raw); - if (!raw->executable->resolveImports()) { - DEBUG_LOG(" resolveImports failed for %s\n", raw->originalName.c_str()); - reg.lock.lock(); - reg->modulesByKey.erase(key); - diskError = kernel32::getLastError(); - return nullptr; - } - if (!initializeModuleTls(*raw)) { - DEBUG_LOG(" initializeModuleTls failed for %s\n", raw->originalName.c_str()); - reg.lock.lock(); - reg->modulesByKey.erase(key); - diskError = kernel32::getLastError(); - return nullptr; - } - reg.lock.lock(); - if (!callDllMain(*raw, DLL_PROCESS_ATTACH, nullptr)) { - DEBUG_LOG(" DllMain failed for %s\n", raw->originalName.c_str()); - releaseModuleTls(*raw); - // runPendingOnExit(*raw); - for (auto it = reg->modulesByAlias.begin(); it != reg->modulesByAlias.end();) { - if (it->second == raw) { - it = reg->modulesByAlias.erase(it); - } else { - ++it; - } + if (raw->executable->isDll) { + reg.lock.unlock(); + ensureExportsInitialized(*raw); + if (!raw->executable->resolveImports()) { + DEBUG_LOG(" resolveImports failed for %s\n", raw->originalName.c_str()); + reg.lock.lock(); + reg->modulesByKey.erase(key); + diskError = kernel32::getLastError(); + return nullptr; + } + if (!initializeModuleTls(*raw)) { + DEBUG_LOG(" initializeModuleTls failed for %s\n", raw->originalName.c_str()); + reg.lock.lock(); + reg->modulesByKey.erase(key); + diskError = kernel32::getLastError(); + return nullptr; + } + reg.lock.lock(); + if (!callDllMain(*raw, DLL_PROCESS_ATTACH, nullptr)) { + DEBUG_LOG(" DllMain failed for %s\n", raw->originalName.c_str()); + releaseModuleTls(*raw); + // runPendingOnExit(*raw); + for (auto it = reg->modulesByAlias.begin(); it != reg->modulesByAlias.end();) { + if (it->second == raw) { + it = reg->modulesByAlias.erase(it); + } else { + ++it; + } + } + reg->pinnedModules.erase(raw); + reg->modulesByKey.erase(key); + diskError = ERROR_DLL_INIT_FAILED; + kernel32::setLastError(ERROR_DLL_INIT_FAILED); + return nullptr; } - reg->pinnedModules.erase(raw); - reg->modulesByKey.erase(key); - diskError = ERROR_DLL_INIT_FAILED; - kernel32::setLastError(ERROR_DLL_INIT_FAILED); - return nullptr; } return raw; }; diff --git a/src/modules.h b/src/modules.h index ac822ee..ca3c0fe 100644 --- a/src/modules.h +++ b/src/modules.h @@ -65,6 +65,7 @@ class Executable { bool importsResolved = false; bool importsResolving = false; bool sectionsProtected = false; + bool isDll = false; std::vector sections; };