From f1288350c729d63aeeb0a6bdab0746b865131668 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Tue, 27 Aug 2024 07:48:33 +0100 Subject: hooking: run callbacks for imported modules (#780) Previously we only ran callbacks for modules loaded using WinAPI. This now also runs callbacks for modules imported by those loaded by WinAPI. This fixes callbacks for miles and bink dlls. --- primedev/thirdparty/silver-bun/module.cpp | 15 +++++++++++++++ primedev/thirdparty/silver-bun/module.h | 2 ++ primedev/windows/libsys.cpp | 16 ++++++++++++++++ 3 files changed, 33 insertions(+) (limited to 'primedev') diff --git a/primedev/thirdparty/silver-bun/module.cpp b/primedev/thirdparty/silver-bun/module.cpp index 84f4da9e..dceb602a 100644 --- a/primedev/thirdparty/silver-bun/module.cpp +++ b/primedev/thirdparty/silver-bun/module.cpp @@ -66,6 +66,21 @@ void CModule::Init() m_ModuleSections.push_back(ModuleSections_t(reinterpret_cast(hCurrentSection.Name), static_cast(m_pModuleBase + hCurrentSection.VirtualAddress), hCurrentSection.SizeOfRawData)); // Push back a struct with the section data. } + + // Get the location of IMAGE_IMPORT_DESCRIPTOR for this module by adding the IMAGE_DIRECTORY_ENTRY_IMPORT relative virtual address onto our + // module base address. + IMAGE_IMPORT_DESCRIPTOR* pImageImportDescriptors = reinterpret_cast( + m_pModuleBase + m_pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + if (!pImageImportDescriptors) + return; + + for (IMAGE_IMPORT_DESCRIPTOR* pIID = pImageImportDescriptors; pIID->Name != 0; pIID++) + { + // Get virtual relative Address of the imported module name. Then add module base Address to get the actual location. + const char* szImportedModuleName = reinterpret_cast(reinterpret_cast(m_pModuleBase + pIID->Name)); + + m_vImportedModules.push_back(szImportedModuleName); + } } //----------------------------------------------------------------------------- diff --git a/primedev/thirdparty/silver-bun/module.h b/primedev/thirdparty/silver-bun/module.h index 5683ee14..cc513086 100644 --- a/primedev/thirdparty/silver-bun/module.h +++ b/primedev/thirdparty/silver-bun/module.h @@ -52,6 +52,7 @@ public: ModuleSections_t GetSectionByName(const char* szSectionName) const; inline const std::vector& GetSections() const { return m_ModuleSections; } + inline const std::vector& GetImportedModules() const { return m_vImportedModules; } inline uintptr_t GetModuleBase(void) const { return m_pModuleBase; } inline DWORD GetModuleSize(void) const { return m_nModuleSize; } inline const std::string& GetModuleName(void) const { return m_ModuleName; } @@ -73,4 +74,5 @@ private: uintptr_t m_pModuleBase; DWORD m_nModuleSize; std::vector m_ModuleSections; + std::vector m_vImportedModules; }; diff --git a/primedev/windows/libsys.cpp b/primedev/windows/libsys.cpp index 501eae68..0aff820b 100644 --- a/primedev/windows/libsys.cpp +++ b/primedev/windows/libsys.cpp @@ -18,15 +18,31 @@ ILoadLibraryExW o_LoadLibraryExW = nullptr; //----------------------------------------------------------------------------- void LibSys_RunModuleCallbacks(HMODULE hModule) { + // Modules that we have already ran callbacks for. + // Note: If we ever hook unloading modules, then this will need updating to handle removal etc. + static std::vector vCalledModules; + if (!hModule) { return; } + // If we have already ran callbacks for this module, don't run them again. + if (std::find(vCalledModules.begin(), vCalledModules.end(), hModule) != vCalledModules.end()) + { + return; + } + vCalledModules.push_back(hModule); + // Get module base name in ASCII as noone wants to deal with unicode CHAR szModuleName[MAX_PATH]; GetModuleBaseNameA(GetCurrentProcess(), hModule, szModuleName, MAX_PATH); + // Run calllbacks for all imported modules + CModule cModule(hModule); + for (const std::string& svImport : cModule.GetImportedModules()) + LibSys_RunModuleCallbacks(GetModuleHandleA(svImport.c_str())); + // DevMsg(eLog::NONE, "%s\n", szModuleName); // Call callbacks -- cgit v1.2.3