mirror of
https://github.com/decompals/wibo.git
synced 2025-10-16 15:15:10 +00:00
Force builtin lmgr stub and stub missing imports
This commit is contained in:
parent
f23224bbcc
commit
b53ae15c82
2
common.h
2
common.h
@ -127,6 +127,8 @@ namespace wibo {
|
|||||||
void freeModule(HMODULE module);
|
void freeModule(HMODULE module);
|
||||||
void *resolveFuncByName(HMODULE module, const char *funcName);
|
void *resolveFuncByName(HMODULE module, const char *funcName);
|
||||||
void *resolveFuncByOrdinal(HMODULE module, uint16_t ordinal);
|
void *resolveFuncByOrdinal(HMODULE module, uint16_t ordinal);
|
||||||
|
void *resolveMissingImportByName(const char *dllName, const char *funcName);
|
||||||
|
void *resolveMissingImportByOrdinal(const char *dllName, uint16_t ordinal);
|
||||||
|
|
||||||
struct ResourceIdentifier {
|
struct ResourceIdentifier {
|
||||||
ResourceIdentifier() : isString(false), id(0) {}
|
ResourceIdentifier() : isString(false), id(0) {}
|
||||||
|
@ -261,6 +261,14 @@ namespace kernel32 {
|
|||||||
wibo::lastError = dwErrCode;
|
wibo::lastError = dwErrCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WIN_FUNC IsBadReadPtr(const void *lp, uintptr_t ucb) {
|
||||||
|
DEBUG_LOG("STUB: IsBadReadPtr(ptr=%p, size=%zu)\n", lp, static_cast<size_t>(ucb));
|
||||||
|
if (!lp) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC Wow64DisableWow64FsRedirection(void **OldValue) {
|
BOOL WIN_FUNC Wow64DisableWow64FsRedirection(void **OldValue) {
|
||||||
DEBUG_LOG("Wow64DisableWow64FsRedirection\n");
|
DEBUG_LOG("Wow64DisableWow64FsRedirection\n");
|
||||||
if (OldValue) {
|
if (OldValue) {
|
||||||
@ -3387,6 +3395,7 @@ static void *resolveByName(const char *name) {
|
|||||||
// errhandlingapi.h
|
// errhandlingapi.h
|
||||||
if (strcmp(name, "GetLastError") == 0) return (void *) kernel32::GetLastError;
|
if (strcmp(name, "GetLastError") == 0) return (void *) kernel32::GetLastError;
|
||||||
if (strcmp(name, "SetLastError") == 0) return (void *) kernel32::SetLastError;
|
if (strcmp(name, "SetLastError") == 0) return (void *) kernel32::SetLastError;
|
||||||
|
if (strcmp(name, "IsBadReadPtr") == 0) return (void *) kernel32::IsBadReadPtr;
|
||||||
if (strcmp(name, "Wow64DisableWow64FsRedirection") == 0) return (void *) kernel32::Wow64DisableWow64FsRedirection;
|
if (strcmp(name, "Wow64DisableWow64FsRedirection") == 0) return (void *) kernel32::Wow64DisableWow64FsRedirection;
|
||||||
if (strcmp(name, "Wow64RevertWow64FsRedirection") == 0) return (void *) kernel32::Wow64RevertWow64FsRedirection;
|
if (strcmp(name, "Wow64RevertWow64FsRedirection") == 0) return (void *) kernel32::Wow64RevertWow64FsRedirection;
|
||||||
if (strcmp(name, "RaiseException") == 0) return (void *) kernel32::RaiseException;
|
if (strcmp(name, "RaiseException") == 0) return (void *) kernel32::RaiseException;
|
||||||
|
14
loader.cpp
14
loader.cpp
@ -290,14 +290,16 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
|||||||
// Import by ordinal
|
// Import by ordinal
|
||||||
uint16_t ordinal = lookup & 0xFFFF;
|
uint16_t ordinal = lookup & 0xFFFF;
|
||||||
DEBUG_LOG(" Ordinal: %d\n", ordinal);
|
DEBUG_LOG(" Ordinal: %d\n", ordinal);
|
||||||
void *func = resolveFuncByOrdinal(module, ordinal);
|
void *func = module ? resolveFuncByOrdinal(module, ordinal)
|
||||||
|
: resolveMissingImportByOrdinal(dllName, ordinal);
|
||||||
DEBUG_LOG(" -> %p\n", func);
|
DEBUG_LOG(" -> %p\n", func);
|
||||||
*addressTable = reinterpret_cast<uintptr_t>(func);
|
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||||
} else {
|
} else {
|
||||||
// Import by name
|
// Import by name
|
||||||
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
||||||
DEBUG_LOG(" Name: %s (IAT=%p)\n", hintName->name, addressTable);
|
DEBUG_LOG(" Name: %s (IAT=%p)\n", hintName->name, addressTable);
|
||||||
void *func = resolveFuncByName(module, hintName->name);
|
void *func = module ? resolveFuncByName(module, hintName->name)
|
||||||
|
: resolveMissingImportByName(dllName, hintName->name);
|
||||||
DEBUG_LOG(" -> %p\n", func);
|
DEBUG_LOG(" -> %p\n", func);
|
||||||
*addressTable = reinterpret_cast<uintptr_t>(func);
|
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||||
}
|
}
|
||||||
@ -321,11 +323,15 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
|||||||
if (lookup & 0x80000000) {
|
if (lookup & 0x80000000) {
|
||||||
uint16_t ordinal = lookup & 0xFFFF;
|
uint16_t ordinal = lookup & 0xFFFF;
|
||||||
DEBUG_LOG(" Ordinal: %d (IAT=%p)\n", ordinal, addressTable);
|
DEBUG_LOG(" Ordinal: %d (IAT=%p)\n", ordinal, addressTable);
|
||||||
*addressTable = reinterpret_cast<uintptr_t>(resolveFuncByOrdinal(module, ordinal));
|
void *func = module ? resolveFuncByOrdinal(module, ordinal)
|
||||||
|
: resolveMissingImportByOrdinal(dllName, ordinal);
|
||||||
|
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||||
} else {
|
} else {
|
||||||
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
||||||
DEBUG_LOG(" Name: %s\n", hintName->name);
|
DEBUG_LOG(" Name: %s\n", hintName->name);
|
||||||
*addressTable = reinterpret_cast<uintptr_t>(resolveFuncByName(module, hintName->name));
|
void *func = module ? resolveFuncByName(module, hintName->name)
|
||||||
|
: resolveMissingImportByName(dllName, hintName->name);
|
||||||
|
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||||
}
|
}
|
||||||
++lookupTable;
|
++lookupTable;
|
||||||
++addressTable;
|
++addressTable;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@ -63,16 +64,35 @@ struct PEExportDirectory {
|
|||||||
FOR_256_2(0, 3) FOR_256_2(1, 0) FOR_256_2(1, 1) FOR_256_2(1, 2) FOR_256_2(1, 3) FOR_256_2(2, 0) FOR_256_2(2, 1) \
|
FOR_256_2(0, 3) FOR_256_2(1, 0) FOR_256_2(1, 1) FOR_256_2(1, 2) FOR_256_2(1, 3) FOR_256_2(2, 0) FOR_256_2(2, 1) \
|
||||||
FOR_256_2(2, 2) FOR_256_2(2, 3) FOR_256_2(3, 0) FOR_256_2(3, 1) FOR_256_2(3, 2) FOR_256_2(3, 3)
|
FOR_256_2(2, 2) FOR_256_2(2, 3) FOR_256_2(3, 0) FOR_256_2(3, 1) FOR_256_2(3, 2) FOR_256_2(3, 3)
|
||||||
|
|
||||||
|
static constexpr size_t MAX_STUBS = 0x100;
|
||||||
static int stubIndex = 0;
|
static int stubIndex = 0;
|
||||||
static char stubDlls[0x100][0x100];
|
static std::array<std::string, MAX_STUBS> stubDlls;
|
||||||
static char stubFuncNames[0x100][0x100];
|
static std::array<std::string, MAX_STUBS> stubFuncNames;
|
||||||
|
static std::unordered_map<std::string, void *> stubCache;
|
||||||
|
|
||||||
|
static std::string makeStubKey(const char *dllName, const char *funcName) {
|
||||||
|
std::string key;
|
||||||
|
if (dllName) {
|
||||||
|
key.assign(dllName);
|
||||||
|
std::transform(key.begin(), key.end(), key.begin(),
|
||||||
|
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
||||||
|
}
|
||||||
|
key.push_back(':');
|
||||||
|
if (funcName) {
|
||||||
|
std::string func(funcName);
|
||||||
|
std::transform(func.begin(), func.end(), func.begin(),
|
||||||
|
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
||||||
|
key += func;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
static void stubBase(int index) {
|
static void stubBase(int index) {
|
||||||
printf("Unhandled function %s (%s)\n", stubFuncNames[index], stubDlls[index]);
|
printf("Unhandled function %s (%s)\n", stubFuncNames[index].c_str(), stubDlls[index].c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*stubFuncs[0x100])(void) = {
|
void (*stubFuncs[MAX_STUBS])(void) = {
|
||||||
#define FOR_ITER(i) []() { stubBase(i); },
|
#define FOR_ITER(i) []() { stubBase(i); },
|
||||||
FOR_256
|
FOR_256
|
||||||
#undef FOR_ITER
|
#undef FOR_ITER
|
||||||
@ -84,12 +104,23 @@ void (*stubFuncs[0x100])(void) = {
|
|||||||
|
|
||||||
void *resolveMissingFuncName(const char *dllName, const char *funcName) {
|
void *resolveMissingFuncName(const char *dllName, const char *funcName) {
|
||||||
DEBUG_LOG("Missing function: %s (%s)\n", dllName, funcName);
|
DEBUG_LOG("Missing function: %s (%s)\n", dllName, funcName);
|
||||||
assert(stubIndex < 0x100);
|
std::string key = makeStubKey(dllName, funcName);
|
||||||
assert(strlen(dllName) < 0x100);
|
auto existing = stubCache.find(key);
|
||||||
assert(strlen(funcName) < 0x100);
|
if (existing != stubCache.end()) {
|
||||||
strcpy(stubFuncNames[stubIndex], funcName);
|
return existing->second;
|
||||||
strcpy(stubDlls[stubIndex], dllName);
|
}
|
||||||
return (void *)stubFuncs[stubIndex++];
|
if (stubIndex >= static_cast<int>(MAX_STUBS)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Too many missing functions encountered (>%zu). Last failure: %s (%s)\n",
|
||||||
|
MAX_STUBS, funcName, dllName);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stubFuncNames[stubIndex] = funcName ? funcName : "";
|
||||||
|
stubDlls[stubIndex] = dllName ? dllName : "";
|
||||||
|
void *stub = (void *)stubFuncs[stubIndex];
|
||||||
|
stubCache.emplace(std::move(key), stub);
|
||||||
|
stubIndex++;
|
||||||
|
return stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *resolveMissingFuncOrdinal(const char *dllName, uint16_t ordinal) {
|
void *resolveMissingFuncOrdinal(const char *dllName, uint16_t ordinal) {
|
||||||
@ -113,6 +144,8 @@ struct ModuleRegistry {
|
|||||||
std::unordered_map<void *, wibo::ModuleInfo *> onExitTables;
|
std::unordered_map<void *, wibo::ModuleInfo *> onExitTables;
|
||||||
std::unordered_map<const wibo::Module *, std::vector<std::string>> builtinAliasLists;
|
std::unordered_map<const wibo::Module *, std::vector<std::string>> builtinAliasLists;
|
||||||
std::unordered_map<std::string, wibo::ModuleInfo *> builtinAliasMap;
|
std::unordered_map<std::string, wibo::ModuleInfo *> builtinAliasMap;
|
||||||
|
std::unordered_set<std::string> pinnedAliases;
|
||||||
|
std::unordered_set<wibo::ModuleInfo *> pinnedModules;
|
||||||
};
|
};
|
||||||
|
|
||||||
ModuleRegistry ®istry() {
|
ModuleRegistry ®istry() {
|
||||||
@ -322,6 +355,9 @@ void registerAlias(const std::string &alias, wibo::ModuleInfo *info) {
|
|||||||
reg.modulesByAlias[alias] = info;
|
reg.modulesByAlias[alias] = info;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (reg.pinnedAliases.count(alias)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Prefer externally loaded modules over built-ins when both are present.
|
// Prefer externally loaded modules over built-ins when both are present.
|
||||||
if (it->second && it->second->module != nullptr && info->module == nullptr) {
|
if (it->second && it->second->module != nullptr && info->module == nullptr) {
|
||||||
reg.modulesByAlias[alias] = info;
|
reg.modulesByAlias[alias] = info;
|
||||||
@ -345,15 +381,25 @@ void registerBuiltinModule(const wibo::Module *module) {
|
|||||||
|
|
||||||
reg.builtinAliasLists[module] = {};
|
reg.builtinAliasLists[module] = {};
|
||||||
auto &aliasList = reg.builtinAliasLists[module];
|
auto &aliasList = reg.builtinAliasLists[module];
|
||||||
|
const bool pinModule = (module == &lib_lmgr);
|
||||||
|
if (pinModule) {
|
||||||
|
reg.pinnedModules.insert(raw);
|
||||||
|
}
|
||||||
for (size_t i = 0; module->names[i]; ++i) {
|
for (size_t i = 0; module->names[i]; ++i) {
|
||||||
std::string alias = normalizeAlias(module->names[i]);
|
std::string alias = normalizeAlias(module->names[i]);
|
||||||
aliasList.push_back(alias);
|
aliasList.push_back(alias);
|
||||||
|
if (pinModule) {
|
||||||
|
reg.pinnedAliases.insert(alias);
|
||||||
|
}
|
||||||
registerAlias(alias, raw);
|
registerAlias(alias, raw);
|
||||||
reg.builtinAliasMap[alias] = raw;
|
reg.builtinAliasMap[alias] = raw;
|
||||||
ParsedModuleName parsed = parseModuleName(module->names[i]);
|
ParsedModuleName parsed = parseModuleName(module->names[i]);
|
||||||
std::string baseAlias = normalizedBaseKey(parsed);
|
std::string baseAlias = normalizedBaseKey(parsed);
|
||||||
if (baseAlias != alias) {
|
if (baseAlias != alias) {
|
||||||
aliasList.push_back(baseAlias);
|
aliasList.push_back(baseAlias);
|
||||||
|
if (pinModule) {
|
||||||
|
reg.pinnedAliases.insert(baseAlias);
|
||||||
|
}
|
||||||
registerAlias(baseAlias, raw);
|
registerAlias(baseAlias, raw);
|
||||||
reg.builtinAliasMap[baseAlias] = raw;
|
reg.builtinAliasMap[baseAlias] = raw;
|
||||||
}
|
}
|
||||||
@ -706,11 +752,14 @@ HMODULE loadModule(const char *dllName) {
|
|||||||
lastError = ERROR_SUCCESS;
|
lastError = ERROR_SUCCESS;
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
bool pinned = reg.pinnedModules.count(existing) != 0;
|
||||||
|
if (!pinned) {
|
||||||
if (ModuleInfo *external = resolveAndLoadExternal()) {
|
if (ModuleInfo *external = resolveAndLoadExternal()) {
|
||||||
DEBUG_LOG(" replaced builtin module %s with external copy\n", requested.c_str());
|
DEBUG_LOG(" replaced builtin module %s with external copy\n", requested.c_str());
|
||||||
lastError = ERROR_SUCCESS;
|
lastError = ERROR_SUCCESS;
|
||||||
return external;
|
return external;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
lastError = ERROR_SUCCESS;
|
lastError = ERROR_SUCCESS;
|
||||||
DEBUG_LOG(" returning builtin module %s\n", existing->originalName.c_str());
|
DEBUG_LOG(" returning builtin module %s\n", existing->originalName.c_str());
|
||||||
return existing;
|
return existing;
|
||||||
@ -828,6 +877,21 @@ void *resolveFuncByOrdinal(HMODULE module, uint16_t ordinal) {
|
|||||||
return resolveMissingFuncOrdinal(info->originalName.c_str(), ordinal);
|
return resolveMissingFuncOrdinal(info->originalName.c_str(), ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *resolveMissingImportByName(const char *dllName, const char *funcName) {
|
||||||
|
const char *safeDll = dllName ? dllName : "";
|
||||||
|
const char *safeFunc = funcName ? funcName : "";
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(registry().mutex);
|
||||||
|
ensureInitialized();
|
||||||
|
return resolveMissingFuncName(safeDll, safeFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *resolveMissingImportByOrdinal(const char *dllName, uint16_t ordinal) {
|
||||||
|
const char *safeDll = dllName ? dllName : "";
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(registry().mutex);
|
||||||
|
ensureInitialized();
|
||||||
|
return resolveMissingFuncOrdinal(safeDll, ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
Executable *executableFromModule(HMODULE module) {
|
Executable *executableFromModule(HMODULE module) {
|
||||||
if (isMainModule(module)) {
|
if (isMainModule(module)) {
|
||||||
return mainModule;
|
return mainModule;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user