diff --git a/data/scripts/global.ini b/data/scripts/global.ini index 93879a1..01b9380 100644 --- a/data/scripts/global.ini +++ b/data/scripts/global.ini @@ -2,6 +2,7 @@ LoadPlugins=1 LoadFromScriptsOnly=1 DontLoadFromDllMain=1 +;LoadFromAPI=GetSystemTimeAsFileTime FindModule=0 UseD3D8to9=0 DisableCrashDumps=0 diff --git a/premake5.lua b/premake5.lua index 0741090..58ba5e1 100644 --- a/premake5.lua +++ b/premake5.lua @@ -10,7 +10,7 @@ workspace "Ultimate-ASI-Loader-Win32" configurations { "Release", "Debug" } architecture "x86" location "build" - buildoptions {"-std:c++latest"} + cppdialect "C++latest" defines { "rsc_CompanyName=\"ThirteenAG\"" } defines { "rsc_LegalCopyright=\"MIT License\""} @@ -172,7 +172,7 @@ workspace "Ultimate-ASI-Loader-x64" configurations { "Release", "Debug" } architecture "x86_64" location "build" - buildoptions {"-std:c++latest"} + cppdialect "C++latest" defines { "rsc_CompanyName=\"ThirteenAG\"" } defines { "rsc_LegalCopyright=\"MIT License\""} diff --git a/source/demo_plugins/OverloadFromFolderDLL.cpp b/source/demo_plugins/OverloadFromFolderDLL.cpp index ffa3595..a9e604e 100644 --- a/source/demo_plugins/OverloadFromFolderDLL.cpp +++ b/source/demo_plugins/OverloadFromFolderDLL.cpp @@ -2,11 +2,17 @@ #include #include #include +#include +#include +#include #include #include "../../external/ModuleList/ModuleList.hpp" HMODULE hm = NULL; HMODULE ual = NULL; +std::vector extraDLLs = { + L"_nvngx.dll", L"dxilconv.dll" // for nvngx_dlss.dll loading +}; class DllCallbackHandler { @@ -129,117 +135,259 @@ typedef DWORD(WINAPI* tGetFileAttributesA)(LPCSTR lpFileName); typedef DWORD(WINAPI* tGetFileAttributesW)(LPCWSTR lpFileName); typedef BOOL(WINAPI* tGetFileAttributesExA)(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation); typedef BOOL(WINAPI* tGetFileAttributesExW)(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation); +typedef HMODULE(WINAPI* tCustomLoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +typedef HMODULE(WINAPI* tCustomLoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +typedef HMODULE(WINAPI* tCustomLoadLibraryA)(LPCSTR lpLibFileName); +typedef HMODULE(WINAPI* tCustomLoadLibraryW)(LPCWSTR lpLibFileName); tCreateFileA ptrCreateFileA; tCreateFileW ptrCreateFileW; tGetFileAttributesA ptrGetFileAttributesA; tGetFileAttributesW ptrGetFileAttributesW; tGetFileAttributesExA ptrGetFileAttributesExA; tGetFileAttributesExW ptrGetFileAttributesExW; +tCustomLoadLibraryExA ptrLoadLibraryExA; +tCustomLoadLibraryExW ptrLoadLibraryExW; +tCustomLoadLibraryA ptrLoadLibraryA; +tCustomLoadLibraryW ptrLoadLibraryW; -PIMAGE_SECTION_HEADER getSection(const PIMAGE_NT_HEADERS nt_headers, unsigned section) -{ - return reinterpret_cast( - (UCHAR*)nt_headers->OptionalHeader.DataDirectory + - nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) + - section * sizeof(IMAGE_SECTION_HEADER)); -} - -auto getSectionEnd(IMAGE_NT_HEADERS* ntHeader, size_t inst) +class IATHook { - auto sec = getSection(ntHeader, ntHeader->FileHeader.NumberOfSections - 1); - // .bind section may have vanished from the executable (test case: Yakuza 4) - // so back to the first valid section if that happened - while (sec->Misc.VirtualSize == 0) sec--; - - auto secSize = max(sec->SizeOfRawData, sec->Misc.VirtualSize); - auto end = inst + max(sec->PointerToRawData, sec->VirtualAddress) + secSize; - return end; -} - -bool HookKernel32IATForOverride(HMODULE mod) -{ - auto hExecutableInstance = (size_t)mod; - IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)(hExecutableInstance + ((IMAGE_DOS_HEADER*)hExecutableInstance)->e_lfanew); - IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)(hExecutableInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); - size_t nNumImports = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; +public: + template + static auto Replace(HMODULE target_module, std::string_view dll_name, Ts&& ... inputs) + { + std::map> originalPtrs; - uint32_t matchedImports = 0; + const DWORD_PTR instance = reinterpret_cast(target_module); + const PIMAGE_NT_HEADERS ntHeader = reinterpret_cast(instance + reinterpret_cast(instance)->e_lfanew); + PIMAGE_IMPORT_DESCRIPTOR pImports = reinterpret_cast(instance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + DWORD dwProtect[2]; - auto PatchIAT = [&](size_t start, size_t end, size_t exe_end) - { - for (size_t i = 0; i < nNumImports; i++) + for (; pImports->Name != 0; pImports++) { - if (hExecutableInstance + (pImports + i)->FirstThunk > start && !(end && hExecutableInstance + (pImports + i)->FirstThunk > end)) - end = hExecutableInstance + (pImports + i)->FirstThunk; + if (_stricmp(reinterpret_cast(instance + pImports->Name), dll_name.data()) == 0) + { + if (pImports->OriginalFirstThunk != 0) + { + const PIMAGE_THUNK_DATA pThunk = reinterpret_cast(instance + pImports->OriginalFirstThunk); + + for (ptrdiff_t j = 0; pThunk[j].u1.AddressOfData != 0; j++) + { + auto pAddress = reinterpret_cast(instance + pImports->FirstThunk) + j; + if (!pAddress) continue; + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + ([&] + { + auto name = std::string_view(std::get<0>(inputs)); + auto newAddr = std::get<1>(inputs); + auto num = std::string("-1"); + if (name.contains("@")) { + num = name.substr(name.find_last_of("@") + 1); + name = name.substr(0, name.find_last_of("@")); + } + + if (pThunk[j].u1.Ordinal & IMAGE_ORDINAL_FLAG) + { + try + { + if (newAddr && IMAGE_ORDINAL(pThunk[j].u1.Ordinal) == std::stoi(num.data())) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::deferred, [&]() -> void* { return *pAddress; }); + originalPtrs[std::get<0>(inputs)].wait(); + *pAddress = newAddr; + } + } + catch (...) {} + } + else if ((newAddr && *pAddress && *pAddress == (void*)GetProcAddress(GetModuleHandleA(dll_name.data()), name.data())) || + (strcmp(reinterpret_cast(instance + pThunk[j].u1.AddressOfData)->Name, name.data()) == 0)) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::deferred, [&]() -> void* { return *pAddress; }); + originalPtrs[std::get<0>(inputs)].wait(); + *pAddress = newAddr; + } + } (), ...); + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + } + } + else + { + auto pFunctions = reinterpret_cast(instance + pImports->FirstThunk); + + for (ptrdiff_t j = 0; pFunctions[j] != nullptr; j++) + { + auto pAddress = reinterpret_cast(pFunctions[j]); + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + ([&] + { + auto newAddr = std::get<1>(inputs); + if (newAddr && *pAddress && *pAddress == (void*)GetProcAddress(GetModuleHandleA(dll_name.data()), std::get<0>(inputs))) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::deferred, [&]() -> void* { return *pAddress; }); + originalPtrs[std::get<0>(inputs)].wait(); + *pAddress = newAddr; + } + } (), ...); + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + } + } + } } - if (!end) { end = start + 0x100; } - if (end > exe_end) //for very broken exes + if (originalPtrs.empty()) { - start = hExecutableInstance; - end = exe_end; + PIMAGE_DELAYLOAD_DESCRIPTOR pDelayed = reinterpret_cast(instance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress); + if (pDelayed) + { + for (; pDelayed->DllNameRVA != 0; pDelayed++) + { + if (_stricmp(reinterpret_cast(instance + pDelayed->DllNameRVA), dll_name.data()) == 0) + { + if (pDelayed->ImportAddressTableRVA != 0) + { + const PIMAGE_THUNK_DATA pThunk = reinterpret_cast(instance + pDelayed->ImportNameTableRVA); + const PIMAGE_THUNK_DATA pFThunk = reinterpret_cast(instance + pDelayed->ImportAddressTableRVA); + + for (ptrdiff_t j = 0; pThunk[j].u1.AddressOfData != 0; j++) + { + auto pAddress = reinterpret_cast(pFThunk[j].u1.Function); + if (!pAddress) continue; + if (pThunk[j].u1.Ordinal & IMAGE_ORDINAL_FLAG) + pAddress = *reinterpret_cast(pFThunk[j].u1.Function + 1); // mov eax, offset * + + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + ([&] + { + auto name = std::string_view(std::get<0>(inputs)); + auto newAddr = std::get<1>(inputs); + auto num = std::string("-1"); + if (name.contains("@")) { + num = name.substr(name.find_last_of("@") + 1); + name = name.substr(0, name.find_last_of("@")); + } + + if (pThunk[j].u1.Ordinal & IMAGE_ORDINAL_FLAG) + { + try + { + if (newAddr && IMAGE_ORDINAL(pThunk[j].u1.Ordinal) == std::stoi(num.data())) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::async, + [](void** pAddress, void* value, PVOID instance) -> void* + { + DWORD dwProtect[2]; + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + MEMORY_BASIC_INFORMATION mbi; + mbi.AllocationBase = instance; + do + { + VirtualQuery(*pAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } while (mbi.AllocationBase == instance); + auto r = *pAddress; + *pAddress = value; + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + return r; + }, pAddress, newAddr, (PVOID)instance); + } + } + catch (...) {} + } + else if ((newAddr && *pAddress && *pAddress == (void*)GetProcAddress(GetModuleHandleA(dll_name.data()), name.data())) || + (strcmp(reinterpret_cast(instance + pThunk[j].u1.AddressOfData)->Name, name.data()) == 0)) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::async, + [](void** pAddress, void* value, PVOID instance) -> void* + { + DWORD dwProtect[2]; + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + MEMORY_BASIC_INFORMATION mbi; + mbi.AllocationBase = instance; + do + { + VirtualQuery(*pAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } while (mbi.AllocationBase == instance); + auto r = *pAddress; + *pAddress = value; + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + return r; + }, pAddress, newAddr, (PVOID)instance); + } + } (), ...); + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + } + } + } + } + } } - for (auto i = start; i < end; i += sizeof(size_t)) + if (originalPtrs.empty()) // e.g. re5dx9.exe steam { - DWORD dwProtect[2]; - VirtualProtect((size_t*)i, sizeof(size_t), PAGE_EXECUTE_READWRITE, &dwProtect[0]); - - auto ptr = *(size_t*)i; - if (!ptr) - continue; - - if (ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateFileA")) - { - *(size_t*)i = (size_t)ptrCreateFileA; - matchedImports++; - } - else if (ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateFileW")) - { - *(size_t*)i = (size_t)ptrCreateFileW; - matchedImports++; - } - else if (ptrGetFileAttributesA && ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetFileAttributesA")) - { - *(size_t*)i = (size_t)ptrGetFileAttributesA; - matchedImports++; - } - else if (ptrGetFileAttributesW && ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetFileAttributesW")) + static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER { - *(size_t*)i = (size_t)ptrGetFileAttributesW; - matchedImports++; - } - else if (ptrGetFileAttributesExA && ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetFileAttributesExA")) - { - *(size_t*)i = (size_t)ptrGetFileAttributesExA; - matchedImports++; - } - else if (ptrGetFileAttributesExW && ptr == (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetFileAttributesExW")) + return reinterpret_cast( + (UCHAR*)nt_headers->OptionalHeader.DataDirectory + + nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) + + section * sizeof(IMAGE_SECTION_HEADER)); + }; + + for (auto i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) { - *(size_t*)i = (size_t)ptrGetFileAttributesExW; - matchedImports++; + auto sec = getSection(ntHeader, i); + auto pFunctions = reinterpret_cast(instance + max(sec->PointerToRawData, sec->VirtualAddress)); + + for (ptrdiff_t j = 0; j < 300; j++) + { + auto pAddress = reinterpret_cast(&pFunctions[j]); + VirtualProtect(pAddress, sizeof(pAddress), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + ([&] + { + auto name = std::string_view(std::get<0>(inputs)); + auto newAddr = std::get<1>(inputs); + auto num = std::string("-1"); + if (name.contains("@")) { + num = name.substr(name.find_last_of("@") + 1); + name = name.substr(0, name.find_last_of("@")); + } + + if (newAddr && *pAddress && *pAddress == (void*)GetProcAddress(GetModuleHandleA(dll_name.data()), name.data())) + { + originalPtrs[std::get<0>(inputs)] = std::async(std::launch::deferred, [&]() -> void* { return *pAddress; }); + originalPtrs[std::get<0>(inputs)].wait(); + *pAddress = newAddr; + } + } (), ...); + VirtualProtect(pAddress, sizeof(pAddress), dwProtect[0], &dwProtect[1]); + } + + if (!originalPtrs.empty()) + return originalPtrs; } - - VirtualProtect((size_t*)i, sizeof(size_t), dwProtect[0], &dwProtect[1]); } - }; - - auto hExecutableInstance_end = getSectionEnd(ntHeader, hExecutableInstance); - // Find kernel32.dll - for (size_t i = 0; i < nNumImports; i++) - { - if ((size_t)(hExecutableInstance + (pImports + i)->Name) < hExecutableInstance_end) - { - if (!_stricmp((const char*)(hExecutableInstance + (pImports + i)->Name), "KERNEL32.DLL")) - PatchIAT(hExecutableInstance + (pImports + i)->FirstThunk, 0, hExecutableInstance_end); - } + return originalPtrs; } +}; - return matchedImports > 0; +void HookKernel32IATForOverride(HMODULE mod) +{ + IATHook::Replace(mod, "KERNEL32.DLL", + std::forward_as_tuple("CreateFileA", ptrCreateFileA), + std::forward_as_tuple("CreateFileW", ptrCreateFileW), + std::forward_as_tuple("GetFileAttributesA", ptrGetFileAttributesA), + std::forward_as_tuple("GetFileAttributesW", ptrGetFileAttributesW), + std::forward_as_tuple("GetFileAttributesExA", ptrGetFileAttributesExA), + std::forward_as_tuple("GetFileAttributesExW", ptrGetFileAttributesExW), + std::forward_as_tuple("LoadLibraryExA", ptrLoadLibraryExA), + std::forward_as_tuple("LoadLibraryExW", ptrLoadLibraryExW), + std::forward_as_tuple("LoadLibraryA", ptrLoadLibraryA), + std::forward_as_tuple("LoadLibraryW", ptrLoadLibraryW) + ); } -void OverrideCreateFileInDLLs(HMODULE mod) +void OverrideInDLLs(HMODULE mod) { ModuleList dlls; dlls.Enumerate(ModuleList::SearchLocation::LocalOnly); @@ -249,6 +397,12 @@ void OverrideCreateFileInDLLs(HMODULE mod) if (m == mod && m != ual && m != hm && m != GetModuleHandle(NULL)) HookKernel32IATForOverride(mod); } + + for (auto& e : extraDLLs) + { + if (mod == GetModuleHandle(e.c_str())) + HookKernel32IATForOverride(mod); + } } extern "C" __declspec(dllexport) void InitializeASI() @@ -267,6 +421,11 @@ extern "C" __declspec(dllexport) void InitializeASI() auto pGetFileAttributesW = (tGetFileAttributesW)GetProcAddress(m, "CustomGetFileAttributesW"); auto pGetFileAttributesExA = (tGetFileAttributesExA)GetProcAddress(m, "CustomGetFileAttributesExA"); auto pGetFileAttributesExW = (tGetFileAttributesExW)GetProcAddress(m, "CustomGetFileAttributesExW"); + auto pLoadLibraryExA = (tCustomLoadLibraryExA)GetProcAddress(m, "CustomLoadLibraryExA"); + auto pLoadLibraryExW = (tCustomLoadLibraryExW)GetProcAddress(m, "CustomLoadLibraryExW"); + auto pLoadLibraryA = (tCustomLoadLibraryA)GetProcAddress(m, "CustomLoadLibraryA"); + auto pLoadLibraryW = (tCustomLoadLibraryW)GetProcAddress(m, "CustomLoadLibraryW"); + auto GetMemoryModule = (HMODULE(WINAPI*)())GetProcAddress(m, "GetMemoryModule"); if (pCreateFileA && pCreateFileW) { ual = m; @@ -280,19 +439,49 @@ extern "C" __declspec(dllexport) void InitializeASI() ptrGetFileAttributesExA = pGetFileAttributesExA; if (pGetFileAttributesExW) ptrGetFileAttributesExW = pGetFileAttributesExW; - break; - } - } + if (pLoadLibraryExA) + ptrLoadLibraryExA = pLoadLibraryExA; + if (pLoadLibraryExW) + ptrLoadLibraryExW = pLoadLibraryExW; + if (pLoadLibraryA) + ptrLoadLibraryA = pLoadLibraryA; + if (pLoadLibraryW) + ptrLoadLibraryW = pLoadLibraryW; + + for (auto& e : dlls.m_moduleList) + { + auto m = std::get(e); + if (m != ual && m != hm && m != GetModuleHandle(NULL)) + HookKernel32IATForOverride(m); + else if (m == ual && GetMemoryModule) + { + if (GetMemoryModule()) + { + auto ptr = *reinterpret_cast(GetMemoryModule()); + if (*reinterpret_cast(ptr) == 0x4550) //IMAGE_NT_SIGNATURE + { + for (size_t i = 0; i <= 0xF0; i++) + { + auto hModule = reinterpret_cast(ptr - i); + if (hModule->e_magic == IMAGE_DOS_SIGNATURE) + HookKernel32IATForOverride((HMODULE)hModule); + } + } + } + } + } + + for (auto& e : extraDLLs) + { + auto m = GetModuleHandle(e.c_str()); + if (m) + HookKernel32IATForOverride(m); + } + + DllCallbackHandler::RegisterCallback(OverrideInDLLs); - if (ptrCreateFileA && ptrCreateFileW) - { - for (auto& e : dlls.m_moduleList) - { - auto m = std::get(e); - if (m != ual && m != hm && m != GetModuleHandle(NULL)) - HookKernel32IATForOverride(m); + break; } - DllCallbackHandler::RegisterCallback(OverrideCreateFileInDLLs); } }); } diff --git a/source/dllmain.cpp b/source/dllmain.cpp index b89635a..56169dd 100644 --- a/source/dllmain.cpp +++ b/source/dllmain.cpp @@ -5,7 +5,7 @@ #if !X64 #include -extern "C" Direct3D8 *WINAPI Direct3DCreate8(UINT SDKVersion); +extern "C" Direct3D8* WINAPI Direct3DCreate8(UINT SDKVersion); #endif bool WINAPI IsUltimateASILoader() @@ -13,10 +13,17 @@ bool WINAPI IsUltimateASILoader() return true; } +void* ogMemModule = NULL; +void* WINAPI GetMemoryModule() +{ + return ogMemModule; +} + HMODULE hm; std::vector iniPaths; std::filesystem::path sFileLoaderPath; std::filesystem::path gamePath; +std::wstring sLoadFromAPI; bool iequals(std::wstring_view s1, std::wstring_view s2) { @@ -48,11 +55,6 @@ std::wstring SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE h return r; }; -HMODULE LoadLibraryW(const std::wstring& lpLibFileName) -{ - return LoadLibraryW(lpLibFileName.c_str()); -} - std::wstring GetCurrentDirectoryW() { static constexpr auto INITIAL_BUFFER_SIZE = MAX_PATH; @@ -163,6 +165,8 @@ enum Kernel32ExportsNames eGetShortPathNameA, eFindNextFileA, eFindNextFileW, + eLoadLibraryExA, + eLoadLibraryExW, eLoadLibraryA, eLoadLibraryW, eFreeLibrary, @@ -214,6 +218,7 @@ size_t OLE32Data[OLE32ExportsNamesCount][Kernel32ExportsDataCount]; #define IDR_BINK01994I 108 #endif +HMODULE LoadLibraryW(const std::wstring& lpLibFileName); static LONG OriginalLibraryLoaded = 0; void LoadOriginalLibrary() { @@ -326,7 +331,7 @@ void LoadOriginalLibrary() size_t dwResourceSize = SizeofResource(hm, hResource); if (0 != dwResourceSize) { - vorbisfile.LoadOriginalLibrary(MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize), true); + vorbisfile.LoadOriginalLibrary(ogMemModule = MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize), true); // Unprotect the module NOW (CLEO 4.1.1.30f crash fix) auto hExecutableInstance = (size_t)GetModuleHandle(NULL); @@ -424,7 +429,7 @@ void LoadOriginalLibrary() size_t dwResourceSize = SizeofResource(hm, hResource); if (0 != dwResourceSize) { - binkw32.LoadOriginalLibrary(MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize), true); + binkw32.LoadOriginalLibrary(ogMemModule = MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize), true); } } } @@ -605,7 +610,7 @@ void LoadPlugins() DWORD dwResourceSize = SizeofResource(hm, hResource); if (0 != dwResourceSize) { - MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize); + ogMemModule = MemoryLoadLibrary((const void*)pLockedResource, dwResourceSize); } } } @@ -631,6 +636,11 @@ void LoadPlugins() if (SetCurrentDirectoryW(L"plugins\\")) FindFiles(&fd); + + SetCurrentDirectoryW(szSelfPath.c_str()); + + if (SetCurrentDirectoryW(L"update\\")) + FindFiles(&fd); } SetCurrentDirectoryW(oldDir.c_str()); // Reset the current directory @@ -649,8 +659,11 @@ void LoadEverything() } static LONG RestoredOnce = 0; -void LoadPluginsAndRestoreIAT(uintptr_t retaddr) +void LoadPluginsAndRestoreIAT(uintptr_t retaddr, std::wstring_view calledFrom = L"") { + if (!sLoadFromAPI.empty() && calledFrom != sLoadFromAPI) + return; + bool calledFromBind = false; //steam drm check @@ -666,11 +679,10 @@ void LoadPluginsAndRestoreIAT(uintptr_t retaddr) if (_InterlockedCompareExchange(&RestoredOnce, 1, 0) != 0) return; - LoadEverything(); - for (size_t i = 0; i < Kernel32ExportsNamesCount; i++) { - if (!sFileLoaderPath.empty() && (i == eCreateFileA || i == eCreateFileW + if (!sFileLoaderPath.empty() && (i == eCreateFileA || i == eCreateFileW + || i == eLoadLibraryExA || i == eLoadLibraryExW || i == eLoadLibraryA || i == eLoadLibraryW || i == eGetFileAttributesA || i == eGetFileAttributesW || i == eGetFileAttributesExA || i == eGetFileAttributesExW)) continue; @@ -683,68 +695,182 @@ void LoadPluginsAndRestoreIAT(uintptr_t retaddr) VirtualProtect(ptr, sizeof(size_t), dwProtect[0], &dwProtect[1]); } } + + LoadEverything(); +} + +std::filesystem::path GetFileName(auto lpFilename) +{ + std::error_code ec; + + static auto starts_with = [](const std::filesystem::path& path, const std::filesystem::path& base) -> bool { + std::wstring str1(path.wstring()); std::wstring str2(base.wstring()); + std::transform(str1.begin(), str1.end(), str1.begin(), ::tolower); + std::transform(str2.begin(), str2.end(), str2.begin(), ::tolower); + return str1.starts_with(str2); + }; + + static auto lexicallyRelativeCaseIns = [](const std::filesystem::path& path, const std::filesystem::path& base) -> std::filesystem::path + { + class input_iterator_range + { + public: + input_iterator_range(const std::filesystem::path::const_iterator& first, const std::filesystem::path::const_iterator& last) + : _first(first) + , _last(last) + {} + std::filesystem::path::const_iterator begin() const { return _first; } + std::filesystem::path::const_iterator end() const { return _last; } + private: + std::filesystem::path::const_iterator _first; + std::filesystem::path::const_iterator _last; + }; + + if (!iequals(path.root_name().wstring(), base.root_name().wstring()) || path.is_absolute() != base.is_absolute() || (!path.has_root_directory() && base.has_root_directory())) { + return std::filesystem::path(); + } + std::filesystem::path::const_iterator a = path.begin(), b = base.begin(); + while (a != path.end() && b != base.end() && iequals(a->wstring(), b->wstring())) { + ++a; + ++b; + } + if (a == path.end() && b == base.end()) { + return std::filesystem::path("."); + } + int count = 0; + for (const auto& element : input_iterator_range(b, base.end())) { + if (element != "." && element != "" && element != "..") { + ++count; + } + else if (element == "..") { + --count; + } + } + if (count < 0) { + return std::filesystem::path(); + } + std::filesystem::path result; + for (int i = 0; i < count; ++i) { + result /= ".."; + } + for (const auto& element : input_iterator_range(a, path.end())) { + result /= element; + } + return result; + }; + + if (gamePath.empty()) + gamePath = std::filesystem::path(GetExeModulePath()); + + auto filePath = std::filesystem::path(lpFilename); + auto absolutePath = std::filesystem::absolute(filePath, ec); + auto relativePath = lexicallyRelativeCaseIns(absolutePath, gamePath); + auto commonPath = gamePath; + + if (starts_with(relativePath, "..")) + { + auto common = std::mismatch(absolutePath.begin(), absolutePath.end(), gamePath.begin()); + for (auto& iter = common.second; iter != gamePath.end(); ++iter) + commonPath = commonPath.parent_path(); + + std::filesystem::path rp; + for (auto& p : relativePath) + { + if (p != "..") + rp = rp / p; + } + relativePath = rp; + } + + if (starts_with(std::filesystem::path(absolutePath).remove_filename(), gamePath) || starts_with(std::filesystem::path(absolutePath).remove_filename(), commonPath)) + { + auto newPath = gamePath / sFileLoaderPath.make_preferred() / relativePath; + if (std::filesystem::exists(newPath, ec) && std::filesystem::is_regular_file(newPath, ec)) + return newPath; + } + + return lpFilename; +} + +HMODULE LoadLibraryW(const std::wstring& lpLibFileName) +{ + return LoadLibraryW(GetFileName(lpLibFileName).wstring().c_str()); } void WINAPI CustomGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetStartupInfoA"); return GetStartupInfoA(lpStartupInfo); } void WINAPI CustomGetStartupInfoW(LPSTARTUPINFOW lpStartupInfo) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetStartupInfoW"); return GetStartupInfoW(lpStartupInfo); } HMODULE WINAPI CustomGetModuleHandleA(LPCSTR lpModuleName) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetModuleHandleA"); return GetModuleHandleA(lpModuleName); } HMODULE WINAPI CustomGetModuleHandleW(LPCWSTR lpModuleName) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetModuleHandleW"); return GetModuleHandleW(lpModuleName); } FARPROC WINAPI CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetProcAddress"); return GetProcAddress(hModule, lpProcName); } DWORD WINAPI CustomGetShortPathNameA(LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetShortPathNameA"); return GetShortPathNameA(lpszLongPath, lpszShortPath, cchBuffer); } BOOL WINAPI CustomFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"FindNextFileA"); return FindNextFileA(hFindFile, lpFindFileData); } BOOL WINAPI CustomFindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"FindNextFileW"); return FindNextFileW(hFindFile, lpFindFileData); } +HMODULE WINAPI CustomLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + LoadOriginalLibrary(); + + return LoadLibraryExA(GetFileName(lpLibFileName).string().c_str(), hFile, dwFlags); +} + +HMODULE WINAPI CustomLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + LoadOriginalLibrary(); + + return LoadLibraryExW(GetFileName(lpLibFileName).wstring().c_str(), hFile, dwFlags); +} + HMODULE WINAPI CustomLoadLibraryA(LPCSTR lpLibFileName) { LoadOriginalLibrary(); - return LoadLibraryA(lpLibFileName); + return LoadLibraryA(GetFileName(lpLibFileName).string().c_str()); } HMODULE WINAPI CustomLoadLibraryW(LPCWSTR lpLibFileName) { LoadOriginalLibrary(); - return LoadLibraryW(lpLibFileName); + return LoadLibraryW(GetFileName(lpLibFileName).wstring().c_str()); } BOOL WINAPI CustomFreeLibrary(HMODULE hLibModule) @@ -757,157 +883,64 @@ BOOL WINAPI CustomFreeLibrary(HMODULE hLibModule) HANDLE WINAPI CustomCreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"CreateEventA"); return CreateEventA(lpEventAttributes, bManualReset, bInitialState, lpName); } HANDLE WINAPI CustomCreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"CreateEventW"); return CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName); } void WINAPI CustomGetSystemInfo(LPSYSTEM_INFO lpSystemInfo) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetSystemInfo"); return GetSystemInfo(lpSystemInfo); } LONG WINAPI CustomInterlockedCompareExchange(LONG volatile* Destination, LONG ExChange, LONG Comperand) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"InterlockedCompareExchange"); return _InterlockedCompareExchange(Destination, ExChange, Comperand); } void WINAPI CustomSleep(DWORD dwMilliseconds) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"Sleep"); return Sleep(dwMilliseconds); } void WINAPI CustomGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetSystemTimeAsFileTime"); return GetSystemTimeAsFileTime(lpSystemTimeAsFileTime); } DWORD WINAPI CustomGetCurrentProcessId() { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetCurrentProcessId"); return GetCurrentProcessId(); } LPSTR WINAPI CustomGetCommandLineA() { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetCommandLineA"); return GetCommandLineA(); } LPWSTR WINAPI CustomGetCommandLineW() { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetCommandLineW"); return GetCommandLineW(); } void WINAPI CustomAcquireSRWLockExclusive(PSRWLOCK SRWLock) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"AcquireSRWLockExclusive"); return AcquireSRWLockExclusive(SRWLock); } -std::filesystem::path GetFileName(auto lpFilename) -{ - std::error_code ec; - - static auto starts_with = [](const std::filesystem::path& path, const std::filesystem::path& base) -> bool { - std::wstring str1(path.wstring()); std::wstring str2(base.wstring()); - std::transform(str1.begin(), str1.end(), str1.begin(), ::tolower); - std::transform(str2.begin(), str2.end(), str2.begin(), ::tolower); - return str1.starts_with(str2); - }; - - static auto lexicallyRelativeCaseIns = [](const std::filesystem::path& path, const std::filesystem::path& base) -> std::filesystem::path - { - class input_iterator_range - { - public: - input_iterator_range(const std::filesystem::path::const_iterator& first, const std::filesystem::path::const_iterator& last) - : _first(first) - , _last(last) - {} - std::filesystem::path::const_iterator begin() const { return _first; } - std::filesystem::path::const_iterator end() const { return _last; } - private: - std::filesystem::path::const_iterator _first; - std::filesystem::path::const_iterator _last; - }; - - if (!iequals(path.root_name().wstring(), base.root_name().wstring()) || path.is_absolute() != base.is_absolute() || (!path.has_root_directory() && base.has_root_directory())) { - return std::filesystem::path(); - } - std::filesystem::path::const_iterator a = path.begin(), b = base.begin(); - while (a != path.end() && b != base.end() && iequals(a->wstring(), b->wstring())) { - ++a; - ++b; - } - if (a == path.end() && b == base.end()) { - return std::filesystem::path("."); - } - int count = 0; - for (const auto& element : input_iterator_range(b, base.end())) { - if (element != "." && element != "" && element != "..") { - ++count; - } - else if (element == "..") { - --count; - } - } - if (count < 0) { - return std::filesystem::path(); - } - std::filesystem::path result; - for (int i = 0; i < count; ++i) { - result /= ".."; - } - for (const auto& element : input_iterator_range(a, path.end())) { - result /= element; - } - return result; - }; - - if (gamePath.empty()) - gamePath = std::filesystem::path(GetExeModulePath()); - - auto filePath = std::filesystem::path(lpFilename); - auto absolutePath = std::filesystem::absolute(filePath, ec); - auto relativePath = lexicallyRelativeCaseIns(absolutePath, gamePath); - auto commonPath = gamePath; - - if (starts_with(relativePath, "..")) - { - auto common = std::mismatch(absolutePath.begin(), absolutePath.end(), gamePath.begin()); - for (auto& iter = common.second; iter != gamePath.end(); ++iter) - commonPath = commonPath.parent_path(); - - std::filesystem::path rp; - for (auto& p : relativePath) - { - if (p != "..") - rp = rp / p; - } - relativePath = rp; - } - - if (starts_with(std::filesystem::path(absolutePath).remove_filename(), gamePath) || starts_with(std::filesystem::path(absolutePath).remove_filename(), commonPath)) - { - auto newPath = gamePath / sFileLoaderPath.make_preferred() / relativePath; - if (std::filesystem::exists(newPath, ec) && std::filesystem::is_regular_file(newPath, ec)) - return newPath; - } - - return lpFilename; -} - typedef HANDLE(WINAPI* tCreateFileA)(LPCSTR lpFilename, DWORD dwAccess, DWORD dwSharing, LPSECURITY_ATTRIBUTES saAttributes, DWORD dwCreation, DWORD dwAttributes, HANDLE hTemplate); tCreateFileA ptrCreateFileA; HANDLE WINAPI CustomCreateFileA(LPCSTR lpFilename, DWORD dwAccess, DWORD dwSharing, LPSECURITY_ATTRIBUTES saAttributes, DWORD dwCreation, DWORD dwAttributes, HANDLE hTemplate) @@ -915,7 +948,7 @@ HANDLE WINAPI CustomCreateFileA(LPCSTR lpFilename, DWORD dwAccess, DWORD dwShari static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"CreateFileA"); once = true; } @@ -932,7 +965,7 @@ HANDLE WINAPI CustomCreateFileW(LPCWSTR lpFilename, DWORD dwAccess, DWORD dwShar static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"CreateFileW"); once = true; } @@ -949,7 +982,7 @@ DWORD WINAPI CustomGetFileAttributesA(LPCSTR lpFileName) static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetFileAttributesA"); once = true; } @@ -966,7 +999,7 @@ DWORD WINAPI CustomGetFileAttributesW(LPCWSTR lpFileName) static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetFileAttributesW"); once = true; } @@ -983,7 +1016,7 @@ BOOL WINAPI CustomGetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetFileAttributesExA"); once = true; } @@ -1000,7 +1033,7 @@ BOOL WINAPI CustomGetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVEL static bool once = false; if (!once) { - LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress(), L"GetFileAttributesExW"); once = true; } @@ -1068,6 +1101,8 @@ bool HookKernel32IAT(HMODULE mod, bool exe) Kernel32Data[eGetShortPathNameA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetShortPathNameA"); Kernel32Data[eFindNextFileA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileA"); Kernel32Data[eFindNextFileW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileW"); + Kernel32Data[eLoadLibraryExA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryExA"); + Kernel32Data[eLoadLibraryExW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryExW"); Kernel32Data[eLoadLibraryA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryA"); Kernel32Data[eLoadLibraryW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryW"); Kernel32Data[eFreeLibrary][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FreeLibrary"); @@ -1163,6 +1198,18 @@ bool HookKernel32IAT(HMODULE mod, bool exe) *(size_t*)i = (size_t)CustomFindNextFileW; matchedImports++; } + else if (ptr == Kernel32Data[eLoadLibraryExA][ProcAddress]) + { + if (exe) Kernel32Data[eLoadLibraryExA][IATPtr] = i; + *(size_t*)i = (size_t)CustomLoadLibraryExA; + matchedImports++; + } + else if (ptr == Kernel32Data[eLoadLibraryExW][ProcAddress]) + { + if (exe) Kernel32Data[eLoadLibraryExW][IATPtr] = i; + *(size_t*)i = (size_t)CustomLoadLibraryExW; + matchedImports++; + } else if (ptr == Kernel32Data[eLoadLibraryA][ProcAddress]) { if (exe) Kernel32Data[eLoadLibraryA][IATPtr] = i; @@ -1906,12 +1953,14 @@ void Init() iniPaths.emplace_back(modulePath + L"global.ini"); iniPaths.emplace_back(modulePath + L"scripts\\global.ini"); iniPaths.emplace_back(modulePath + L"plugins\\global.ini"); + iniPaths.emplace_back(modulePath + L"update\\global.ini"); - auto nForceEPHook = GetPrivateProfileInt(TEXT("globalsets"), TEXT("forceentrypointhook"), FALSE, iniPaths); - auto nDontLoadFromDllMain = GetPrivateProfileInt(TEXT("globalsets"), TEXT("dontloadfromdllmain"), TRUE, iniPaths); - auto nFindModule = GetPrivateProfileInt(TEXT("globalsets"), TEXT("findmodule"), FALSE, iniPaths); - auto nDisableCrashDumps = GetPrivateProfileInt(TEXT("globalsets"), TEXT("disablecrashdumps"), FALSE, iniPaths); - sFileLoaderPath = GetPrivateProfileString(TEXT("fileloader"), TEXT("overloadfromfolder"), TEXT("update"), iniPaths); + auto nForceEPHook = GetPrivateProfileIntW(TEXT("globalsets"), TEXT("forceentrypointhook"), FALSE, iniPaths); + auto nDontLoadFromDllMain = GetPrivateProfileIntW(TEXT("globalsets"), TEXT("dontloadfromdllmain"), TRUE, iniPaths); + sLoadFromAPI = GetPrivateProfileStringW(TEXT("globalsets"), TEXT("loadfromapi"), L"", iniPaths); + auto nFindModule = GetPrivateProfileIntW(TEXT("globalsets"), TEXT("findmodule"), FALSE, iniPaths); + auto nDisableCrashDumps = GetPrivateProfileIntW(TEXT("globalsets"), TEXT("disablecrashdumps"), FALSE, iniPaths); + sFileLoaderPath = GetPrivateProfileStringW(TEXT("fileloader"), TEXT("overloadfromfolder"), TEXT("update"), iniPaths); auto FolderExists = [](LPCWSTR szPath) -> BOOL { @@ -1945,6 +1994,13 @@ void Init() if (nForceEPHook != FALSE || nDontLoadFromDllMain != FALSE) { + if (sLoadFromAPI.empty()) // compatibility with GTAV/RDR2 plugins + { + auto exeName = std::filesystem::path(GetModulePath(NULL)).stem().wstring(); + if (iequals(exeName, L"GTA5") || iequals(exeName, L"RDR2") || iequals(exeName, L"game_win64_master")) + sLoadFromAPI = L"GetSystemTimeAsFileTime"; + } + HMODULE mainModule = GetModuleHandle(NULL); bool hookedSuccessfully = HookKernel32IAT(mainModule, true); if (!hookedSuccessfully) diff --git a/source/x64.def b/source/x64.def index ddce9d2..62b3bcc 100644 --- a/source/x64.def +++ b/source/x64.def @@ -1,12 +1,17 @@ LIBRARY "UAL" EXPORTS IsUltimateASILoader = IsUltimateASILoader +GetMemoryModule = GetMemoryModule CustomCreateFileA = CustomCreateFileA CustomCreateFileW = CustomCreateFileW CustomGetFileAttributesA = CustomGetFileAttributesA CustomGetFileAttributesW = CustomGetFileAttributesW CustomGetFileAttributesExA = CustomGetFileAttributesExA CustomGetFileAttributesExW = CustomGetFileAttributesExW +CustomLoadLibraryExA = CustomLoadLibraryExA +CustomLoadLibraryExW = CustomLoadLibraryExW +CustomLoadLibraryA = CustomLoadLibraryA +CustomLoadLibraryW = CustomLoadLibraryW LIBRARY "dinput8" EXPORTS diff --git a/source/x86.def b/source/x86.def index 7c00500..bcb3fc2 100644 --- a/source/x86.def +++ b/source/x86.def @@ -1,12 +1,17 @@ LIBRARY "UAL" EXPORTS IsUltimateASILoader = IsUltimateASILoader +GetMemoryModule = GetMemoryModule CustomCreateFileA = CustomCreateFileA CustomCreateFileW = CustomCreateFileW CustomGetFileAttributesA = CustomGetFileAttributesA CustomGetFileAttributesW = CustomGetFileAttributesW CustomGetFileAttributesExA = CustomGetFileAttributesExA CustomGetFileAttributesExW = CustomGetFileAttributesExW +CustomLoadLibraryExA = CustomLoadLibraryExA +CustomLoadLibraryExW = CustomLoadLibraryExW +CustomLoadLibraryA = CustomLoadLibraryA +CustomLoadLibraryW = CustomLoadLibraryW LIBRARY "vorbisfile" EXPORTS