mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +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 *resolveFuncByName(HMODULE module, const char *funcName);
|
||||
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 {
|
||||
ResourceIdentifier() : isString(false), id(0) {}
|
||||
|
@ -261,6 +261,14 @@ namespace kernel32 {
|
||||
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) {
|
||||
DEBUG_LOG("Wow64DisableWow64FsRedirection\n");
|
||||
if (OldValue) {
|
||||
@ -3387,6 +3395,7 @@ static void *resolveByName(const char *name) {
|
||||
// errhandlingapi.h
|
||||
if (strcmp(name, "GetLastError") == 0) return (void *) kernel32::GetLastError;
|
||||
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, "Wow64RevertWow64FsRedirection") == 0) return (void *) kernel32::Wow64RevertWow64FsRedirection;
|
||||
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
|
||||
uint16_t ordinal = lookup & 0xFFFF;
|
||||
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);
|
||||
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||
} else {
|
||||
// Import by name
|
||||
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
||||
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);
|
||||
*addressTable = reinterpret_cast<uintptr_t>(func);
|
||||
}
|
||||
@ -321,11 +323,15 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
||||
if (lookup & 0x80000000) {
|
||||
uint16_t ordinal = lookup & 0xFFFF;
|
||||
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 {
|
||||
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
||||
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;
|
||||
++addressTable;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "strutil.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#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(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 char stubDlls[0x100][0x100];
|
||||
static char stubFuncNames[0x100][0x100];
|
||||
static std::array<std::string, MAX_STUBS> stubDlls;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
void (*stubFuncs[0x100])(void) = {
|
||||
void (*stubFuncs[MAX_STUBS])(void) = {
|
||||
#define FOR_ITER(i) []() { stubBase(i); },
|
||||
FOR_256
|
||||
#undef FOR_ITER
|
||||
@ -84,12 +104,23 @@ void (*stubFuncs[0x100])(void) = {
|
||||
|
||||
void *resolveMissingFuncName(const char *dllName, const char *funcName) {
|
||||
DEBUG_LOG("Missing function: %s (%s)\n", dllName, funcName);
|
||||
assert(stubIndex < 0x100);
|
||||
assert(strlen(dllName) < 0x100);
|
||||
assert(strlen(funcName) < 0x100);
|
||||
strcpy(stubFuncNames[stubIndex], funcName);
|
||||
strcpy(stubDlls[stubIndex], dllName);
|
||||
return (void *)stubFuncs[stubIndex++];
|
||||
std::string key = makeStubKey(dllName, funcName);
|
||||
auto existing = stubCache.find(key);
|
||||
if (existing != stubCache.end()) {
|
||||
return existing->second;
|
||||
}
|
||||
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) {
|
||||
@ -113,6 +144,8 @@ struct ModuleRegistry {
|
||||
std::unordered_map<void *, wibo::ModuleInfo *> onExitTables;
|
||||
std::unordered_map<const wibo::Module *, std::vector<std::string>> builtinAliasLists;
|
||||
std::unordered_map<std::string, wibo::ModuleInfo *> builtinAliasMap;
|
||||
std::unordered_set<std::string> pinnedAliases;
|
||||
std::unordered_set<wibo::ModuleInfo *> pinnedModules;
|
||||
};
|
||||
|
||||
ModuleRegistry ®istry() {
|
||||
@ -322,6 +355,9 @@ void registerAlias(const std::string &alias, wibo::ModuleInfo *info) {
|
||||
reg.modulesByAlias[alias] = info;
|
||||
return;
|
||||
}
|
||||
if (reg.pinnedAliases.count(alias)) {
|
||||
return;
|
||||
}
|
||||
// Prefer externally loaded modules over built-ins when both are present.
|
||||
if (it->second && it->second->module != nullptr && info->module == nullptr) {
|
||||
reg.modulesByAlias[alias] = info;
|
||||
@ -345,15 +381,25 @@ void registerBuiltinModule(const wibo::Module *module) {
|
||||
|
||||
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) {
|
||||
std::string alias = normalizeAlias(module->names[i]);
|
||||
aliasList.push_back(alias);
|
||||
if (pinModule) {
|
||||
reg.pinnedAliases.insert(alias);
|
||||
}
|
||||
registerAlias(alias, raw);
|
||||
reg.builtinAliasMap[alias] = raw;
|
||||
ParsedModuleName parsed = parseModuleName(module->names[i]);
|
||||
std::string baseAlias = normalizedBaseKey(parsed);
|
||||
if (baseAlias != alias) {
|
||||
aliasList.push_back(baseAlias);
|
||||
if (pinModule) {
|
||||
reg.pinnedAliases.insert(baseAlias);
|
||||
}
|
||||
registerAlias(baseAlias, raw);
|
||||
reg.builtinAliasMap[baseAlias] = raw;
|
||||
}
|
||||
@ -706,10 +752,13 @@ HMODULE loadModule(const char *dllName) {
|
||||
lastError = ERROR_SUCCESS;
|
||||
return existing;
|
||||
}
|
||||
if (ModuleInfo *external = resolveAndLoadExternal()) {
|
||||
DEBUG_LOG(" replaced builtin module %s with external copy\n", requested.c_str());
|
||||
lastError = ERROR_SUCCESS;
|
||||
return external;
|
||||
bool pinned = reg.pinnedModules.count(existing) != 0;
|
||||
if (!pinned) {
|
||||
if (ModuleInfo *external = resolveAndLoadExternal()) {
|
||||
DEBUG_LOG(" replaced builtin module %s with external copy\n", requested.c_str());
|
||||
lastError = ERROR_SUCCESS;
|
||||
return external;
|
||||
}
|
||||
}
|
||||
lastError = ERROR_SUCCESS;
|
||||
DEBUG_LOG(" returning builtin module %s\n", existing->originalName.c_str());
|
||||
@ -828,6 +877,21 @@ void *resolveFuncByOrdinal(HMODULE module, uint16_t 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) {
|
||||
if (isMainModule(module)) {
|
||||
return mainModule;
|
||||
|
Loading…
x
Reference in New Issue
Block a user