From 850bbc19ef41672fe493998c8001e37d566e760f Mon Sep 17 00:00:00 2001 From: Amos Date: Tue, 8 Jun 2021 10:54:49 -0700 Subject: [PATCH] Code refactor + improvents * Move all utilities to single implementation file * Remove unnecessary code in .cpp and .h * Patch opcodes in runtime instead of patching raw PE file * Move launch parameters to cfg folder instead * Move back to pattern scan instead of hardcoded offsets * Change langauge to new ISO C++17 standard --- r5dev/console.cpp | 45 +++++++----- r5dev/console.h | 8 +- r5dev/dllmain.cpp | 17 +++-- r5dev/hooks.cpp | 44 ++++------- r5dev/hooks.h | 3 +- r5dev/opcptc.cpp | 27 +++++++ r5dev/opcptc.h | 36 +++++++++ r5dev/patterns.h | 99 ++++++++++--------------- r5dev/r5dev.h | 2 +- r5dev/r5dev.vcxproj | 24 ++++-- r5dev/r5dev.vcxproj.filters | 16 ++-- r5dev/sigscan.h | 43 ----------- r5dev/structs.h | 2 +- r5dev/utilities.h | 84 --------------------- r5dev/utility.cpp | 133 ++++++++++++++++++++++++++++++++++ r5dev/utility.h | 10 +++ r5launcher/main.cpp | 2 +- r5launcher/r5launcher.vcxproj | 18 ++++- 18 files changed, 352 insertions(+), 261 deletions(-) create mode 100644 r5dev/opcptc.cpp create mode 100644 r5dev/opcptc.h delete mode 100644 r5dev/sigscan.h delete mode 100644 r5dev/utilities.h create mode 100644 r5dev/utility.cpp create mode 100644 r5dev/utility.h diff --git a/r5dev/console.cpp b/r5dev/console.cpp index 3e17cac8..89ff38c2 100644 --- a/r5dev/console.cpp +++ b/r5dev/console.cpp @@ -1,15 +1,17 @@ #include -#include #include +#include #include #include #include "hooks.h" +#include "opcptc.h" +#include "console.h" #include "patterns.h" //--------------------------------------------------------------------------------- -// Console Init +// Init //--------------------------------------------------------------------------------- void SetupConsole() @@ -25,6 +27,7 @@ void SetupConsole() FILE* sBuildTxt; CHAR sBuildBuf[1024] = { 0 }; fopen_s(&sBuildTxt, "build.txt", "r"); + if (sBuildTxt) { while (fgets(sBuildBuf, sizeof(sBuildBuf), sBuildTxt) != NULL) @@ -41,29 +44,27 @@ void SetupConsole() freopen_s(&fDummy, "CONOUT$", "w", stderr); // Create a worker thread to process console commands - DWORD threadId; + DWORD threadId0; DWORD __stdcall ProcessConsoleWorker(LPVOID); - HANDLE hThread = CreateThread(NULL, 0, ProcessConsoleWorker, NULL, 0, &threadId); + HANDLE hThread0 = CreateThread(NULL, 0, ProcessConsoleWorker, NULL, 0, &threadId0); - if (hThread) + if (hThread0) { - printf("THREAD ID: %ld\n\n", threadId); - CloseHandle(hThread); + printf("THREAD ID: %ld\n\n", threadId0); + CloseHandle(hThread0); } } //--------------------------------------------------------------------------------- -// Console Hooks +// Hooks //--------------------------------------------------------------------------------- -static bool g_bDebugConsole = true; -static bool g_bToggleAll = false; bool Hook_ConVar_IsFlagSet(int** cvar, int flag) { int real_flags = *(*(cvar + (72 / (sizeof(void*)))) + (56 / sizeof(int))); if (g_bDebugConsole) { - printf("----------------------------------------------\n"); + printf("--------------------------------------------------\n"); printf(" Flaged: %08X\n", real_flags); } // Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY @@ -72,11 +73,11 @@ bool Hook_ConVar_IsFlagSet(int** cvar, int flag) { printf(" Masked: %08X\n", real_flags); printf(" Verify: %08X\n", flag); - printf("----------------------------------------------\n"); + printf("--------------------------------------------------\n"); } if (flag & 0x80000) { return true; } - if (!g_bToggleAll) { return (real_flags & flag) != 0; } + if (!g_bReturnAllFalse) { return (real_flags & flag) != 0; } else { return false; } } @@ -85,7 +86,7 @@ bool Hook_ConCommand_IsFlagSet(int* cmd, int flag) int real_flags = *((cmd + (56 / sizeof(int)))); if (g_bDebugConsole) { - printf("----------------------------------------------\n"); + printf("--------------------------------------------------\n"); printf(" Flaged: %08X\n", real_flags); } // Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY @@ -94,16 +95,16 @@ bool Hook_ConCommand_IsFlagSet(int* cmd, int flag) { printf(" Masked: %08X\n", real_flags); printf(" Verify: %08X\n", flag); - printf("----------------------------------------------\n"); + printf("--------------------------------------------------\n"); } if (flag & 0x80000) { return true; } - if (!g_bToggleAll) { return (real_flags & flag) != 0; } + if (!g_bReturnAllFalse) { return (real_flags & flag) != 0; } else { return false; } } //--------------------------------------------------------------------------------- -// Console Worker +// Worker //--------------------------------------------------------------------------------- DWORD __stdcall ProcessConsoleWorker(LPVOID) @@ -120,12 +121,16 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) // Engine toggles if (sCommand == "toggle net") { ToggleNetHooks(); continue; } if (sCommand == "toggle dev") { ToggleDevCommands(); continue; } - if (sCommand == "toggle all") { g_bToggleAll = !g_bToggleAll; continue; } + if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } // Debug toggles - if (sCommand == "pattern test") { PrintHAddress(); continue; } + if (sCommand == "pattern test") { PrintHAddress(); PrintOAddress(); continue; } if (sCommand == "console test") { g_bDebugConsole = !g_bDebugConsole; continue; } + // Exec toggles + if (sCommand == "1") { ToggleDevCommands(); CommandExecute(NULL, "exec autoexec_dev"); } + if (sCommand == "2") { g_bDebugLog = !g_bDebugLog; continue; } + // Execute the command in the r5 SQVM CommandExecute(NULL, sCommand.c_str()); sCommand.clear(); @@ -135,4 +140,4 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) } return 0; -} \ No newline at end of file +} diff --git a/r5dev/console.h b/r5dev/console.h index 1c219758..92fd203d 100644 --- a/r5dev/console.h +++ b/r5dev/console.h @@ -1,3 +1,9 @@ #pragma once -void SetupConsole(); \ No newline at end of file +void SetupConsole(); + +bool Hook_ConVar_IsFlagSet(int** cvar, int flag); +bool Hook_ConCommand_IsFlagSet(int* cmd, int flag); + +inline bool g_bDebugConsole = false; +inline bool g_bReturnAllFalse = false; diff --git a/r5dev/dllmain.cpp b/r5dev/dllmain.cpp index 405e4c91..c9a4c6c6 100644 --- a/r5dev/dllmain.cpp +++ b/r5dev/dllmain.cpp @@ -1,22 +1,25 @@ -#include #include +#include #include "r5dev.h" -#include "console.h" -#include "utilities.h" #include "hooks.h" +#include "opcptc.h" +#include "console.h" +#include "utility.h" //--------------------------------------------------------------------------------- -// Main +// Init //--------------------------------------------------------------------------------- void InitializeR5Dev() { SetupConsole(); InstallHooks(); + InstallOpcodes(); printf("+-----------------------------------------------------------------------------+\n"); printf("| R5 DEV -- INITIALIZED ------------------------------------------------- |\n"); printf("+-----------------------------------------------------------------------------+\n"); + printf("\n"); } void TerminateR5Dev() @@ -25,6 +28,10 @@ void TerminateR5Dev() FreeConsole(); } +//--------------------------------------------------------------------------------- +// Main +//--------------------------------------------------------------------------------- + BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { @@ -44,4 +51,4 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) } return TRUE; -} \ No newline at end of file +} diff --git a/r5dev/hooks.cpp b/r5dev/hooks.cpp index e2dd3593..10fcbce8 100644 --- a/r5dev/hooks.cpp +++ b/r5dev/hooks.cpp @@ -4,13 +4,14 @@ #include #include -#include "utilities.h" -#include "hooks.h" #include "patterns.h" +#include "utility.h" #include "structs.h" +#include "console.h" +#include "hooks.h" //--------------------------------------------------------------------------------- -// Netchan Hooks +// Netchan //--------------------------------------------------------------------------------- bool Hook_NET_ReceiveDatagram(int sock, void* inpacket, bool raw) @@ -41,7 +42,7 @@ unsigned int Hook_NET_SendDatagram(SOCKET s, const char* buf, int len, int flags } //--------------------------------------------------------------------------------- -// SquirrelVM Hooks +// SQVM //--------------------------------------------------------------------------------- void* Hook_SQVM_Print(void* sqvm, char* fmt, ...) @@ -58,7 +59,7 @@ bool Hook_SQVM_LoadScript(void* sqvm, const char* script_path, const char* scrip char filepath[MAX_PATH] = { 0 }; sprintf_s(filepath, MAX_PATH, "platform\\%s", script_path); - // Flip forward slashes in filepath to windows-style backslash + // Flip forward slashes in filepath to windows-style backslash for (int i = 0; i < strlen(filepath); i++) { if (filepath[i] == '/') @@ -67,27 +68,18 @@ bool Hook_SQVM_LoadScript(void* sqvm, const char* script_path, const char* scrip } } - printf(" [+] Loading SQVM Script '%s' ...\n", filepath); + if (g_bDebugLog) { printf(" [+] Loading SQVM Script '%s' ...\n", filepath); } if (FileExists(filepath) && SQVM_LoadScript(sqvm, filepath, script_name, flag)) { return true; // Redirect to disk worked / script exists on disk.. } - - printf(" [!] FAILED, loading from SearchPath / VPK...\n"); + + if (g_bDebugLog) { printf(" [!] FAILED. Try SP / VPK for '%s'\n", filepath); } return SQVM_LoadScript(sqvm, script_path, script_name, flag); } //--------------------------------------------------------------------------------- -// Origin Hooks -//--------------------------------------------------------------------------------- - -unsigned int Hook_OriginScript(int value) -{ - return true; -} - -//--------------------------------------------------------------------------------- -// Hook Management +// Management //--------------------------------------------------------------------------------- void InstallHooks() @@ -99,11 +91,6 @@ void InstallHooks() // Hook Engine functions DetourAttach((LPVOID*)&SQVM_Print, &Hook_SQVM_Print); DetourAttach((LPVOID*)&SQVM_LoadScript, &Hook_SQVM_LoadScript); - // Hook Origin functions - DetourAttach((LPVOID*)&Origin_IsEnabled, &Hook_OriginScript); - DetourAttach((LPVOID*)&Origin_IsUpToDate, &Hook_OriginScript); - DetourAttach((LPVOID*)&Origin_IsOnline, &Hook_OriginScript); - DetourAttach((LPVOID*)&Origin_IsReady, &Hook_OriginScript); // Commit the transaction if (DetourTransactionCommit() != NO_ERROR) @@ -128,16 +115,15 @@ void RemoveHooks() // Unhook Console functions DetourDetach((LPVOID*)&ConVar_IsFlagSet, &Hook_ConVar_IsFlagSet); DetourDetach((LPVOID*)&ConCommand_IsFlagSet, &Hook_ConCommand_IsFlagSet); - // Unhook Origin functions - DetourDetach((LPVOID*)&Origin_IsEnabled, &Hook_OriginScript); - DetourDetach((LPVOID*)&Origin_IsUpToDate, &Hook_OriginScript); - DetourDetach((LPVOID*)&Origin_IsOnline, &Hook_OriginScript); - DetourDetach((LPVOID*)&Origin_IsReady, &Hook_OriginScript); // Commit the transaction DetourTransactionCommit(); } +//--------------------------------------------------------------------------------- +// Toggles +//--------------------------------------------------------------------------------- + void ToggleNetHooks() { static bool g_net = false; @@ -209,4 +195,4 @@ void ToggleDevCommands() } g_dev = !g_dev; -} \ No newline at end of file +} diff --git a/r5dev/hooks.h b/r5dev/hooks.h index 9ab28963..b08aaa25 100644 --- a/r5dev/hooks.h +++ b/r5dev/hooks.h @@ -5,5 +5,4 @@ void RemoveHooks(); void ToggleDevCommands(); void ToggleNetHooks(); -bool Hook_ConVar_IsFlagSet(int** cvar, int flag); -bool Hook_ConCommand_IsFlagSet(int* cmd, int flag); \ No newline at end of file +inline bool g_bDebugLog = false; diff --git a/r5dev/opcptc.cpp b/r5dev/opcptc.cpp new file mode 100644 index 00000000..d684840c --- /dev/null +++ b/r5dev/opcptc.cpp @@ -0,0 +1,27 @@ +#include "windows.h" +#include "opcptc.h" + +/*----------------------------------------------------------------------------- + * opcptc.cpp + *-----------------------------------------------------------------------------*/ + +void InstallOpcodes() +{ + HANDLE GameProcess = GetCurrentProcess(); + // JNZ --> JMP | Prevent OriginSDK from initializing on the client + //WriteProcessMemory(GetCurrentProcess(), LPVOID(dst000 + 0x0B), "\xE9\x63\x02\x00\x00\x00", 6, NULL); + + // JE --> NOP | Allow execution of map commands even if the OriginSDK is not running + WriteProcessMemory(GameProcess, LPVOID(dst001 + 0x2B), "\x90\x90\x90\x90\x90\x90", 6, NULL); + WriteProcessMemory(GameProcess, LPVOID(dst001 + 0x39), "\x90\x90\x90\x90\x90\x90", 6, NULL); + WriteProcessMemory(GameProcess, LPVOID(dst001 + 0x46), "\x90\x90\x90\x90\x90\x90", 6, NULL); + + // JL --> NOP | Enable clientcommand callbacks without persistent player data + WriteProcessMemory(GameProcess, LPVOID(dst002 + 0x76), "\x90\x90", 2, NULL); + + // JA --> JMP | Disable client-side verification for duplicate accounts on the server + WriteProcessMemory(GameProcess, LPVOID(dst003 + 0x269), "\xEB\x39", 2, NULL); + + // JA --> JMP | Prevent FairFight anti-cheat from initializing on the server + WriteProcessMemory(GameProcess, LPVOID(dst004 + 0x72), "\xE9\xE4\x00\x00\x00\x00", 6, NULL); +} diff --git a/r5dev/opcptc.h b/r5dev/opcptc.h new file mode 100644 index 00000000..ef9a155f --- /dev/null +++ b/r5dev/opcptc.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include "utility.h" + +void InstallOpcodes(); + +namespace +{ + /* -------------- ORIGIN ------------------------------------------------------------------------------------------------------------------------------------------------ */ + DWORD64 dst000 = /*0x14032C910*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x83\xEC\x28\x80\x3D\x00\x00\x00\x22\x00\x0F\x85\x00\x02\x00", "xxxxxx???xxxx?xx"); + DWORD64 dst001 = /*0x14023C440*/ FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x18\x55\x41\x56\x41\x57\x48\x81\xEC\x40\x02\x00", "xxxxxxxxxxxxxxxx"); + + /* -------------- ENGINE ------------------------------------------------------------------------------------------------------------------------------------------------ */ + DWORD64 dst002 = /*0x140E3E110*/ FindPattern("r5apex.exe", (const unsigned char*)"\x41\x56\x41\x57\x48\x81\xEC\x00\x00\x00\x00\x4C\x8B\xF2\x4C\x8B", "xxxxxxx????xxxxx"); + + /* -------------- NETCHAN ----------------------------------------------------------------------------------------------------------------------------------------------- */ + DWORD64 dst003 = /*0x14030BEF0*/ FindPattern("r5apex.exe", (const unsigned char*)"\x44\x89\x44\x24\x18\x55\x56\x57\x48\x8D\xAC\x24\x60\xFF\xFF\xFF", "xxxxxxxxxxxxxxxx"); + + /* -------------- FAIRFIGHT --------------------------------------------------------------------------------------------------------------------------------------------- */ + DWORD64 dst004 = /*0x140302D90*/ FindPattern("r5apex.exe", (const unsigned char*)"\x40\x53\x57\x41\x57\x48\x83\xEC\x30\x8B\x81\xB0\x03\x00\x00\x48", "xxxxxxxxxxxxxxxx"); + + /* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */ + + void PrintOAddress() // Test the sigscan results + { + std::cout << "--------------------------------------------------" << std::endl; + std::cout << " dst000 : " << std::hex << dst000 << std::endl; + std::cout << " dst001 : " << std::hex << dst001 << std::endl; + std::cout << " dst002 : " << std::hex << dst001 << std::endl; + std::cout << " dst003 : " << std::hex << dst003 << std::endl; + std::cout << " dst004 : " << std::hex << dst004 << std::endl; + std::cout << "--------------------------------------------------" << std::endl; + + // TODO implement error handling when sigscan fails or result is 0 + } +} diff --git a/r5dev/patterns.h b/r5dev/patterns.h index 2614671f..df493641 100644 --- a/r5dev/patterns.h +++ b/r5dev/patterns.h @@ -1,81 +1,62 @@ #pragma once #include -#include "sigscan.h" +#include "utility.h" // Define the signatures or offsets to be searched and hooked namespace { - CSigScan Scanner; + /* ==== 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*/ - /* =========================================================== CONSOLE =========================================================== */ - LONGLONG p_CommandExecute = 0x1402463E0;//Scanner.FindPattern("r5apex.exe", "\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;//p_CommandExecute; /*48 89 5C 24 ?? 57 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 41 8B D8*/ + 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*/ - LONGLONG p_ConVar_IsFlagSet = 0x1404D5490;//Scanner.FindPattern("r5apex.exe", "\x48\x8B\x41\x48\x85\x50\x38", "xxxxxxx"); - bool (*ConVar_IsFlagSet)(int** cvar, int flag) = (bool (*)(int**, int))p_ConVar_IsFlagSet;//p_ConVar_IsFlagSet; /*48 8B 41 48 85 50 38*/ + 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*/ - LONGLONG p_ConCommand_IsFlagSet = 0x1404D4AC0;//Scanner.FindPattern("r5apex.exe", "\x85\x51\x38\x0F\x95\xC0\xC3", "xxxxxxx"); - bool (*ConCommand_IsFlagSet)(int* cmd, int flag) = (bool (*)(int*, int))p_ConCommand_IsFlagSet;// p_ConCommand_IsFlagSet; /*85 51 38 0F 95 C0 C3*/ + /* ==== 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*/ - /* =========================================================== SQUIRREL ========================================================== */ - LONGLONG p_SQVM_Print = 0x1410C3760;//Scanner.FindPattern("r5apex.exe", "\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;// 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_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", "\x48\x8B\xC4\x48\x89\x48\x08\x55\x41\x56\x48\x8D\x68", "xxxxxxxxxxxxx"); // 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 ?? ?? ?? ??*/ - LONGLONG p_SQVM_LoadScript = 0x1410C0940;//Scanner.FindPattern("r5apex.exe", "\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 - //LONGLONG p_SQVM_LoadScript = Scanner.FindPattern("r5apex.exe", "\x48\x8B\xC4\x48\x89\x48\x08\x55\x41\x56\x48\x8D\x68", "xxxxxxxxxxxxx"); // 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;//p_SQVM_LoadScript; /*E8 ?? ?? ?? ?? 84 C0 74 1C 41 B9 ?? ?? ?? ??*/ + /* ==== 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"); + bool (*NET_ReceiveDatagram)(int, void*, bool) = (bool (*)(int, void*, bool))p_NET_ReceiveDatagram; /*E8 ?? ?? ?? ?? 84 C0 75 35 48 8B D3*/ - /* =========================================================== NETCHAN =========================================================== */ - LONGLONG p_NET_ReceiveDatagram = 0x1402B61F0;//Scanner.FindPattern("r5apex.exe", "\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"); - bool (*NET_ReceiveDatagram)(int, void*, bool) = (bool (*)(int, void*, bool))p_NET_ReceiveDatagram;//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"); + unsigned int (*NET_SendDatagram)(SOCKET s, const char* buf, int len, int flags) = (unsigned 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*/ - LONGLONG p_NET_SendDatagram = 0x1402B6E70;//Scanner.FindPattern("r5apex.exe", "\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"); - unsigned int (*NET_SendDatagram)(SOCKET s, const char* buf, int len, int flags) = (unsigned int (*)(SOCKET, const char*, int, int))p_NET_SendDatagram;// 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*/ + /* ==== WINAPI ========================================================================================================================================================== */ + DWORD64 p_SetCursorPosition = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x85\xD2\x0F\x00\x00\x00\x00\x00\x48\x89\x6C\x24\x00\x56\x48\x83\xEC\x40\x4C", "xxxx?????xxxx?xxxxxx"); // Uncomment for anything that is not between S1 build 525 and S4 build 856 + //DWORD64 p_SetCursorPosition = FindPattern("r5apex.exe", "\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x48\x83\xEC\x40\x48\x8B\xF9", "xxxxxxxxxxxxxxxxxx"); // Uncomment for anything that is between S1 build 525 and S4 build 856 + void (*SetCursorPosition)(int a1, INT64 posX, INT64 posY) = (void (*)(int, INT64, INT64))p_SetCursorPosition; /*48 85 D2 0F ?? ?? ?? ?? ?? 48 89 6C 24 ?? 56 48 83 EC 40 4C*/ - /* =========================================================== WINAPI ============================================================ */ - LONGLONG p_SetCursorPosition = 0x1403FD100;//Scanner.FindPattern("r5apex.exe", "\x48\x85\xD2\x0F\x00\x00\x00\x00\x00\x48\x89\x6C\x24\x00\x56\x48\x83\xEC\x40\x4C", "xxxx?????xxxx?xxxxxx"); // TODO: This does not exist in anything between S1 build 525 and S4 build 856 - void (*SetCursorPosition)(int a1, int a2, unsigned int posX, unsigned int posY) = (void (*)(int, int, unsigned int, unsigned int))p_SetCursorPosition;// p_SetCursorPosition; /*48 85 D2 0F ?? ?? ?? ?? ?? 48 89 6C 24 ?? 56 48 83 EC 40 4C*/ - - //LONGLONG p_GameWindowProc = 0x1403F3C50; //Scanner.FindPattern("r5apex.exe", "\x48\x89\x4C\x24\x00\x56\x41\x54\x41\x56\x41\x57\x48\x83\xEC\x48", "xxxx?xxxxxxxxxxx"); + //DWORD64 p_GameWindowProc = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x4C\x24\x00\x56\x41\x54\x41\x56\x41\x57\x48\x83\xEC\x48", "xxxx?xxxxxxxxxxx"); //unsigned int (*GameWindowProc)(int game, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = (unsigned int (*)(int, HWND, UINT, WPARAM, LPARAM))p_GameWindowProc; /*48 89 4C 24 ?? 56 41 54 41 56 41 57 48 83 EC 48*/ - /* =========================================================== ORIGIN ============================================================ */ - LONGLONG p_Origin_IsEnabled = 0x1408CD820;//Scanner.FindPattern("r5apex.exe", "\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\xE8\x00\x00\x00\x00\x33\xC9", "xxxxxxxxxx????xx"); - unsigned int (*Origin_IsEnabled) (int value) = (unsigned int (*)(int))p_Origin_IsEnabled;// p_Origin_IsEnabled; //0x1406CC150; - - LONGLONG p_Origin_IsUpToDate = 0x1408CD770;//Scanner.FindPattern("r5apex.exe", "\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\xE8\x00\x00\x00\x00\x8B\x4B\x68", "xxxxxxxxxx????xxx");; - unsigned int (*Origin_IsUpToDate) (int value) = (unsigned int (*)(int))p_Origin_IsUpToDate;//p_Origin_IsUpToDate; //0x1406CC0C0; - - LONGLONG p_Origin_IsOnline = 0x1408CD6D0;//Scanner.FindPattern("r5apex.exe", "\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\xE8\x00\x00\x00\x00\x84\xC0\x74\x07", "xxxxxxxxxx????xxxx");; - unsigned int (*Origin_IsOnline) (int value) = (unsigned int (*)(int))p_Origin_IsOnline;// p_Origin_IsOnline; //0x1406CC010; - - LONGLONG p_Origin_IsReady = 0x1408CD5F0;//Scanner.FindPattern("r5apex.exe", "\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\xE8\x00\x00\x00\x00\x84\xC0\x74\x47", "xxxxxxxxxx????xxxx");; - unsigned int (*Origin_IsReady) (int value) = (unsigned int (*)(int))p_Origin_IsReady; //p_Origin_IsReady; //0x1406CBF50; - - /* =========================================================== ------- =========================================================== */ + /* ==== ------- ========================================================================================================================================================= */ void PrintHAddress() // Test the sigscan results { - std::cout << "----------------------------------------------" << std::endl; - std::cout << " CommandExecute : " << std::hex << p_CommandExecute << std::endl; - std::cout << " ConCommandFlag : " << std::hex << p_ConVar_IsFlagSet << std::endl; - std::cout << " ConVarFlag : " << std::hex << p_ConCommand_IsFlagSet << std::endl; - std::cout << "----------------------------------------------" << std::endl; - std::cout << " SquirrelVMPrint : " << std::hex << p_SQVM_Print << std::endl; - std::cout << " SquirrelVMScript : " << std::hex << p_SQVM_LoadScript << std::endl; - std::cout << "----------------------------------------------" << std::endl; - std::cout << " NetReceiveDatagram : " << std::hex << p_NET_ReceiveDatagram << std::endl; - std::cout << " NetSendDatagram : " << std::hex << p_NET_SendDatagram << std::endl; - std::cout << "----------------------------------------------" << std::endl; - std::cout << " SetCursorPosition : " << std::hex << p_SetCursorPosition << std::endl; - //std::cout << " GameWindowProc : " << std::hex << p_GameWindowProc << std::endl; - std::cout << "----------------------------------------------" << std::endl; - std::cout << " OriginIsEnabled : " << std::hex << p_Origin_IsEnabled << std::endl; - std::cout << " OriginIsUpdate : " << std::hex << p_Origin_IsUpToDate << std::endl; - std::cout << " OriginIsOnline : " << std::hex << p_Origin_IsOnline << std::endl; - std::cout << " OriginIsReady : " << std::hex << p_Origin_IsReady << std::endl; - std::cout << "----------------------------------------------" << std::endl; + std::cout << "--------------------------------------------------" << std::endl; + std::cout << " p_CommandExecute : " << std::hex << p_CommandExecute << std::endl; + std::cout << " p_ConVar_IsFlagSet : " << std::hex << p_ConVar_IsFlagSet << std::endl; + std::cout << " p_ConCommand_IsFlagSet : " << std::hex << p_ConCommand_IsFlagSet << std::endl; + std::cout << "--------------------------------------------------" << std::endl; + std::cout << " p_SQVM_Print : " << std::hex << p_SQVM_Print << std::endl; + std::cout << " p_SQVM_LoadScript : " << std::hex << p_SQVM_LoadScript << std::endl; + std::cout << "--------------------------------------------------" << std::endl; + std::cout << " p_NET_ReceiveDatagram : " << std::hex << p_NET_ReceiveDatagram << std::endl; + std::cout << " p_NET_SendDatagram : " << std::hex << p_NET_SendDatagram << std::endl; + std::cout << "--------------------------------------------------" << std::endl; + std::cout << " p_SetCursorPosition : " << std::hex << p_SetCursorPosition << std::endl; + //std::cout << " p_GameWindowProc : " << std::hex << p_GameWindowProc << std::endl; + std::cout << "--------------------------------------------------" << std::endl; // TODO implement error handling when sigscan fails or result is 0 } -} \ No newline at end of file +} diff --git a/r5dev/r5dev.h b/r5dev/r5dev.h index c2ec62d7..6f4d7cb3 100644 --- a/r5dev/r5dev.h +++ b/r5dev/r5dev.h @@ -7,4 +7,4 @@ __declspec(dllexport) void DummyExport() { // Required for detours. -} \ No newline at end of file +} diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index 2725bbc6..2fe458a7 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -43,14 +43,14 @@ DynamicLibrary true v142 - NotSet + MultiByte DynamicLibrary false v142 true - NotSet + MultiByte @@ -133,6 +133,8 @@ NotUsing + stdc17 + stdcpp17 Windows @@ -142,7 +144,8 @@ detours.lib;%(AdditionalDependencies) - copy /Y "$(TargetPath)" "$(ApexDir)$(TargetFileName)" + + @@ -156,6 +159,12 @@ NotUsing + stdc17 + stdcpp17 + AnySuitable + Speed + true + true Windows @@ -167,22 +176,25 @@ detours.lib;%(AdditionalDependencies) - copy /Y "$(TargetPath)" "$(ApexDir)$(TargetFileName)" + + + - - + + + diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index 4abc4db6..5ea98e0e 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -24,6 +24,12 @@ Source Files + + Source Files + + + Source Files + @@ -32,19 +38,19 @@ Header Files - - Header Files - Header Files Header Files - + Header Files - + + Header Files + + Header Files diff --git a/r5dev/sigscan.h b/r5dev/sigscan.h deleted file mode 100644 index b97d6a4c..00000000 --- a/r5dev/sigscan.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include - -class CSigScan -{ -public: - // For getting information about the executing module - MODULEINFO GetModuleInfo(const char *szModule) - { - MODULEINFO modinfo = { 0 }; - HMODULE hModule = GetModuleHandle(szModule); - if (hModule == 0) - { - return modinfo; - } - GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO)); - return modinfo; - } - - // For finding a signature/pattern in memory of the game process - LONGLONG FindPattern(const char *module, const char *pattern, const char *mask) - { - MODULEINFO mInfo = GetModuleInfo(module); - LONGLONG base = (LONGLONG)mInfo.lpBaseOfDll; - LONGLONG size = (LONGLONG)mInfo.SizeOfImage; - LONGLONG patternLength = (LONGLONG)strlen(mask); - - for (LONGLONG i = 0; i < size - patternLength; i++) - { - bool found = true; - for (LONGLONG j = 0; j < patternLength; j++) - { - found &= mask[j] == '?' || pattern[j] == *(const char*)(base + i + j); - } - if (found) - { - return base + i; - } - } - - return NULL; - } -}; \ No newline at end of file diff --git a/r5dev/structs.h b/r5dev/structs.h index a3f62b0c..133186bd 100644 --- a/r5dev/structs.h +++ b/r5dev/structs.h @@ -25,4 +25,4 @@ struct __declspec(align(8)) netpacket_t DWORD wiresize; BYTE gap78[8]; QWORD qword80; -}; \ No newline at end of file +}; diff --git a/r5dev/utilities.h b/r5dev/utilities.h deleted file mode 100644 index 6eefc65d..00000000 --- a/r5dev/utilities.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include -#include - -#include "hooks.h" - -namespace -{ - BOOL FileExists(LPCTSTR szPath) - { - DWORD dwAttrib = GetFileAttributes(szPath); - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); - } - - ///////////////////////////////////////////////////////////////////////////// - static void DbgPrint(LPCSTR Format, ...) - { - CHAR Buffer[512] = { 0 }; - va_list Args; - - // Get the variable arg pointer. - va_start(Args, Format); - - // Format print the string. - int length = vsnprintf(Buffer, sizeof(Buffer), Format, Args); - va_end(Args); - - // Output the string to the debugger. - OutputDebugString(Buffer); - } - - ///////////////////////////////////////////////////////////////////////////// - static void HexDump(const char* header, const char* file, const char* mode, int func, const void* data, int size) - { - char ascii[17] = { 0 }; - int i, j; - ascii[16] = '\0'; - FILE* sTraceLog; - -#pragma warning(suppress : 4996) - sTraceLog = fopen(file, mode); - if (sTraceLog == NULL) - { - printf("Unable to write '%s'!\n", file); - if (func == 0) { ToggleNetHooks(); } - return; - } - - // Create block header - fprintf(sTraceLog, "%s ---- %u Bytes\n:\n", header, size); - fprintf(sTraceLog, "-------- 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n"); - - // Output the buffer to the file - for (i = 0; i < size; i++) - { - if (i % size == 0) { fprintf(sTraceLog, " 0x%04x ", i); fflush(NULL); } - fprintf(sTraceLog, "%02x ", ((unsigned char*)data)[i]); - fflush(NULL); - - if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { ascii[i % 16] = ((unsigned char*)data)[i]; } - else { ascii[i % 16] = '.'; } - - if ((i + 1) % 8 == 0 || i + 1 == size) - { - fprintf(sTraceLog, " "); - fflush(NULL); - - if ((i + 1) % 16 == 0) { i++; fprintf(sTraceLog, "%s \n ", ascii); fprintf(sTraceLog, "0x%04X ", i--); fflush(NULL); } - else if (i + 1 == size) - { - ascii[(i + 1) % 16] = '\0'; - if ((i + 1) % 16 <= 8) { fprintf(sTraceLog, " "); fflush(NULL); } - for (j = (i + 1) % 16; j < 16; j++) { fprintf(sTraceLog, " "); fflush(NULL); } - fprintf(sTraceLog, "%s \n", ascii); - fprintf(sTraceLog, "---------------------------------------------------------------------------\n\n"); - } - } - } - - fclose(sTraceLog); - } -} \ No newline at end of file diff --git a/r5dev/utility.cpp b/r5dev/utility.cpp new file mode 100644 index 00000000..9bb2d30e --- /dev/null +++ b/r5dev/utility.cpp @@ -0,0 +1,133 @@ +#include +#include +#include + +#include "hooks.h" + +/*----------------------------------------------------------------------------- + * utility.cpp + *-----------------------------------------------------------------------------*/ + + ///////////////////////////////////////////////////////////////////////////// + // +BOOL FileExists(LPCTSTR szPath) +{ + DWORD dwAttrib = GetFileAttributes(szPath); + + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} + +///////////////////////////////////////////////////////////////////////////// +// For getting information about the specified module +MODULEINFO GetModuleInfo(const char* szModule) +{ + MODULEINFO modinfo = { 0 }; + HMODULE hModule = GetModuleHandle(szModule); + if (hModule == 0) + { + return modinfo; + } + GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO)); + return modinfo; +} + +///////////////////////////////////////////////////////////////////////////// +// 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++) + { + if (Compare((unsigned char*)(dwAddress + i), szPattern, szMask)) + { + return (DWORD64)(dwAddress + i); + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// +void DbgPrint(LPCSTR sFormat, ...) +{ + CHAR sBuffer[512] = { 0 }; + va_list sArgs; + + // Get the variable arg pointer + va_start(sArgs, sFormat); + + // Format print the string + int length = vsnprintf(sBuffer, sizeof(sBuffer), sFormat, sArgs); + va_end(sArgs); + + // Output the string to the debugger + OutputDebugString(sBuffer); +} + +///////////////////////////////////////////////////////////////////////////// +// For dumping data from a buffer to a file on the disk +void HexDump(const char* szHeader, const char* szFile, const char* szMode, int nFunc, const void* pData, int nSize) +{ + char ascii[17] = { 0 }; + int i, j; + ascii[16] = '\0'; + FILE* sTraceLog; + +#pragma warning(suppress : 4996) + sTraceLog = fopen(szFile, szMode); + if (sTraceLog == NULL) + { + printf("Unable to write '%s'!\n", szFile); + if (nFunc == 0) { ToggleNetHooks(); } + return; + } + + // Create block header + fprintf(sTraceLog, "%s ---- %u Bytes\n:\n", szHeader, nSize); + fprintf(sTraceLog, "-------- 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n"); + + // Output the buffer to the file + for (i = 0; i < nSize; i++) + { + if (i % nSize == 0) { fprintf(sTraceLog, " 0x%04x ", i); fflush(NULL); } + fprintf(sTraceLog, "%02x ", ((unsigned char*)pData)[i]); + fflush(NULL); + + if (((unsigned char*)pData)[i] >= ' ' && ((unsigned char*)pData)[i] <= '~') { ascii[i % 16] = ((unsigned char*)pData)[i]; } + else { ascii[i % 16] = '.'; } + + if ((i + 1) % 8 == 0 || i + 1 == nSize) + { + fprintf(sTraceLog, " "); + fflush(NULL); + + if ((i + 1) % 16 == 0) { i++; fprintf(sTraceLog, "%s \n ", ascii); fprintf(sTraceLog, "0x%04X ", i--); fflush(NULL); } + else if (i + 1 == nSize) + { + ascii[(i + 1) % 16] = '\0'; + if ((i + 1) % 16 <= 8) { fprintf(sTraceLog, " "); fflush(NULL); } + for (j = (i + 1) % 16; j < 16; j++) { fprintf(sTraceLog, " "); fflush(NULL); } + fprintf(sTraceLog, "%s \n", ascii); + fprintf(sTraceLog, "---------------------------------------------------------------------------\n\n"); + } + } + } + + fclose(sTraceLog); +} diff --git a/r5dev/utility.h b/r5dev/utility.h new file mode 100644 index 00000000..c5ae8d36 --- /dev/null +++ b/r5dev/utility.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +BOOL FileExists(LPCTSTR szPath); +MODULEINFO GetModuleInfo(const char* szModule); +DWORD64 FindPattern(const char* szModule, const unsigned char* szPattern, const char* szMask); + +void DbgPrint(LPCSTR sFormat, ...); +void HexDump(const char* szHeader, const char* szFile, const char* szMode, int nFunc, const void* pData, int nSize); diff --git a/r5launcher/main.cpp b/r5launcher/main.cpp index 8e80ad68..d29cb894 100644 --- a/r5launcher/main.cpp +++ b/r5launcher/main.cpp @@ -28,7 +28,7 @@ bool LaunchR5Apex() LPSTR sCommandLine = sCommandDirectory; // '+exec autoexec -dev -fnf -noplatform' - fopen_s(&sLaunchParams, "launchparams.txt", "r"); + fopen_s(&sLaunchParams, "platform\\cfg\\startup_debug.cfg", "r"); BOOL result; diff --git a/r5launcher/r5launcher.vcxproj b/r5launcher/r5launcher.vcxproj index 09327cc9..d776c1c6 100644 --- a/r5launcher/r5launcher.vcxproj +++ b/r5launcher/r5launcher.vcxproj @@ -43,14 +43,14 @@ Application true v142 - NotSet + MultiByte Application false v142 true - NotSet + MultiByte @@ -122,6 +122,8 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp17 + stdc17 Console @@ -129,7 +131,8 @@ detours.lib;%(AdditionalDependencies) - copy /Y "$(TargetPath)" "$(ApexDir)$(TargetFileName)" + + @@ -140,6 +143,12 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp17 + stdc17 + AnySuitable + Speed + true + true Console @@ -149,7 +158,8 @@ detours.lib;%(AdditionalDependencies) - copy /Y "$(TargetPath)" "$(ApexDir)$(TargetFileName)" + +