mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Merge pull request #12 from PixieCore/master
Added memory helper class.
This commit is contained in:
commit
0587c8f85c
270
r5dev/include/address.h
Normal file
270
r5dev/include/address.h
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class MemoryAddress
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Direction : int
|
||||||
|
{
|
||||||
|
UP = 0,
|
||||||
|
DOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uintptr_t GetPtr()
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress() = default;
|
||||||
|
MemoryAddress(std::uintptr_t ptr) : ptr(ptr) {}
|
||||||
|
MemoryAddress(void* ptr) : ptr(std::uintptr_t(ptr)) {}
|
||||||
|
|
||||||
|
operator std::uintptr_t() const
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator void*()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool()
|
||||||
|
{
|
||||||
|
return ptr != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const MemoryAddress& addr) const
|
||||||
|
{
|
||||||
|
return ptr != addr.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const MemoryAddress& addr) const
|
||||||
|
{
|
||||||
|
return ptr == addr.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const std::uintptr_t& addr) const
|
||||||
|
{
|
||||||
|
return ptr == addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T CCast()
|
||||||
|
{
|
||||||
|
return (T)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T RCast()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress Offset(std::ptrdiff_t offset)
|
||||||
|
{
|
||||||
|
return MemoryAddress(ptr + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress OffsetSelf(std::ptrdiff_t offset)
|
||||||
|
{
|
||||||
|
ptr += offset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress Deref(int deref = 1)
|
||||||
|
{
|
||||||
|
std::uintptr_t reference = ptr;
|
||||||
|
|
||||||
|
while (deref--)
|
||||||
|
{
|
||||||
|
if (reference)
|
||||||
|
reference = *reinterpret_cast<std::uintptr_t*>(reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MemoryAddress(reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress DerefSelf(int deref = 1)
|
||||||
|
{
|
||||||
|
while (deref--)
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
ptr = *reinterpret_cast<std::uintptr_t*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckOpCode(char opcode)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<char*>(ptr) == opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> T GetVirtualFunctionIndex()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<T*>(ptr) / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Patch(std::vector<byte> opcodes)
|
||||||
|
{
|
||||||
|
DWORD oldProt = NULL;
|
||||||
|
|
||||||
|
SIZE_T dwSize = opcodes.size();
|
||||||
|
VirtualProtect((void*)ptr, dwSize, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||||
|
|
||||||
|
for (int i = 0; i < opcodes.size(); i++)
|
||||||
|
{
|
||||||
|
*(byte*)(ptr + i) = opcodes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
dwSize = opcodes.size();
|
||||||
|
VirtualProtect((void*)ptr, dwSize, oldProt, &oldProt);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress FindPattern(const char* pattern, Direction searchDirect, int opCodesToScan = 100)
|
||||||
|
{
|
||||||
|
static auto PatternToBytes = [](const char* pattern)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uint8_t* ScanBytes = reinterpret_cast<std::uint8_t*>(ptr); // Get the base of the module.
|
||||||
|
|
||||||
|
const std::vector<int> PatternBytes = PatternToBytes(pattern); // 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 (auto i = 01; i < opCodesToScan + BytesInfo.first; ++i)
|
||||||
|
{
|
||||||
|
bool FoundAddress = true;
|
||||||
|
|
||||||
|
int memOffset = searchDirect == Direction::UP ? -i : i;
|
||||||
|
|
||||||
|
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[memOffset + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||||
|
{
|
||||||
|
FoundAddress = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FoundAddress)
|
||||||
|
{
|
||||||
|
return MemoryAddress(&ScanBytes[memOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return MemoryAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uintptr_t ptr = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Module() = default;
|
||||||
|
Module(std::string moduleName) : moduleName(moduleName)
|
||||||
|
{
|
||||||
|
const MODULEINFO mInfo = GetModuleInfo(moduleName.c_str()); // Get module info.
|
||||||
|
sizeOfModule = (DWORD64)mInfo.SizeOfImage; // Grab the module size.
|
||||||
|
moduleBase = (std::uintptr_t)mInfo.lpBaseOfDll; // Grab module base.
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAddress PatternSearch(const char* signature)
|
||||||
|
{
|
||||||
|
static auto PatternToBytes = [](const char* pattern)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uint8_t* ScanBytes = reinterpret_cast<std::uint8_t*>(moduleBase); // 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 MemoryAddress(&ScanBytes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MemoryAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uintptr_t GetModuleBase()
|
||||||
|
{
|
||||||
|
return moduleBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string moduleName = std::string();
|
||||||
|
std::uintptr_t moduleBase = 0;
|
||||||
|
DWORD64 sizeOfModule = 0;
|
||||||
|
};
|
@ -5,35 +5,47 @@ inline HANDLE GameProcess = GetCurrentProcess();
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/* -------------- ORIGIN ------------------------------------------------------------------------------------------------------------------------------------------------ */
|
Module r5_op = Module("r5apex.exe"); // Create module class instance.
|
||||||
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 ------------------------------------------------------------------------------------------------------------------------------------------------ */
|
#pragma region Origin
|
||||||
DWORD64 dst002 /*0x14043FB90*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 89 4C 24 08 56 41 55 48 81 EC 68 03 ? ? 4C"));
|
/*0x14032EEA0*/
|
||||||
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"));
|
MemoryAddress dst000 = r5_op.PatternSearch("48 83 EC 28 80 3D ? ? ? 23 ? 0F 85 ? 02 ?");
|
||||||
DWORD64 Host_NewGame /*0x140238DA0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 8B C4 ? 41 54 41 ? 48 81 EC ? ? ? ? F2"));
|
|
||||||
|
|
||||||
/* -------------- NETCHAN ----------------------------------------------------------------------------------------------------------------------------------------------- */
|
/*0x140330290*/
|
||||||
DWORD64 dst006 /*0x14030D000*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 55 57 41 55 41 57 48 8D AC 24 ? ? ? ?"));
|
MemoryAddress dst001 = r5_op.PatternSearch("48 81 EC 58 04 ? ? 80 3D ? ? ? ? ? 0F 84");
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
/* -------------- FAIRFIGHT --------------------------------------------------------------------------------------------------------------------------------------------- */
|
#pragma region Engine
|
||||||
DWORD64 dst007 /*0x140303AE0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6"));
|
/*0x14043FB90*/
|
||||||
|
MemoryAddress dst002 = r5_op.PatternSearch("48 89 4C 24 08 56 41 55 48 81 EC 68 03 ? ? 4C");
|
||||||
|
|
||||||
/* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */
|
/*0x14022A4A0*/
|
||||||
|
MemoryAddress dst004 = r5_op.PatternSearch("48 83 EC 38 0F 29 74 24 20 48 89 5C 24 40 48 8B");
|
||||||
|
|
||||||
|
/*0x140238DA0*/
|
||||||
|
MemoryAddress Host_NewGame = r5_op.PatternSearch("48 8B C4 ? 41 54 41 ? 48 81 EC ? ? ? ? F2");
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region NetChannel
|
||||||
|
/*0x14030D000*/
|
||||||
|
MemoryAddress dst006 = r5_op.PatternSearch("40 55 57 41 55 41 57 48 8D AC 24 ? ? ? ?");
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region FairFight
|
||||||
|
/*0x140303AE0*/
|
||||||
|
MemoryAddress dst007 = r5_op.PatternSearch("40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6");
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
void PrintOAddress() // Test the sigscan results
|
void PrintOAddress() // Test the sigscan results
|
||||||
{
|
{
|
||||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||||
std::cout << "| dst000 : " << std::hex << std::uppercase << dst000 << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("dst000", dst000.GetPtr());
|
||||||
std::cout << "| dst001 : " << std::hex << std::uppercase << dst001 << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("dst001", dst001.GetPtr());
|
||||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
PRINT_ADDRESS("dst002", dst002.GetPtr());
|
||||||
std::cout << "| dst002 : " << std::hex << std::uppercase << dst002 << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("dst004", dst004.GetPtr());
|
||||||
std::cout << "| dst004 : " << std::hex << std::uppercase << dst004 << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("Host_NewGame", Host_NewGame.GetPtr());
|
||||||
std::cout << "| Host_NewGame : " << std::hex << std::uppercase << Host_NewGame << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("dst006", dst006.GetPtr());
|
||||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
PRINT_ADDRESS("dst007", dst007.GetPtr());
|
||||||
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;
|
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||||
|
|
||||||
// TODO implement error handling when sigscan fails or result is 0
|
// TODO implement error handling when sigscan fails or result is 0
|
||||||
|
@ -3,78 +3,73 @@
|
|||||||
// Define the signatures or offsets to be searched and hooked
|
// Define the signatures or offsets to be searched and hooked
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
Module r5_patterns = Module("r5apex.exe"); // Create module class instance.
|
||||||
/* ==== CONSOLE ========================================================================================================================================================= */
|
|
||||||
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 (*org_CommandExecute)(void* self, const char* cmd) = (void (*)(void*, const char*))p_CommandExecute;
|
|
||||||
|
|
||||||
DWORD64 p_ConVar_IsFlagSet = /*0x14046FE90*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 8B 41 48 85 50 38"));
|
#pragma region Console
|
||||||
bool (*org_ConVar_IsFlagSet)(int** cvar, int flag) = (bool (*)(int**, int))p_ConVar_IsFlagSet;
|
/*0x140202090*/
|
||||||
|
FUNC_AT_ADDRESS(org_CommandExecute, void(*)(void*, const char*), r5_patterns.PatternSearch("48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 41 8B D8").GetPtr());
|
||||||
|
|
||||||
DWORD64 p_ConCommand_IsFlagSet = /*0x14046F490*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "85 51 38 0F 95 C0 C3"));
|
/*0x14046FE90*/
|
||||||
bool (*org_ConCommand_IsFlagSet)(int* cmd, int flag) = (bool (*)(int*, int))p_ConCommand_IsFlagSet;
|
FUNC_AT_ADDRESS(org_ConVar_IsFlagSet, bool(*)(int**, int), r5_patterns.PatternSearch("48 8B 41 48 85 50 38").GetPtr());
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/*0x14046F490*/
|
||||||
/* ==== SQUIRREL ======================================================================================================================================================== */
|
FUNC_AT_ADDRESS(org_ConCommand_IsFlagSet, bool(*)(int*, int), r5_patterns.PatternSearch("85 51 38 0F 95 C0 C3").GetPtr());
|
||||||
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"));
|
#pragma endregion
|
||||||
void* org_SQVM_Print = (void*)p_SQVM_Print;
|
|
||||||
|
#pragma region Squirrel
|
||||||
|
/*0x141057FD0*/
|
||||||
|
FUNC_AT_ADDRESS(org_SQVM_Print, void*, r5_patterns.PatternSearch("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_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\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 = /*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 (*org_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 = /*0x140C957E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "4C 8B DC 49 89 5B 08 57 48 81 EC A0 00 00 00 33"));
|
/*0x141055630*/
|
||||||
int (*org_SQVM_LoadRson)(const char* rson_name) = (int (*)(const char*))p_SQVM_LoadRson;
|
// For anything S2 and above (current S8
|
||||||
|
FUNC_AT_ADDRESS(org_SQVM_LoadScript, bool(*)(void*, const char*, const char*, int), r5_patterns.PatternSearch("48 8B C4 48 89 48 08 55 41 56 48 8D 68").GetPtr());
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/*0x140C957E0*/
|
||||||
/* ==== NETCHAN ========================================================================================================================================================= */
|
FUNC_AT_ADDRESS(org_SQVM_LoadRson, int(*)(const char*), r5_patterns.PatternSearch("4C 8B DC 49 89 5B 08 57 48 81 EC A0 00 00 00 33").GetPtr());
|
||||||
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"));
|
#pragma endregion
|
||||||
bool (*org_NET_ReceiveDatagram)(int, void*, bool) = (bool (*)(int, void*, bool))p_NET_ReceiveDatagram; /*E8 ?? ?? ?? ?? 84 C0 75 35 48 8B D3*/
|
|
||||||
|
|
||||||
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 ? ?"));
|
#pragma region NetChannel
|
||||||
int (*org_NET_SendDatagram)(SOCKET s, const char* buf, int len, int flags) = (int (*)(SOCKET, const char*, int, int))p_NET_SendDatagram;
|
/*0x1402655F0*/
|
||||||
|
FUNC_AT_ADDRESS(org_NET_ReceiveDatagram, bool(*)(int, void*, bool), r5_patterns.PatternSearch("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").GetPtr());
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/*0x1402662D0*/
|
||||||
/* ==== CHLCLIENT ======================================================================================================================================================= */
|
FUNC_AT_ADDRESS(org_NET_SendDatagram, int(*)(SOCKET, const char*, int, int), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ? 05 ? ?").GetPtr());
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
DWORD64 p_CHLClient_FrameStageNotify = /*0x1405C0740*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 83 EC 28 89 15 ?? ?? ?? ??"));
|
#pragma region CHLClient
|
||||||
void (*org_CHLClient_FrameStageNotify)(void* rcx, int curStage) = (void (*)(void*, int))p_CHLClient_FrameStageNotify;
|
/*0x1405C0740*/
|
||||||
|
FUNC_AT_ADDRESS(org_CHLClient_FrameStageNotify, void(*)(void* rcx, int curStage), r5_patterns.PatternSearch("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr());
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
#pragma region CVEngineServer
|
||||||
/* ==== CCLIENT ========================================================================================================================================================= */
|
/*0x140315CF0*/
|
||||||
DWORD64 p_CVEngineServer_IsPersistenceDataAvailable = /*0x140315CF0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "3B 15 ?? ?? ?? ?? 7D 33"));
|
FUNC_AT_ADDRESS(org_CVEngineServer_IsPersistenceDataAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr());
|
||||||
bool (*org_CVEngineServer_IsPersistenceDataAvailable)(__int64 thisptr /*Class thisptr usually CVEngineServer*/, int client) = (bool(*)(__int64, int))p_CVEngineServer_IsPersistenceDataAvailable;
|
#pragma endregion
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/* ==== UTILITY ========================================================================================================================================================= */
|
|
||||||
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 (*org_MSG_EngineError)(char* fmt, va_list args) = (int (*)(char*, va_list))p_MSG_EngineError;
|
|
||||||
|
|
||||||
|
#pragma region Utility
|
||||||
|
/*0x140295600*/
|
||||||
|
FUNC_AT_ADDRESS(org_MSG_EngineError, int(*)(char*, va_list), r5_patterns.PatternSearch("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").GetPtr());
|
||||||
|
#pragma endregion
|
||||||
// Un-used atm.
|
// Un-used atm.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/* ==== KEYVALUES ======================================================================================================================================================= */
|
|
||||||
// DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
|
// DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/* ==== ------- ========================================================================================================================================================= */
|
|
||||||
|
|
||||||
void PrintHAddress() // Test the sigscan results
|
void PrintHAddress() // Test the sigscan results
|
||||||
{
|
{
|
||||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||||
std::cout << "| CommandExecute : " << std::hex << std::uppercase << p_CommandExecute << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("CommandExecute", org_CommandExecute);
|
||||||
std::cout << "| ConVar_IsFlagSet : " << std::hex << std::uppercase << p_ConVar_IsFlagSet << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("ConVar_IsFlagSet", org_ConVar_IsFlagSet);
|
||||||
std::cout << "| ConCommand_IsFlagSet : " << std::hex << std::uppercase << p_ConCommand_IsFlagSet << std::setw(20) << " |" << std::endl;
|
PRINT_ADDRESS("ConCommand_IsFlagSet", org_ConCommand_IsFlagSet);
|
||||||
|
PRINT_ADDRESS("SQVM_Print", org_SQVM_Print);
|
||||||
|
PRINT_ADDRESS("SQVM_LoadScript", org_SQVM_LoadScript);
|
||||||
|
PRINT_ADDRESS("SQVM_LoadRson", org_SQVM_LoadRson);
|
||||||
|
PRINT_ADDRESS("NET_ReceiveDatagram", org_NET_ReceiveDatagram);
|
||||||
|
PRINT_ADDRESS("NET_SendDatagram ", org_NET_SendDatagram);
|
||||||
|
PRINT_ADDRESS("CHLClient::FrameStageNotify", org_CHLClient_FrameStageNotify);
|
||||||
|
PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", org_CVEngineServer_IsPersistenceDataAvailable);
|
||||||
|
PRINT_ADDRESS("MSG_EngineError", org_MSG_EngineError);
|
||||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
std::cout << "+--------------------------------------------------------+" << 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 << 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 << 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
|
// TODO implement error handling when sigscan fails or result is 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,12 @@
|
|||||||
#include "imgui_impl_win32.h"
|
#include "imgui_impl_win32.h"
|
||||||
#include "spdlog.h"
|
#include "spdlog.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
|
#include "address.h"
|
||||||
|
|
||||||
|
#define FUNC_AT_ADDRESS(name, funcbody, addr) \
|
||||||
|
using _##name = funcbody; \
|
||||||
|
_##name name = (funcbody)addr \
|
||||||
|
|
||||||
|
#define PRINT_ADDRESS(name, address) std::cout << name << ": " << std::hex << std::uppercase << address << std::endl;
|
@ -160,11 +160,11 @@ bool HCVEngineClient_IsPersistenceDataAvailable(__int64 thisptr, int client)
|
|||||||
static bool isPersistenceVarSet[256];
|
static bool isPersistenceVarSet[256];
|
||||||
|
|
||||||
// TODO: Maybe not hardcode
|
// TODO: Maybe not hardcode
|
||||||
DWORD64 playerStructBase = 0x16073B200;
|
std::uintptr_t playerStructBase = 0x16073B200;
|
||||||
DWORD64 playerStructSize = 0x4A4C0;
|
std::uintptr_t playerStructSize = 0x4A4C0;
|
||||||
DWORD64 persistenceVar = 0x5BC;
|
std::uintptr_t persistenceVar = 0x5BC;
|
||||||
|
|
||||||
DWORD64 targetPlayerStruct = playerStructBase + client * playerStructSize;
|
std::uintptr_t targetPlayerStruct = playerStructBase + client * playerStructSize;
|
||||||
|
|
||||||
*(char*)(targetPlayerStruct + persistenceVar) = (char)0x5;
|
*(char*)(targetPlayerStruct + persistenceVar) = (char)0x5;
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||||||
g_bShowConsole = !g_bShowConsole;
|
g_bShowConsole = !g_bShowConsole;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uMsg == WM_SYSKEYDOWN)
|
if (uMsg == WM_SYSKEYDOWN)
|
||||||
{
|
{
|
||||||
if (wParam == VK_F10)
|
if (wParam == VK_F10)
|
||||||
@ -70,6 +71,7 @@ LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||||||
g_bShowBrowser = !g_bShowBrowser;
|
g_bShowBrowser = !g_bShowBrowser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_bShowConsole || g_bShowBrowser)
|
if (g_bShowConsole || g_bShowBrowser)
|
||||||
{//////////////////////////////////////////////////////////////////////////////
|
{//////////////////////////////////////////////////////////////////////////////
|
||||||
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
||||||
|
@ -11,19 +11,22 @@ void InstallOpcodes() /* .TEXT */
|
|||||||
// JNZ --> JMP | Prevent OriginSDK from initializing on the client
|
// JNZ --> JMP | Prevent OriginSDK from initializing on the client
|
||||||
//WriteProcessMemory(GameProcess, LPVOID(dst000 + 0x0B), "\xE9\x63\x02\x00\x00\x00", 6, NULL);
|
//WriteProcessMemory(GameProcess, LPVOID(dst000 + 0x0B), "\xE9\x63\x02\x00\x00\x00", 6, NULL);
|
||||||
//WriteProcessMemory(GameProcess, LPVOID(dst001 + 0x0E), "\xE9\xCB\x03\x00\x00", 5, NULL);
|
//WriteProcessMemory(GameProcess, LPVOID(dst001 + 0x0E), "\xE9\xCB\x03\x00\x00", 5, NULL);
|
||||||
|
//dst000.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
|
||||||
|
//dst001.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 });
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// JNE --> JMP | Allow games to be loaded without the optional texture streaming file
|
// JNE --> JMP | Allow games to be loaded without the optional texture streaming file
|
||||||
WriteProcessMemory(GameProcess, LPVOID(dst002 + 0x8E5), "\xEB\x19", 2, NULL);
|
dst002.Offset(0x8E5).Patch({ 0xEB, 0x19 });
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// JNE --> JMP | Prevent connect command from crashing by invalid call to UI function
|
// JNE --> JMP | Prevent connect command from crashing by invalid call to UI function
|
||||||
WriteProcessMemory(GameProcess, LPVOID(dst004 + 0x1D6), "\xEB\x27", 2, NULL);
|
dst004.Offset(0x1D6).Patch({ 0xEB, 0x27 });
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// JNE --> JMP | Prevent connect localhost from being executed after listenserver init
|
// JNE --> JMP | Prevent connect localhost from being executed after listenserver init
|
||||||
//WriteProcessMemory(GameProcess, LPVOID(Host_NewGame + 0x637), "\xE9\xC1\x00\x00\x00", 5, NULL);
|
//WriteProcessMemory(GameProcess, LPVOID(Host_NewGame + 0x637), "\xE9\xC1\x00\x00\x00", 5, NULL);
|
||||||
|
//Host_NewGame.Offset(0x637).Patch({ 0xE9, 0xC1, 0x00, 0x00, 0x00});
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// JA --> JMP | Disable server-side verification for duplicate accounts on the server
|
// JA --> JMP | Disable server-side verification for duplicate accounts on the server
|
||||||
WriteProcessMemory(GameProcess, LPVOID(dst006 + 0x284), "\x90\x90", 2, NULL);
|
dst006.Offset(0x284).Patch({ 0x90, 0x90 });
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server
|
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server
|
||||||
WriteProcessMemory(GameProcess, LPVOID(dst007 + 0x61), "\xE9\xED\x00\x00\x00\x00", 6, NULL);
|
dst007.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 });
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user