Merge pull request #4 from PixieCore/master

Updated PatternScan and added more gameclasses.
This commit is contained in:
Amos 2021-07-17 01:28:07 -07:00 committed by GitHub
commit 4a4af50039
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 314 additions and 70 deletions

View File

@ -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<OriginalFn**>(this))[10](this, bEnabled); // EnableInput is virtual function index 10 in the CInputSystem virtual table.
(*reinterpret_cast<OriginalFn**>(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<OriginalFn**>(this))[11](this, bEnabled); // EnableMessagePump is virtual function index 11 in the CInputSystem virtual table.
(*reinterpret_cast<OriginalFn**>(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<OriginalFn**>(this))[13](this, Button); // IsButtonDown is virtual function index 13 in the CInputSystem virtual table.
return (*reinterpret_cast<OriginalFn**>(this))[13](this, Button);
}
private:
@ -247,3 +248,205 @@ 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<OriginalFn**>(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<OriginalFn**>(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<OriginalFn**>(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<OriginalFn**>(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<OriginalFn**>(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<void*>(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<OriginalFn**>(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<OriginalFn**>(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<OriginalFn**>(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<KeyValues*(__thiscall*)(KeyValues*, const char*, bool)>(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<int>(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;
};

View File

@ -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<DWORD64>(PatternScan("r5apex.exe", "48 83 EC 28 80 3D ? ? ? 23 ? 0F 85 ? 02 ?"));
DWORD64 dst001 /*0x140330290*/ = reinterpret_cast<DWORD64>(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<DWORD64>(PatternScan("r5apex.exe", "48 89 4C 24 08 56 41 55 48 81 EC 68 03 ? ? 4C"));
DWORD64 dst003 /*0x140302FF0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74"));
DWORD64 dst004 /*0x14022A4A0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 83 EC 38 0F 29 74 24 20 48 89 5C 24 40 48 8B"));
DWORD64 dst005 /*0x140238DA0*/ = reinterpret_cast<DWORD64>(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<DWORD64>(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<DWORD64>(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

View File

@ -9,39 +9,44 @@ 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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(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<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* ==== ------- ========================================================================================================================================================= */
@ -49,18 +54,18 @@ namespace
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

View File

@ -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

View File

@ -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;
}

View File

@ -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<char*>(pattern); // Cast const away and get start of pattern.
char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern.
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // 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 0;
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<std::uint8_t*>(mInfo.lpBaseOfDll); // Get the base of the module.
const std::vector<int> 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 nullptr;
}
///////////////////////////////////////////////////////////////////////////////