Merge pull request #12 from PixieCore/master

Added memory helper class.
This commit is contained in:
PixieCore 2021-07-20 23:36:48 +02:00 committed by GitHub
commit 0587c8f85c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 373 additions and 83 deletions

270
r5dev/include/address.h Normal file
View 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;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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