Skip to content

Commit

Permalink
hooking: run callbacks for imported modules (#780)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ASpoonPlaysGames authored Aug 27, 2024
1 parent 932735e commit f128835
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
15 changes: 15 additions & 0 deletions primedev/thirdparty/silver-bun/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ void CModule::Init()
m_ModuleSections.push_back(ModuleSections_t(reinterpret_cast<const char*>(hCurrentSection.Name),
static_cast<uintptr_t>(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<IMAGE_IMPORT_DESCRIPTOR*>(
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<char*>(reinterpret_cast<DWORD*>(m_pModuleBase + pIID->Name));

m_vImportedModules.push_back(szImportedModuleName);
}
}

//-----------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions primedev/thirdparty/silver-bun/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class CModule
ModuleSections_t GetSectionByName(const char* szSectionName) const;

inline const std::vector<CModule::ModuleSections_t>& GetSections() const { return m_ModuleSections; }
inline const std::vector<std::string>& 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; }
Expand All @@ -73,4 +74,5 @@ class CModule
uintptr_t m_pModuleBase;
DWORD m_nModuleSize;
std::vector<ModuleSections_t> m_ModuleSections;
std::vector<std::string> m_vImportedModules;
};
16 changes: 16 additions & 0 deletions primedev/windows/libsys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<HMODULE> 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
Expand Down

0 comments on commit f128835

Please sign in to comment.