diff --git a/r5dev/include/gameclasses.h b/r5dev/include/gameclasses.h index e68b5323..03a63b0f 100644 --- a/r5dev/include/gameclasses.h +++ b/r5dev/include/gameclasses.h @@ -1,4 +1,5 @@ #pragma once +#include "patterns.h" ///////////////////////////////////////////////////////////////////////////// // Enums @@ -223,22 +224,22 @@ enum ButtonCode_t class CInputSystem { public: - void EnableInput(bool bEnabled) + void EnableInput(bool bEnabled)// @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM { using OriginalFn = void(__thiscall*)(CInputSystem*, bool); - (*reinterpret_cast(this))[10](this, bEnabled); // EnableInput is virtual function index 10 in the CInputSystem virtual table. + (*reinterpret_cast(this))[10](this, bEnabled); } - void EnableMessagePump(bool bEnabled) + void EnableMessagePump(bool bEnabled) // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM { using OriginalFn = void(__thiscall*)(CInputSystem*, bool); - (*reinterpret_cast(this))[11](this, bEnabled); // EnableMessagePump is virtual function index 11 in the CInputSystem virtual table. + (*reinterpret_cast(this))[11](this, bEnabled); } - bool IsButtonDown(ButtonCode_t Button) + bool IsButtonDown(ButtonCode_t Button) // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM { using OriginalFn = bool(__thiscall*)(CInputSystem*, ButtonCode_t); - return (*reinterpret_cast(this))[13](this, Button); // IsButtonDown is virtual function index 13 in the CInputSystem virtual table. + return (*reinterpret_cast(this))[13](this, Button); } private: @@ -246,4 +247,206 @@ private: public: bool m_bEnabled; //0x0010 IsInputEnabled variable. bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable. +}; + +typedef int HKeySymbol; + +class CKeyValuesSystem // VTABLE @ 0x1413AA1E8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM +{ +public: + + void RegisterSizeofKeyValues(__int64 size) //@0x1413AA1F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, __int64); + (*reinterpret_cast(this))[0](this, size); + } + + void* AllocKeyValuesMemory(__int64 size) // @0x1413AA1F8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = void*(__thiscall*)(CKeyValuesSystem*, __int64); + return (*reinterpret_cast(this))[1](this, size); + } + + void FreeKeyValuesMemory(void* pMem) // @0x1413AA200 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, void*); + (*reinterpret_cast(this))[2](this, pMem); + } + + HKeySymbol GetSymbolForString(const char* name, bool bCreate) // @0x1413AA208 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, const char*, bool); + return (*reinterpret_cast(this))[3](this, name, bCreate); + } + + const char* GetStringForSymbol(HKeySymbol symbol) // @0x1413AA210 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = const char*(__thiscall*)(CKeyValuesSystem*, HKeySymbol); + return (*reinterpret_cast(this))[4](this, symbol); + } + +// void __fastcall CKeyValuesSystem::FreeKeyValuesMemory(CKeyValuesSystem* this_arg, void* ptr_mem_arg) +// { +// __int64* v2; // rax +// __int64 v4; // rax +// __int64* v5; // rax +// +// v2 = qword_14D40B538; +// if (!qword_14D40B538) +// { +// v2 = sub_140462930(); +// qword_14D40B538 = v2; +// } +// v4 = (*(*v2 + 48))(v2, ptr_mem_arg); +// if (v4 > 0) +// CKeyValuesSystem::m_pMemPool -= v4; +// v5 = qword_14D40B538; +// if (!qword_14D40B538) +// { +// v5 = sub_140462930(); +// qword_14D40B538 = v5; +// } +// (*(*v5 + 40))(v5, ptr_mem_arg); +// } + + // GetMemPool return a global variable called m_pMemPool it gets modified by AllocKeyValuesMemory and FreeKeyValuesMemory above you can see where the find it in FreeKeyValuesMemory. + void* GetMemPool() // @0x1413AA228 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + return reinterpret_cast(0x14D412768); // May need to dereference is once more not sure right now. + } + + void SetKeyValuesExpressionSymbol(const char* name, bool bValue) // @0x1413AA230 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, const char*, bool); + (*reinterpret_cast(this))[8](this, name, bValue); + } + + bool GetKeyValuesExpressionSymbol(const char* name) // @0x1413AA238 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = bool(__thiscall*)(CKeyValuesSystem*, const char*); + return (*reinterpret_cast(this))[9](this, name); + } + + HKeySymbol GetSymbolForStringCaseSensitive(HKeySymbol& hCaseInsensitiveSymbol, const char* name, bool bCreate) // @0x1413AA240 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, HKeySymbol&, const char*, bool); + return (*reinterpret_cast(this))[10](this, hCaseInsensitiveSymbol, name, bCreate); + } + + // Datatypes aren't accurate. But full fill the actual byte distance. +public: + void* vtable; + __int64 m_iMaxKeyValuesSize; +private: + char gap10[240]; +public: + int m_KvConditionalSymbolTable; +private: + char gap104[4]; +public: + __int64 field_108; +private: + char gap110[32]; +public: + int m_mutex; +}; + +enum KeyValuesTypes +{ + TYPE_NONE = 0x0, + TYPE_STRING = 0x1, + TYPE_INT = 0x2, + TYPE_FLOAT = 0x3, + TYPE_PTR = 0x4, + TYPE_WSTRING = 0x5, + TYPE_COLOR = 0x6, + TYPE_UINT64 = 0x7, + TYPE_COMPILED_INT_BYTE = 0x8, + TYPE_COMPILED_INT_0 = 0x9, + TYPE_COMPILED_INT_1 = 0xA, + TYPE_NUMTYPES = 0xB, +}; + +class KeyValues +{ +public: + + KeyValues* FindKey(const char* keyName, bool bCreate) + { + // static auto func = reinterpret_cast(p_KeyValues_FindKey); + // return func(this, keyName, bCreate); + return nullptr; + } + + int GetInt(const char* keyName, int defaultValue) + { + KeyValues* dat = FindKey(keyName, false); + + if (!dat) + return defaultValue; + + switch (dat->m_iDataType) + { + case TYPE_STRING: + return atoi(dat->m_sValue); + case TYPE_FLOAT: + return static_cast(m_flValue()); + case TYPE_WSTRING: + return _wtoi(dat->m_wsValue); + case TYPE_UINT64: + return 0; + default: + return dat->m_iValue(); + } + + return defaultValue; + } + + void SetInt(const char* keyName, int iValue) + { + KeyValues* dat = FindKey(keyName, true); + if (dat) + { + dat->m_iValue() = iValue; + dat->m_iDataType = TYPE_INT; + } + } + + void SetFloat(const char* keyName, float flValue) + { + KeyValues* dat = FindKey(keyName, true); + if (dat) + { + dat->m_flValue() = flValue; + dat->m_iDataType = TYPE_FLOAT; + } + } + + // Compiler makes it so m_Value shares the offset spot with m_flValue that why we cast it like this. + float& m_flValue() + { + static __int32 offset = 0x18; + return *(float*)((std::uintptr_t)this + offset); + } + + int& m_iValue() + { + static __int32 offset = 0x18; + return *(int*)((std::uintptr_t)this + offset); + } + +public: + unsigned __int32 m_iKeyName : 24; + unsigned __int32 m_iKeyNameCaseSensitive : 8; + char* m_sValue; + wchar_t* m_wsValue; + int m_Value; +private: + char gap1C[12]; +public: + char m_iDataType; + unsigned __int16 m_iKeyNameCaseSensitive2; + KeyValues* m_pPeer; + KeyValues* m_pSub; + KeyValues* m_pChain; }; \ No newline at end of file diff --git a/r5dev/include/opcptc.h b/r5dev/include/opcptc.h index dea12757..23f08f0b 100644 --- a/r5dev/include/opcptc.h +++ b/r5dev/include/opcptc.h @@ -11,20 +11,20 @@ inline HANDLE GameProcess = GetCurrentProcess(); namespace { /* -------------- ORIGIN ------------------------------------------------------------------------------------------------------------------------------------------------ */ - DWORD64 dst000 = /*0x14032EEA0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x83\xEC\x28\x80\x3D\x00\x00\x00\x23\x00\x0F\x85\x00\x02\x00", "xxxxxx???xxxx?xx"); - DWORD64 dst001 = /*0x140330290*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x81\xEC\x58\x04\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x0F\x84", "xxxxxxxxx????xxx"); + DWORD64 dst000 /*0x14032EEA0*/ = reinterpret_cast(PatternScan("r5apex.exe", "48 83 EC 28 80 3D ? ? ? 23 ? 0F 85 ? 02 ?")); + DWORD64 dst001 /*0x140330290*/ = reinterpret_cast(PatternScan("r5apex.exe", "48 81 EC 58 04 ? ? 80 3D ? ? ? ? ? 0F 84")); /* -------------- ENGINE ------------------------------------------------------------------------------------------------------------------------------------------------ */ - DWORD64 dst002 = /*0x14043FB90*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x4C\x24\x08\x56\x41\x55\x48\x81\xEC\x68\x03\x00\x00\x4C", "xxxx?xxxxxxxxxxx"); - DWORD64 dst003 = /*0x140302FF0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x40\x53\x41\x56\x41\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x89\x74", "xxxxxxxxxxxxxxxx"); - DWORD64 dst004 = /*0x14022A4A0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x83\xEC\x38\x0F\x29\x74\x24\x20\x48\x89\x5C\x24\x40\x48\x8B", "xxxxxxxxxxxxxxxx"); - DWORD64 dst005 = /*0x140238DA0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x8B\xC4\x00\x41\x54\x41\x00\x48\x81\xEC\x00\x00\x00\x00\xF2", "xxx?xxx?xxx??xxx"); + DWORD64 dst002 /*0x14043FB90*/ = reinterpret_cast(PatternScan("r5apex.exe", "48 89 4C 24 08 56 41 55 48 81 EC 68 03 ? ? 4C")); + DWORD64 dst003 /*0x140302FF0*/ = reinterpret_cast(PatternScan("r5apex.exe", "40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74")); + DWORD64 dst004 /*0x14022A4A0*/ = reinterpret_cast(PatternScan("r5apex.exe", "48 83 EC 38 0F 29 74 24 20 48 89 5C 24 40 48 8B")); + DWORD64 dst005 /*0x140238DA0*/ = reinterpret_cast(PatternScan("r5apex.exe", "48 8B C4 ? 41 54 41 ? 48 81 EC ? ? ? ? F2")); /* -------------- NETCHAN ----------------------------------------------------------------------------------------------------------------------------------------------- */ - DWORD64 dst006 = /*0x14030D000*/ FindPattern("r5apex.exe", (const unsigned char*)"\x40\x55\x57\x41\x55\x41\x57\x48\x8D\xAC\x24\x28\xFF\xFF\xFF\x48", "xxxxxxxxxxxxxxxx"); + DWORD64 dst006 /*0x14030D000*/ = reinterpret_cast(PatternScan("r5apex.exe", "40 55 57 41 55 41 57 48 8D AC 24 ? ? ? ?")); /* -------------- FAIRFIGHT --------------------------------------------------------------------------------------------------------------------------------------------- */ - DWORD64 dst007 = /*0x140303AE0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x40\x53\x48\x83\xEC\x20\x8B\x81\xB0\x03\x00\x00\x48\x8B\xD9\xC6", "xxxxxxxxxxxxxxxx"); + DWORD64 dst007 /*0x140303AE0*/ = reinterpret_cast(PatternScan("r5apex.exe", "40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6")); /* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */ @@ -34,16 +34,16 @@ namespace void PrintOAddress() // Test the sigscan results { std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| dst000 : " << std::hex << dst000 << std::setw(20) << " |" << std::endl; - std::cout << "| dst001 : " << std::hex << dst001 << std::setw(20) << " |" << std::endl; + std::cout << "| dst000 : " << std::hex << std::uppercase << dst000 << std::setw(20) << " |" << std::endl; + std::cout << "| dst001 : " << std::hex << std::uppercase << dst001 << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| dst002 : " << std::hex << dst002 << std::setw(20) << " |" << std::endl; - std::cout << "| dst003 : " << std::hex << dst003 << std::setw(20) << " |" << std::endl; - std::cout << "| dst004 : " << std::hex << dst004 << std::setw(20) << " |" << std::endl; - std::cout << "| dst005 : " << std::hex << dst005 << std::setw(20) << " |" << std::endl; + std::cout << "| dst002 : " << std::hex << std::uppercase << dst002 << std::setw(20) << " |" << std::endl; + std::cout << "| dst003 : " << std::hex << std::uppercase << dst003 << std::setw(20) << " |" << std::endl; + std::cout << "| dst004 : " << std::hex << std::uppercase << dst004 << std::setw(20) << " |" << std::endl; + std::cout << "| dst005 : " << std::hex << std::uppercase << dst005 << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| dst006 : " << std::hex << dst006 << std::setw(20) << " |" << std::endl; - std::cout << "| dst007 : " << std::hex << dst007 << std::setw(20) << " |" << std::endl; + std::cout << "| dst006 : " << std::hex << std::uppercase << dst006 << std::setw(20) << " |" << std::endl; + std::cout << "| dst007 : " << std::hex << std::uppercase << dst007 << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; // TODO implement error handling when sigscan fails or result is 0 diff --git a/r5dev/include/patterns.h b/r5dev/include/patterns.h index 53d28bd7..5b8067d8 100644 --- a/r5dev/include/patterns.h +++ b/r5dev/include/patterns.h @@ -9,58 +9,63 @@ namespace { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ==== CONSOLE ========================================================================================================================================================= */ - DWORD64 p_CommandExecute = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x48\x8D\x0D\x27\x61\xa5\x1E\x41\x8B\xD8", "xxxx?xxxxxxxx????xxx"); - void (*CommandExecute)(void* self, const char* cmd) = (void (*)(void*, const char*))p_CommandExecute; /*48 89 5C 24 ?? 57 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 41 8B D8*/ + DWORD64 p_CommandExecute = /*0x140202090*/ reinterpret_cast(PatternScan("r5apex.exe", "48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 41 8B D8")); + void (*CommandExecute)(void* self, const char* cmd) = (void (*)(void*, const char*))p_CommandExecute; - DWORD64 p_ConVar_IsFlagSet = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x8B\x41\x48\x85\x50\x38", "xxxxxxx"); - bool (*ConVar_IsFlagSet)(int** cvar, int flag) = (bool (*)(int**, int))p_ConVar_IsFlagSet; /*48 8B 41 48 85 50 38*/ + DWORD64 p_ConVar_IsFlagSet = /*0x14046FE90*/ reinterpret_cast(PatternScan("r5apex.exe", "48 8B 41 48 85 50 38")); + bool (*ConVar_IsFlagSet)(int** cvar, int flag) = (bool (*)(int**, int))p_ConVar_IsFlagSet; - LONGLONG p_ConCommand_IsFlagSet = FindPattern("r5apex.exe", (const unsigned char*)"\x85\x51\x38\x0F\x95\xC0\xC3", "xxxxxxx"); - bool (*ConCommand_IsFlagSet)(int* cmd, int flag) = (bool (*)(int*, int))p_ConCommand_IsFlagSet; /*85 51 38 0F 95 C0 C3*/ + DWORD64 p_ConCommand_IsFlagSet = /*0x14046F490*/ reinterpret_cast(PatternScan("r5apex.exe", "85 51 38 0F 95 C0 C3")); + bool (*ConCommand_IsFlagSet)(int* cmd, int flag) = (bool (*)(int*, int))p_ConCommand_IsFlagSet; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ==== SQUIRREL ======================================================================================================================================================== */ - DWORD64 p_SQVM_Print = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x8B\xC4\x48\x89\x50\x10\x4C\x89\x40\x18\x4C\x89\x48\x20\x53\x56\x57\x48\x81\xEC\x30\x08\x00\x00\x48\x8B\xDA\x48\x8D\x70\x18\x48\x8B\xF9\xE8\x00\x00\x00\xFF\x48\x89\x74\x24\x28\x48\x8D\x54\x24\x30\x33", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx???xxxxxxxxxxxx"); - void* SQVM_Print = (void*)p_SQVM_Print; /*48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC 30 08 00 00 48 8B DA 48 8D 70 18 48 8B F9 E8 ?? ?? ?? FF 48 89 74 24 28 48 8D 54 24 30 33*/ + DWORD64 p_SQVM_Print = /*0x141057FD0*/ reinterpret_cast(PatternScan("r5apex.exe","48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC 30 08 00 00 48 8B DA 48 8D 70 18 48 8B F9 E8 ?? ?? ?? FF 48 89 74 24 28 48 8D 54 24 30 33")); + void* SQVM_Print = (void*)p_SQVM_Print; //DWORD64 p_SQVM_LoadScript = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x48\x89\x4C\x24\x08\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); // For S0 and S1 - DWORD64 p_SQVM_LoadScript = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x8B\xC4\x48\x89\x48\x08\x55\x41\x56\x48\x8D\x68", "xxxxxxxxxxxxx"); // For anything S2 and above (current S8) + DWORD64 p_SQVM_LoadScript = /*0x141055630*/ reinterpret_cast(PatternScan("r5apex.exe", "48 8B C4 48 89 48 08 55 41 56 48 8D 68")); // For anything S2 and above (current S8) bool (*SQVM_LoadScript)(void* sqvm, const char* script_path, const char* script_name, int flag) = (bool (*)(void*, const char*, const char*, int))p_SQVM_LoadScript; /*E8 ?? ?? ?? ?? 84 C0 74 1C 41 B9 ?? ?? ?? ??*/ - DWORD64 p_SQVM_LoadRson = FindPattern("r5apex.exe", (const unsigned char*)"\x4C\x8B\xDC\x49\x89\x5B\x08\x57\x48\x81\xEC\xA0\x00\x00\x00\x33", "xxxxxxxxxxxxxxxx"); - int (*SQVM_LoadRson)(const char* rson_name) = (int (*)(const char*))p_SQVM_LoadRson; /*4C 8B DC 49 89 5B 08 57 48 81 EC A0 00 00 00 33*/ + DWORD64 p_SQVM_LoadRson = /*0x140C957E0*/ reinterpret_cast(PatternScan("r5apex.exe", "4C 8B DC 49 89 5B 08 57 48 81 EC A0 00 00 00 33")); + int (*SQVM_LoadRson)(const char* rson_name) = (int (*)(const char*))p_SQVM_LoadRson; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ==== NETCHAN ========================================================================================================================================================= */ - DWORD64 p_NET_ReceiveDatagram = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x50\xEB", "xxxxxxxxxxxxxxxxxxxxxxxxx"); + DWORD64 p_NET_ReceiveDatagram = /*0x1402655F0*/ reinterpret_cast(PatternScan("r5apex.exe", "48 89 74 24 18 48 89 7C 24 20 55 41 54 41 55 41 56 41 57 48 8D AC 24 50 EB")); bool (*NET_ReceiveDatagram)(int, void*, bool) = (bool (*)(int, void*, bool))p_NET_ReceiveDatagram; /*E8 ?? ?? ?? ?? 84 C0 75 35 48 8B D3*/ - DWORD64 p_NET_SendDatagram = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x56\x41\x57\x48\x81\xEC\x00\x05\x00\x00", "xxxxxxxxxxxxxxxxxxxxxxx?xxx"); - int (*NET_SendDatagram)(SOCKET s, const char* buf, int len, int flags) = (int (*)(SOCKET, const char*, int, int))p_NET_SendDatagram; /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ?? 05 00 00*/ + DWORD64 p_NET_SendDatagram = /*0x1402662D0*/ reinterpret_cast(PatternScan("r5apex.exe", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ? 05 ? ?")); + int (*NET_SendDatagram)(SOCKET s, const char* buf, int len, int flags) = (int (*)(SOCKET, const char*, int, int))p_NET_SendDatagram; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ==== UTILITY ========================================================================================================================================================= */ - DWORD64 p_MSG_EngineError = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x81\xEC\x30\x08\x00\x00\x48\x8B\xDA\x48\x8B\xF9\xE8\x00\x00\x00\xFF\x33\xF6\x48", "xxxxxxxxxxxxxxxxxxxxxxxxx???xxxx"); - int (*MSG_EngineError)(char* fmt, va_list args) = (int (*)(char*, va_list))p_MSG_EngineError; /*48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA 48 8B F9 E8 ?? ?? ?? FF 33 F6 48*/ + DWORD64 p_MSG_EngineError = /*0x140295600*/ reinterpret_cast(PatternScan("r5apex.exe", "48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA 48 8B F9 E8 ?? ?? ?? FF 33 F6 48")); + int (*MSG_EngineError)(char* fmt, va_list args) = (int (*)(char*, va_list))p_MSG_EngineError; + // Un-used atm. + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /* ==== KEYVALUES ======================================================================================================================================================= */ + // DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45")); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ==== ------- ========================================================================================================================================================= */ void PrintHAddress() // Test the sigscan results { std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| CommandExecute : " << std::hex << p_CommandExecute << std::setw(20) << " |" << std::endl; - std::cout << "| ConVar_IsFlagSet : " << std::hex << p_ConVar_IsFlagSet << std::setw(20) << " |" << std::endl; - std::cout << "| ConCommand_IsFlagSet : " << std::hex << p_ConCommand_IsFlagSet << std::setw(20) << " |" << std::endl; + std::cout << "| CommandExecute : " << std::hex << std::uppercase << p_CommandExecute << std::setw(20) << " |" << std::endl; + std::cout << "| ConVar_IsFlagSet : " << std::hex << std::uppercase << p_ConVar_IsFlagSet << std::setw(20) << " |" << std::endl; + std::cout << "| ConCommand_IsFlagSet : " << std::hex << std::uppercase << p_ConCommand_IsFlagSet << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| SQVM_Print : " << std::hex << p_SQVM_Print << std::setw(20) << " |" << std::endl; - std::cout << "| SQVM_LoadScript : " << std::hex << p_SQVM_LoadScript << std::setw(20) << " |" << std::endl; - std::cout << "| SQVM_LoadRson : " << std::hex << p_SQVM_LoadRson << std::setw(20) << " |" << std::endl; + std::cout << "| SQVM_Print : " << std::hex << std::uppercase << p_SQVM_Print << std::setw(20) << " |" << std::endl; + std::cout << "| SQVM_LoadScript : " << std::hex << std::uppercase << p_SQVM_LoadScript << std::setw(20) << " |" << std::endl; + std::cout << "| SQVM_LoadRson : " << std::hex << std::uppercase << p_SQVM_LoadRson << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| NET_ReceiveDatagram : " << std::hex << p_NET_ReceiveDatagram << std::setw(20) << " |" << std::endl; - std::cout << "| NET_SendDatagram : " << std::hex << p_NET_SendDatagram << std::setw(20) << " |" << std::endl; + std::cout << "| NET_ReceiveDatagram : " << std::hex << std::uppercase << p_NET_ReceiveDatagram << std::setw(20) << " |" << std::endl; + std::cout << "| NET_SendDatagram : " << std::hex << std::uppercase << p_NET_SendDatagram << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; - std::cout << "| MSG_EngineError : " << std::hex << p_NET_SendDatagram << std::setw(20) << " |" << std::endl; + std::cout << "| MSG_EngineError : " << std::hex << std::uppercase << p_MSG_EngineError << std::setw(20) << " |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; // TODO implement error handling when sigscan fails or result is 0 diff --git a/r5dev/include/utility.h b/r5dev/include/utility.h index 5f35c393..fc233db0 100644 --- a/r5dev/include/utility.h +++ b/r5dev/include/utility.h @@ -7,7 +7,7 @@ // Internals BOOL FileExists(LPCTSTR szPath); MODULEINFO GetModuleInfo(const char* szModule); -DWORD64 FindPattern(const char* szModule, const unsigned char* szPattern, const char* szMask); +std::uint8_t* PatternScan(const char* module, const char* signature); ///////////////////////////////////////////////////////////////////////////// // Utility diff --git a/r5dev/src/id3dx.cpp b/r5dev/src/id3dx.cpp index 17d41e83..4c819294 100644 --- a/r5dev/src/id3dx.cpp +++ b/r5dev/src/id3dx.cpp @@ -67,7 +67,7 @@ LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_KEYDOWN) { - if (wParam == VK_OEM_3) + if (wParam == VK_OEM_3 || wParam == VK_INSERT) // For everyone without a US keyboard layout. { g_bShowMenu = !g_bShowMenu; } diff --git a/r5dev/src/utility.cpp b/r5dev/src/utility.cpp index d808a77d..3eef7850 100644 --- a/r5dev/src/utility.cpp +++ b/r5dev/src/utility.cpp @@ -36,32 +36,68 @@ MODULEINFO GetModuleInfo(const char* szModule) /////////////////////////////////////////////////////////////////////////////// // For finding a byte pattern in memory of the game process -BOOL Compare(const unsigned char* pData, const unsigned char* szPattern, const char* szMask) -{ - for (; *szMask; ++szMask, ++pData, ++szPattern) - { - if (*szMask == 'x' && *pData != *szPattern) - { - return false; - } - } - return (*szMask) == NULL; -} -DWORD64 FindPattern(const char* szModule, const unsigned char* szPattern, const char* szMask) -{ - MODULEINFO mInfo = GetModuleInfo(szModule); - DWORD64 dwAddress = (DWORD64)mInfo.lpBaseOfDll; - DWORD64 dwLen = (DWORD64)mInfo.SizeOfImage; - size_t maskLen = strlen(szMask); - for (int i = 0; i < dwLen - maskLen; i++) +std::uint8_t* PatternScan(const char* module, const char* signature) +{ + static auto PatternToBytes = [](const char* pattern) { - if (Compare((unsigned char*)(dwAddress + i), szPattern, szMask)) + char* PatternStart = const_cast(pattern); // Cast const away and get start of pattern. + char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern. + + std::vector Bytes = std::vector{ }; // Initialize byte vector. + + for (char* CurrentByte = PatternStart; CurrentByte < PatternEnd; ++CurrentByte) { - return (DWORD64)(dwAddress + i); + if (*CurrentByte == '?') // Is current char(byte) a wildcard? + { + ++CurrentByte; // Skip 1 character. + + if (*CurrentByte == '?') // Is it a double wildcard pattern? + ++CurrentByte; // If so skip the next space that will come up so we can reach the next byte. + + Bytes.push_back(-1); // Push the byte back as invalid. + } + else + { + // https://stackoverflow.com/a/43860875/12541255 + // Here we convert our string to a unsigned long integer. We pass our string then we use 16 as the base because we want it as hexadecimal. + // Afterwards we push the byte into our bytes vector. + Bytes.push_back(std::strtoul(CurrentByte, &CurrentByte, 16)); + } } + return Bytes; + }; + + const MODULEINFO mInfo = GetModuleInfo(module); // Get module info. + const DWORD64 SizeOfModule = (DWORD64)mInfo.SizeOfImage; // Grab the module size. + std::uint8_t* ScanBytes = reinterpret_cast(mInfo.lpBaseOfDll); // Get the base of the module. + + const std::vector PatternBytes = PatternToBytes(signature); // Convert our pattern to a byte array. + const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes. + + for (DWORD i = 0ul; i < SizeOfModule - BytesInfo.first; ++i) + { + bool FoundAddress = true; + + for (DWORD j = 0ul; j < BytesInfo.first; ++j) + { + // If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard + // our if clause will be false. + if (ScanBytes[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1) + { + FoundAddress = false; + break; + } + } + + if (FoundAddress) + { + return &ScanBytes[i]; + } + } - return 0; + + return nullptr; } ///////////////////////////////////////////////////////////////////////////////