From 2d367f56fe833bc4713aaf33c71d030f89f3629d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 15 Aug 2022 21:05:42 +0200 Subject: [PATCH] Improve FindPatternSIMD and GetVirtualMethodTable Allow searching for multiple occurrences, the main reason for this addition is that some RTTI object locators reference 2 (or more) VFTables, the ConVar class is a good example., where we have 2 separate VFTables, one implementing ConCommandBase (which implements its own IConVar), the other implementing just IConVar for ConVar (2 VMT pointers in one class). --- r5dev/public/utility/module.cpp | 27 +++++++++++++++++++-------- r5dev/public/utility/module.h | 6 +++--- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/r5dev/public/utility/module.cpp b/r5dev/public/utility/module.cpp index 362e1be4..dfea50c6 100644 --- a/r5dev/public/utility/module.cpp +++ b/r5dev/public/utility/module.cpp @@ -41,7 +41,7 @@ CModule::CModule(const string& svModuleName) : m_svModuleName(svModuleName) // *szMask - // Output : CMemory //----------------------------------------------------------------------------- -CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, ModuleSections_t moduleSection) const +CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, const ModuleSections_t& moduleSection, const uint32_t nOccurence) const { if (!m_ExecutableCode.IsSectionValid()) return CMemory(); @@ -58,6 +58,7 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, M const uint8_t* pData = reinterpret_cast(nBase); const uint8_t* pEnd = pData + static_cast(nSize) - strlen(szMask); + int nOccurenceCount = 0; int nMasks[64]; // 64*16 = enough masks for 1024 bytes. const int iNumMasks = static_cast(ceil(static_cast(strlen(szMask)) / 16.f)); @@ -91,7 +92,11 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, M { if ((i + 1) == iNumMasks) { - return static_cast(const_cast(pData)); + if (nOccurenceCount == nOccurence) + { + return static_cast(const_cast(pData)); + } + nOccurenceCount++; } } else @@ -99,7 +104,11 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, M goto cont; } } - return static_cast((&*(const_cast(pData)))); + if (nOccurenceCount == nOccurence) + { + return static_cast((&*(const_cast(pData)))); + } + nOccurenceCount++; } }cont:; } @@ -112,7 +121,7 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, M // Input : *szPattern // Output : CMemory //----------------------------------------------------------------------------- -CMemory CModule::FindPatternSIMD(const string& svPattern, ModuleSections_t moduleSection) const +CMemory CModule::FindPatternSIMD(const string& svPattern, const ModuleSections_t& moduleSection) const { const pair patternInfo = PatternToMaskedBytes(svPattern); return FindPatternSIMD(patternInfo.first.data(), patternInfo.second.c_str(), moduleSection); @@ -170,6 +179,7 @@ CMemory CModule::FindString(const string& svString, const ptrdiff_t nOccurence, return CMemory(); const CMemory stringAddress = FindStringReadOnly(svString, bNullTerminator); // Get Address for the string in the .rdata section. + if (!stringAddress) return CMemory(); @@ -254,12 +264,13 @@ CMemory CModule::GetExportedFunction(const string& svFunctionName) const //----------------------------------------------------------------------------- // Purpose: get address of a virtual method table by rtti type descriptor name. -// Input : *tableName - +// Input : *svTableName - +// nRefIndex - // Output : CMemory //----------------------------------------------------------------------------- -CMemory CModule::GetVirtualMethodTable(const std::string& tableName) +CMemory CModule::GetVirtualMethodTable(const string& svTableName, const uint32_t nRefIndex) { - const auto tableNameInfo = StringToMaskedBytes(tableName, false); + const auto tableNameInfo = StringToMaskedBytes(svTableName, false); CMemory rttiTypeDescriptor = FindPatternSIMD(tableNameInfo.first.data(), tableNameInfo.second.c_str(), { ".data", m_RunTimeData.m_pSectionBase, m_RunTimeData.m_nSectionSize }).OffsetSelf(-0x10); if (!rttiTypeDescriptor) return CMemory(); @@ -270,7 +281,7 @@ CMemory CModule::GetVirtualMethodTable(const std::string& tableName) const uintptr_t rttiTDRva = rttiTypeDescriptor.GetPtr() - m_pModuleBase; // The RTTI gets referenced by a 4-Byte RVA address. We need to scan for that address. while (scanStart < scanEnd) { - CMemory reference = FindPatternSIMD(reinterpret_cast(&rttiTDRva), "xxxx", { ".rdata", scanStart, m_ReadOnlyData.m_nSectionSize }); + CMemory reference = FindPatternSIMD(reinterpret_cast(&rttiTDRva), "xxxx", { ".rdata", scanStart, m_ReadOnlyData.m_nSectionSize }, nRefIndex); if (!reference) break; diff --git a/r5dev/public/utility/module.h b/r5dev/public/utility/module.h index 93d6d8cb..7fbca55a 100644 --- a/r5dev/public/utility/module.h +++ b/r5dev/public/utility/module.h @@ -22,12 +22,12 @@ public: CModule(void) = default; CModule(const string& moduleName); - CMemory FindPatternSIMD(const uint8_t* szPattern, const char* szMask, ModuleSections_t moduleSection = {}) const; - CMemory FindPatternSIMD(const string& svPattern, ModuleSections_t moduleSection = {}) const; + CMemory FindPatternSIMD(const uint8_t* szPattern, const char* szMask, const ModuleSections_t& moduleSection = {}, const uint32_t nOccurence = 0) const; + CMemory FindPatternSIMD(const string& svPattern, const ModuleSections_t& moduleSection = {}) const; CMemory FindString(const string& string, const ptrdiff_t occurence = 1, bool nullTerminator = false) const; CMemory FindStringReadOnly(const string& svString, bool nullTerminator) const; - CMemory GetVirtualMethodTable(const std::string& tableName); + CMemory GetVirtualMethodTable(const string& svTableName, const uint32_t nRefIndex = 0); CMemory GetExportedFunction(const string& svFunctionName) const; ModuleSections_t GetSectionByName(const string& svSectionName) const; uintptr_t GetModuleBase(void) const;