From ef256618f646f090c00c5943d28494fc2a3f3a9a Mon Sep 17 00:00:00 2001 From: Marvin D <41352111+IcePixelx@users.noreply.github.com> Date: Fri, 9 Dec 2022 01:15:42 +0100 Subject: [PATCH] CVTableHelper class for easier RE. * THIS IS NOT SUPPOSED TO BE USED WITH SHIPPING CODE! * This is used for a quick way to call virtual functions for reverse engineering and rebuilding big functions, upon successful rebuild, implement needed VTables accordingly. --- r5dev/public/utility/vtable.cpp | 89 +++++++++++++++++++++++++++ r5dev/public/utility/vtable.h | 53 ++++++++++++++++ r5dev/vproj/clientsdk.vcxproj | 2 + r5dev/vproj/clientsdk.vcxproj.filters | 6 ++ r5dev/vproj/dedicated.vcxproj | 2 + r5dev/vproj/dedicated.vcxproj.filters | 6 ++ r5dev/vproj/gamesdk.vcxproj | 2 + r5dev/vproj/gamesdk.vcxproj.filters | 6 ++ 8 files changed, 166 insertions(+) create mode 100644 r5dev/public/utility/vtable.cpp create mode 100644 r5dev/public/utility/vtable.h diff --git a/r5dev/public/utility/vtable.cpp b/r5dev/public/utility/vtable.cpp new file mode 100644 index 00000000..e110dcc7 --- /dev/null +++ b/r5dev/public/utility/vtable.cpp @@ -0,0 +1,89 @@ +//===========================================================================// +// +// Purpose: Implementation of the CVTableHelper class, used to assist in +// function rebuilding and reverse engineering. +// DO NOT USE FOR SHIPPING CODE!!!!!!!!!! +// +//===========================================================================// +#include "core/stdafx.h" +#include "public/utility/vtable.h" +#include "public/utility/memaddr.h" + +//----------------------------------------------------------------------------- +// Purpose: create class instance from passed module and virtual table name +// Input : CModule* - +// const std::string& - +// uint32_t +//----------------------------------------------------------------------------- +CVTableHelper::CVTableHelper(CModule* module, const std::string& tableName, uint32_t refIndex) : m_svVirtualTableName(tableName) +{ + m_pVirtualTable = module->GetVirtualMethodTable(tableName, refIndex); + m_nVirtualFunctionCount = GetVTableLength(); + GetAllVTableFunctions(); +} + + +//----------------------------------------------------------------------------- +// Purpose: create class instance from passed pointer +// Input : uintptr_t - +// const std::string& - +//----------------------------------------------------------------------------- +CVTableHelper::CVTableHelper(uintptr_t virtualTable, const std::string& tableName) : m_pVirtualTable(virtualTable), m_svVirtualTableName(tableName) +{ + m_nVirtualFunctionCount = GetVTableLength(); + GetAllVTableFunctions(); +} + + +//----------------------------------------------------------------------------- +// Purpose: create class instance from passed pointer +// Input : void* - +// const std::string& - +//----------------------------------------------------------------------------- +CVTableHelper::CVTableHelper(void* virtualTable, const std::string& tableName) : m_pVirtualTable(uintptr_t(virtualTable)), m_svVirtualTableName(tableName) +{ + m_nVirtualFunctionCount = GetVTableLength(); + GetAllVTableFunctions(); +} + +//----------------------------------------------------------------------------- +// Purpose: gets function count of m_pVirtualTable +// Output : ptrdiff_t +//----------------------------------------------------------------------------- +ptrdiff_t CVTableHelper::GetVTableLength() +{ + uintptr_t* pStartOfVTable = reinterpret_cast(m_pVirtualTable); + MEMORY_BASIC_INFORMATION memInfo = { NULL }; + ptrdiff_t vtSize = -1; + + do { + vtSize++; + VirtualQuery(reinterpret_cast(pStartOfVTable[vtSize]), &memInfo, sizeof(memInfo)); + } while (memInfo.Protect == PAGE_EXECUTE_READ || memInfo.Protect == PAGE_EXECUTE_READWRITE); + + return vtSize; +} + +//----------------------------------------------------------------------------- +// Purpose: populate m_vVirtualFunctions with all virtual function pointers +//----------------------------------------------------------------------------- +void CVTableHelper::GetAllVTableFunctions() +{ + for (ptrdiff_t i = 0; i < m_nVirtualFunctionCount; i++) + { + m_vVirtualFunctions.push_back(*reinterpret_cast(m_pVirtualTable + (8 * i))); + } +} + +//----------------------------------------------------------------------------- +// Purpose: call function from m_vVirtualFunctions with passed index +// Input : int - +// void* - +// arg_list - +// Output : Assigned template return type +//----------------------------------------------------------------------------- +template +ReturnType CVTableHelper::Call(int index, void* thisPtr, Args... args) +{ + return reinterpret_cast(m_vVirtualFunctions.at(index))(thisPtr, args...); +} \ No newline at end of file diff --git a/r5dev/public/utility/vtable.h b/r5dev/public/utility/vtable.h new file mode 100644 index 00000000..247255fd --- /dev/null +++ b/r5dev/public/utility/vtable.h @@ -0,0 +1,53 @@ +#pragma once + +class CVTableHelper +{ +public: + + CVTableHelper(void) = default; + CVTableHelper(CModule* module, const std::string& tableName = "", uint32_t refIndex = 0); + CVTableHelper(uintptr_t virtualTable, const std::string& tableName = ""); + CVTableHelper(void* virtualTable, const std::string& tableName = ""); + + inline operator uintptr_t(void) const + { + return m_pVirtualTable; + } + + inline operator void* (void) const + { + return reinterpret_cast(m_pVirtualTable); + } + + inline operator bool(void) const + { + return m_pVirtualTable != NULL && !m_vVirtualFunctions.empty(); + } + + uintptr_t GetVirtualFunctionTable() + { + return m_pVirtualTable; + } + + ptrdiff_t GetVirtualFunctionCount() + { + return m_nVirtualFunctionCount; + } + + const std::string& GetVTableName() + { + return m_svVirtualTableName; + } + + template + ReturnType Call(int index, void* thisPtr, Args... args); + +private: + void GetAllVTableFunctions(); + ptrdiff_t GetVTableLength(); + + uintptr_t m_pVirtualTable; + string m_svVirtualTableName; + ptrdiff_t m_nVirtualFunctionCount; + vector m_vVirtualFunctions; +}; \ No newline at end of file diff --git a/r5dev/vproj/clientsdk.vcxproj b/r5dev/vproj/clientsdk.vcxproj index 1ebcecaf..59c7c3d9 100644 --- a/r5dev/vproj/clientsdk.vcxproj +++ b/r5dev/vproj/clientsdk.vcxproj @@ -107,6 +107,7 @@ + @@ -315,6 +316,7 @@ + diff --git a/r5dev/vproj/clientsdk.vcxproj.filters b/r5dev/vproj/clientsdk.vcxproj.filters index 2e0f11c1..2505cc74 100644 --- a/r5dev/vproj/clientsdk.vcxproj.filters +++ b/r5dev/vproj/clientsdk.vcxproj.filters @@ -645,6 +645,9 @@ sdk\engine + + sdk\public\utility + @@ -1871,6 +1874,9 @@ sdk\engine + + sdk\public\utility + diff --git a/r5dev/vproj/dedicated.vcxproj b/r5dev/vproj/dedicated.vcxproj index 2b940ac2..d9469e8d 100644 --- a/r5dev/vproj/dedicated.vcxproj +++ b/r5dev/vproj/dedicated.vcxproj @@ -248,6 +248,7 @@ + @@ -566,6 +567,7 @@ + diff --git a/r5dev/vproj/dedicated.vcxproj.filters b/r5dev/vproj/dedicated.vcxproj.filters index d1026dc6..41de95c6 100644 --- a/r5dev/vproj/dedicated.vcxproj.filters +++ b/r5dev/vproj/dedicated.vcxproj.filters @@ -1281,6 +1281,9 @@ sdk\public\utility + + sdk\public\utility + @@ -1616,6 +1619,9 @@ sdk\public\utility + + sdk\public\utility + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index 901c44d1..ea6527ac 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -116,6 +116,7 @@ + @@ -345,6 +346,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index 28608123..a70d2663 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -687,6 +687,9 @@ sdk\engine + + sdk\public\utility + @@ -1973,6 +1976,9 @@ sdk\engine + + sdk\public\utility +