mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Implemented CModule::GetVirtualMethodTable.
* Added CModule::GetVirtualMethodTable. Gets you a pointer to a VTable by its rtti type descriptor name. * Added StringToMaskedBytes. Turns a string into masked bytes. * CModule::FindPatternSIMD now allows you to custom define a section it should search in.
This commit is contained in:
parent
79b4d7889a
commit
22bb1d4cde
@ -22,11 +22,12 @@ public:
|
||||
|
||||
CModule(void) = default;
|
||||
CModule(const string& moduleName);
|
||||
CMemory FindPatternSIMD(const uint8_t* szPattern, const char* szMask) const;
|
||||
CMemory FindPatternSIMD(const string& svPattern) const;
|
||||
CMemory FindPatternSIMD(const uint8_t* szPattern, const char* szMask, ModuleSections_t moduleSection = {}) const;
|
||||
CMemory FindPatternSIMD(const string& svPattern, 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 GetExportedFunction(const string& svFunctionName) const;
|
||||
ModuleSections_t GetSectionByName(const string& svSectionName) const;
|
||||
uintptr_t GetModuleBase(void) const;
|
||||
|
@ -45,6 +45,7 @@ string StringUnescape(const string& svInput);
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Bytes
|
||||
vector<int> StringToBytes(const string& svInput, bool bNullTerminator);
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const string& svInput, bool bNullTerminator);
|
||||
vector<int> PatternToBytes(const string& svInput);
|
||||
pair<vector<uint8_t>, string> PatternToMaskedBytes(const string& svInput);
|
||||
vector<int> IntToDigits(int iValue);
|
||||
|
@ -41,13 +41,19 @@ CModule::CModule(const string& svModuleName) : m_svModuleName(svModuleName)
|
||||
// *szMask -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask) const
|
||||
CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, ModuleSections_t moduleSection) const
|
||||
{
|
||||
if (!m_ExecutableCode.IsSectionValid())
|
||||
return CMemory();
|
||||
|
||||
const uint64_t nBase = static_cast<uint64_t>(m_ExecutableCode.m_pSectionBase);
|
||||
const uint64_t nSize = static_cast<uint64_t>(m_ExecutableCode.m_nSectionSize);
|
||||
uint64_t nBase = static_cast<uint64_t>(m_ExecutableCode.m_pSectionBase);
|
||||
uint64_t nSize = static_cast<uint64_t>(m_ExecutableCode.m_nSectionSize);
|
||||
|
||||
if (moduleSection.IsSectionValid())
|
||||
{
|
||||
nBase = static_cast<uint64_t>(moduleSection.m_pSectionBase);
|
||||
nSize = static_cast<uint64_t>(moduleSection.m_nSectionSize);
|
||||
}
|
||||
|
||||
const uint8_t* pData = reinterpret_cast<uint8_t*>(nBase);
|
||||
const uint8_t* pEnd = pData + static_cast<uint32_t>(nSize) - strlen(szMask);
|
||||
@ -106,10 +112,10 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask) c
|
||||
// Input : *szPattern
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindPatternSIMD(const string& svPattern) const
|
||||
CMemory CModule::FindPatternSIMD(const string& svPattern, ModuleSections_t moduleSection) const
|
||||
{
|
||||
const pair patternInfo = PatternToMaskedBytes(svPattern);
|
||||
return FindPatternSIMD(patternInfo.first.data(), patternInfo.second.c_str());
|
||||
return FindPatternSIMD(patternInfo.first.data(), patternInfo.second.c_str(), moduleSection);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -246,6 +252,45 @@ CMemory CModule::GetExportedFunction(const string& svFunctionName) const
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get address of a virtual method table by rtti type descriptor name.
|
||||
// Input : *tableName -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::GetVirtualMethodTable(const std::string& tableName)
|
||||
{
|
||||
const auto tableNameInfo = StringToMaskedBytes(tableName, 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();
|
||||
|
||||
vector <CMemory> rttiTDRef = {};
|
||||
uintptr_t scanStart = m_ReadOnlyData.m_pSectionBase; // Get the start address of our scan.
|
||||
|
||||
const uintptr_t scanEnd = (m_ReadOnlyData.m_pSectionBase + m_ReadOnlyData.m_nSectionSize) - 0x4; // Calculate the end of our scan.
|
||||
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<rsig_t>(&rttiTDRva), "xxxx", {".rdata", scanStart, m_ReadOnlyData.m_nSectionSize});
|
||||
if (!reference)
|
||||
break;
|
||||
|
||||
rttiTDRef.push_back(reference);
|
||||
scanStart = reference.Offset(0x4).GetPtr(); // Set location to current reference + 0x4 so we avoid pushing it back again into the vector.
|
||||
}
|
||||
|
||||
for (const CMemory& ref : rttiTDRef)
|
||||
{
|
||||
CMemory referenceOffset = ref.Offset(-0xC);
|
||||
if (referenceOffset.GetValue<int32_t>() != 1) // Check if we got a RTTI Object Locator for this reference by checking if -0xC is 1, which is the 'signature' field which is always 1 on x64.
|
||||
continue;
|
||||
|
||||
return FindPatternSIMD(reinterpret_cast<rsig_t>(&referenceOffset), "xxxx", { ".rdata", m_ReadOnlyData.m_pSectionBase, m_ReadOnlyData.m_nSectionSize }).OffsetSelf(0x8);
|
||||
}
|
||||
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get the module section by name (example: '.rdata', '.text')
|
||||
// Input : *svModuleName -
|
||||
|
@ -581,6 +581,30 @@ vector<int> StringToBytes(const string& svInput, bool bNullTerminator)
|
||||
return vBytes;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string to an array of bytes.
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const string& svInput, bool bNullTerminator)
|
||||
{
|
||||
char* pszStringStart = const_cast<char*>(svInput.c_str());
|
||||
char* pszStringEnd = pszStringStart + strlen(svInput.c_str());
|
||||
vector<uint8_t> vBytes = vector<uint8_t>{ };
|
||||
string svMask = string();
|
||||
|
||||
for (char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
||||
{
|
||||
// Dereference character and push back the byte.
|
||||
vBytes.push_back(*pszCurrentByte);
|
||||
svMask.append("x");
|
||||
}
|
||||
|
||||
if (bNullTerminator)
|
||||
{
|
||||
vBytes.push_back(0x0);
|
||||
svMask.append("x");
|
||||
}
|
||||
return make_pair(vBytes, svMask);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string pattern with wildcards to an array of bytes.
|
||||
vector<int> PatternToBytes(const string& svInput)
|
||||
|
Loading…
x
Reference in New Issue
Block a user