diff --git a/apex.sln b/apex.sln index 1ff05e56..ae23e289 100644 --- a/apex.sln +++ b/apex.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r5launcher", "r5launcher\r5 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r5dev", "r5dev\r5dev.vcxproj", "{28CC6B4F-7A95-4933-ADA9-65E38D48516D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r5dedicated", "r5dedicated\r5dedicated.vcxproj", "{71988D92-343C-49AB-B52B-0AE0E83B0401}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -31,6 +33,14 @@ Global {28CC6B4F-7A95-4933-ADA9-65E38D48516D}.Release|x64.Build.0 = Release|x64 {28CC6B4F-7A95-4933-ADA9-65E38D48516D}.Release|x86.ActiveCfg = Release|Win32 {28CC6B4F-7A95-4933-ADA9-65E38D48516D}.Release|x86.Build.0 = Release|Win32 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Debug|x64.ActiveCfg = Debug|x64 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Debug|x64.Build.0 = Debug|x64 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Debug|x86.ActiveCfg = Debug|Win32 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Debug|x86.Build.0 = Debug|Win32 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Release|x64.ActiveCfg = Release|x64 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Release|x64.Build.0 = Release|x64 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Release|x86.ActiveCfg = Release|Win32 + {71988D92-343C-49AB-B52B-0AE0E83B0401}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/external/detours/lib.X64/detours.lib b/external/detours/lib.X64/detours.lib deleted file mode 100644 index 11ec64a0..00000000 Binary files a/external/detours/lib.X64/detours.lib and /dev/null differ diff --git a/external/detours/lib.X64/detours_trace.lib b/external/detours/lib.X64/detours_trace.lib deleted file mode 100644 index 1bda1142..00000000 Binary files a/external/detours/lib.X64/detours_trace.lib and /dev/null differ diff --git a/external/detours/lib.X64/syelog.lib b/external/detours/lib.X64/syelog.lib deleted file mode 100644 index 418b6fda..00000000 Binary files a/external/detours/lib.X64/syelog.lib and /dev/null differ diff --git a/external/detours/libs/detours.lib b/external/detours/libs/detours.lib index 11ec64a0..a813633c 100644 Binary files a/external/detours/libs/detours.lib and b/external/detours/libs/detours.lib differ diff --git a/external/detours/libs/detours.pdb b/external/detours/libs/detours.pdb index 67ce79c1..7e39e0c0 100644 Binary files a/external/detours/libs/detours.pdb and b/external/detours/libs/detours.pdb differ diff --git a/external/detours/libs/syelog.lib b/external/detours/libs/syelog.lib index 418b6fda..6012eef0 100644 Binary files a/external/detours/libs/syelog.lib and b/external/detours/libs/syelog.lib differ diff --git a/r5dedicated/cnetchan.cpp b/r5dedicated/cnetchan.cpp new file mode 100644 index 00000000..bfd915ba --- /dev/null +++ b/r5dedicated/cnetchan.cpp @@ -0,0 +1,46 @@ +#include "pch.h" +#include "cnetchan.h" + +//----------------------------------------------------------------------------- +// Hook and log the receive datagram +//----------------------------------------------------------------------------- +bool HNET_ReceiveDatagram(int sock, void* inpacket, bool raw) +{ + bool result = org_NET_ReceiveDatagram(sock, inpacket, raw); + if (result) + { + int i = NULL; + netpacket_t* pkt = (netpacket_t*)inpacket; + + // Log received packet data + HexDump("[+] NET_ReceiveDatagram", 0, &pkt->data[i], pkt->wiresize); + } + return result; +} + +//----------------------------------------------------------------------------- +// Hook and log send datagram +//----------------------------------------------------------------------------- +unsigned int HNET_SendDatagram(SOCKET s, const char* buf, int len, int flags) +{ + unsigned int result = org_NET_SendDatagram(s, buf, len, flags); + if (result) + { + // Log transmitted packet data + HexDump("[+] NET_SendDatagram", 0, buf, len); + } + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +void AttachCNetChanHooks() +{ + DetourAttach((LPVOID*)&org_NET_ReceiveDatagram, &HNET_ReceiveDatagram); + DetourAttach((LPVOID*)&org_NET_SendDatagram, &HNET_SendDatagram); +} + +void DetachCNetChanHooks() +{ + DetourDetach((LPVOID*)&org_NET_ReceiveDatagram, &HNET_ReceiveDatagram); + DetourDetach((LPVOID*)&org_NET_SendDatagram, &HNET_SendDatagram); +} \ No newline at end of file diff --git a/r5dedicated/cnetchan.h b/r5dedicated/cnetchan.h new file mode 100644 index 00000000..b0e425db --- /dev/null +++ b/r5dedicated/cnetchan.h @@ -0,0 +1,34 @@ +#pragma once +#include "pch.h" +#include "hooks.h" + +bool HNET_ReceiveDatagram(int sock, void* inpacket, bool raw); +unsigned int HNET_SendDatagram(SOCKET s, const char* buf, int len, int flags); + +void AttachCNetChanHooks(); +void DetachCNetChanHooks(); + +typedef unsigned __int64 QWORD; +struct __declspec(align(8)) netpacket_t +{ + DWORD family_maybe; + sockaddr_in sin; + WORD sin_port; + BYTE gap16; + BYTE byte17; + DWORD source; + double received; + unsigned __int8* data; + QWORD label; + BYTE byte38; + QWORD qword40; + QWORD qword48; + BYTE gap50[8]; + QWORD qword58; + QWORD qword60; + QWORD qword68; + int less_than_12; + DWORD wiresize; + BYTE gap78[8]; + QWORD qword80; +}; \ No newline at end of file diff --git a/r5dedicated/concommand.cpp b/r5dedicated/concommand.cpp new file mode 100644 index 00000000..bbe14b4d --- /dev/null +++ b/r5dedicated/concommand.cpp @@ -0,0 +1,39 @@ +#include "pch.h" +#include "concommand.h" + +//----------------------------------------------------------------------------- +// Purpose: test each ConCommand query before execution +// Input : *cmd - flag +// Output : true if execution is not permitted, false if permitted +//----------------------------------------------------------------------------- +bool HConCommand_IsFlagSet(int* cmd, int flag) +{ + int real_flags = *((cmd + (56 / sizeof(int)))); + if (g_bDebugConsole) + { + printf("--------------------------------------------------\n"); + printf(" Flaged: %08X\n", real_flags); + } + // Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY + real_flags &= 0xFFFFBFFD; + if (g_bDebugConsole) + { + printf(" Masked: %08X\n", real_flags); + printf(" Verify: %08X\n", flag); + printf("--------------------------------------------------\n"); + } + if (flag & 0x80000) { return true; } + + if (!g_bReturnAllFalse) { return (real_flags & flag) != 0; } + else { return false; } // Returning false on all queries may cause problems +} + +void AttachConCommandHooks() +{ + DetourAttach((LPVOID*)&org_ConCommand_IsFlagSet, &HConCommand_IsFlagSet); +} + +void DetachConCommandHooks() +{ + DetourDetach((LPVOID*)&org_ConCommand_IsFlagSet, &HConCommand_IsFlagSet); +} \ No newline at end of file diff --git a/r5dedicated/concommand.h b/r5dedicated/concommand.h new file mode 100644 index 00000000..6442c1e1 --- /dev/null +++ b/r5dedicated/concommand.h @@ -0,0 +1,7 @@ +#pragma once +#include "hooks.h" + +bool HConCommand_IsFlagSet(int* cmd, int flag); + +void AttachConCommandHooks(); +void DetachConCommandHooks(); \ No newline at end of file diff --git a/r5dedicated/console.cpp b/r5dedicated/console.cpp new file mode 100644 index 00000000..8c22fb47 --- /dev/null +++ b/r5dedicated/console.cpp @@ -0,0 +1,97 @@ +#include "pch.h" +#include "hooks.h" +#include "console.h" +#include "iconvar.h" +#include "concommand.h" + +//############################################################################# +// INITIALIZATION +//############################################################################# + +void SetupConsole() +{ + /////////////////////////////////////////////////////////////////////////// + // Create the console window + if (AllocConsole() == FALSE) + { + OutputDebugString("Failed to create console window!\n"); + return; + } + + /////////////////////////////////////////////////////////////////////////// + // Set the window title + FILE* sBuildTxt; + CHAR sBuildBuf[1024] = { 0 }; + + fopen_s(&sBuildTxt, "build.txt", "r"); + if (sBuildTxt) + { + while (fgets(sBuildBuf, sizeof(sBuildBuf), sBuildTxt) != NULL) + { + fclose(sBuildTxt); + } + } + SetConsoleTitle(sBuildBuf); + + /////////////////////////////////////////////////////////////////////////// + // Open input/output streams + FILE* fDummy; + freopen_s(&fDummy, "CONIN$", "r", stdin); + freopen_s(&fDummy, "CONOUT$", "w", stdout); + freopen_s(&fDummy, "CONOUT$", "w", stderr); + + /////////////////////////////////////////////////////////////////////////// + // Create a worker thread to process console commands + DWORD threadId0; + DWORD __stdcall ProcessConsoleWorker(LPVOID); + HANDLE hThread0 = CreateThread(NULL, 0, ProcessConsoleWorker, NULL, 0, &threadId0); + + if (hThread0) + { + printf("THREAD ID: %ld\n\n", threadId0); + CloseHandle(hThread0); + } +} + +//############################################################################# +// WORKER THREAD +//############################################################################# + +DWORD __stdcall ProcessConsoleWorker(LPVOID) +{ + // Loop forever + while (true) + { + std::string sCommand; + + /////////////////////////////////////////////////////////////////////// + // Get the user input on the debug console + printf(">"); + std::getline(std::cin, sCommand); + + /////////////////////////////////////////////////////////////////////// + // Engine toggles + if (sCommand == "toggle net") { ToggleNetTrace(); continue; } + if (sCommand == "toggle dev") { ToggleDevCommands(); continue; } + if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } + /////////////////////////////////////////////////////////////////////// + // Debug toggles + if (sCommand == "pattern test") { PrintHAddress(); /*PrintOAddress();*/ continue; } + if (sCommand == "console test") { g_bDebugConsole = !g_bDebugConsole; continue; } + /////////////////////////////////////////////////////////////////////// + // Exec toggles + if (sCommand == "1") { org_CommandExecute(NULL, "exec autoexec_dev"); } + if (sCommand == "2") { g_bDebugLoading = !g_bDebugLoading; continue; } + + /////////////////////////////////////////////////////////////////////// + // Execute the command in the r5 SQVM + org_CommandExecute(NULL, sCommand.c_str()); + sCommand.clear(); + + /////////////////////////////////////////////////////////////////////// + // Sleep and loop + Sleep(50); + } + + return 0; +} \ No newline at end of file diff --git a/r5dedicated/console.h b/r5dedicated/console.h new file mode 100644 index 00000000..19d16a6b --- /dev/null +++ b/r5dedicated/console.h @@ -0,0 +1,5 @@ +#pragma once +#include "pch.h" + +void SetupConsole(); +void ToggleDevCommands(); diff --git a/r5dedicated/cvengineserver.cpp b/r5dedicated/cvengineserver.cpp new file mode 100644 index 00000000..bf15cee5 --- /dev/null +++ b/r5dedicated/cvengineserver.cpp @@ -0,0 +1,42 @@ +#include "pch.h" +#include "cvengineserver.h" + +//----------------------------------------------------------------------------- +// Sets the persistence var in the playerstruct to ready for each client +//----------------------------------------------------------------------------- +bool HPersistence_IsAvailable(__int64 thisptr, int client) +{ + static bool isPersistenceVarSet[256]; + + // TODO: Maybe not hardcode + std::uintptr_t playerStructBase = 0x16073B200; + std::uintptr_t playerStructSize = 0x4A4C0; + std::uintptr_t persistenceVar = 0x5BC; + + std::uintptr_t targetPlayerStruct = playerStructBase + client * playerStructSize; + + *(char*)(targetPlayerStruct + persistenceVar) = (char)0x5; + + if (!isPersistenceVarSet[client]) + { + printf("\n"); + printf("##################################################\n"); + printf("] SETTING PERSISTENCE VAR FOR CLIENT #%d\n", client); + printf("##################################################\n"); + printf("\n"); + isPersistenceVarSet[client] = true; + } + + /////////////////////////////////////////////////////////////////////////// + return org_Persistence_IsAvailable(thisptr, client); +} + +void AttachCEngineServerHooks() +{ + DetourAttach((LPVOID*)&org_Persistence_IsAvailable, &HPersistence_IsAvailable); +} + +void DetachCEngineServerHooks() +{ + DetourDetach((LPVOID*)&org_Persistence_IsAvailable, &HPersistence_IsAvailable); +} \ No newline at end of file diff --git a/r5dedicated/cvengineserver.h b/r5dedicated/cvengineserver.h new file mode 100644 index 00000000..933c2a15 --- /dev/null +++ b/r5dedicated/cvengineserver.h @@ -0,0 +1,8 @@ +#pragma once +#include "pch.h" +#include "hooks.h" + +bool HPersistence_IsAvailable(__int64 thisptr, int client); + +void AttachCEngineServerHooks(); +void DetachCEngineServerHooks(); \ No newline at end of file diff --git a/r5dedicated/dllmain.cpp b/r5dedicated/dllmain.cpp new file mode 100644 index 00000000..8d135d1e --- /dev/null +++ b/r5dedicated/dllmain.cpp @@ -0,0 +1,49 @@ +#include "pch.h" +#include "dllmain.h" +#include "hooks.h" +#include "console.h" + +//############################################################################# +// INITIALIZATION +//############################################################################# + +void InitializeR5Dedicated() +{ + SetupConsole(); + InstallHooks(); + printf("+-----------------------------------------------------------------------------+\n"); + printf("| R5 DEDICATED SERVER --------------------------------------------------- |\n"); + printf("+-----------------------------------------------------------------------------+\n"); + printf("\n"); +} + +void TerminateR5Dedicated() +{ + FreeConsole(); + RemoveHooks(); +} + +//############################################################################# +// ENTRYPOINT +//############################################################################# + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) +{ + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { + InitializeR5Dedicated(); + break; + } + + case DLL_PROCESS_DETACH: + { + TerminateR5Dedicated(); + break; + } + } + + return TRUE; +} diff --git a/r5dedicated/dllmain.h b/r5dedicated/dllmain.h new file mode 100644 index 00000000..7ec14cc2 --- /dev/null +++ b/r5dedicated/dllmain.h @@ -0,0 +1,5 @@ +#pragma once +__declspec(dllexport) void DummyExport() +{ + // Required for detours. +} \ No newline at end of file diff --git a/r5dedicated/hooks.cpp b/r5dedicated/hooks.cpp new file mode 100644 index 00000000..90e52c41 --- /dev/null +++ b/r5dedicated/hooks.cpp @@ -0,0 +1,134 @@ +#include "pch.h" +#include "hooks.h" +#include "iconvar.h" +#include "concommand.h" +#include "cvengineserver.h" +#include "cnetchan.h" +#include "sqvm.h" +#include "msgbox.h" +#include "opcodes.h" + +//################################################################################# +// MANAGEMENT +//################################################################################# + +void InstallHooks() +{ + /////////////////////////////////////////////////////////////////////////////// + // Begin the detour transaction, to hook the the process + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + /////////////////////////////////////////////////////////////////////////////// + // Hook functions + AttachIConVarHooks(); + AttachConCommandHooks(); + AttachCEngineServerHooks(); + AttachSQVMHooks(); + AttachMSGBoxHooks(); + + /////////////////////////////////////////////////////////////////////////////// + // Commit the transaction + if (DetourTransactionCommit() != NO_ERROR) + { + // Failed to hook into the process, terminate + TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); + } + + InstallOpcodes(); +} + +void RemoveHooks() +{ + /////////////////////////////////////////////////////////////////////////////// + // Begin the detour transaction, to unhook the the process + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook functions + DetachIConVarHooks(); + DetachConCommandHooks(); + DetachCEngineServerHooks(); + DetachSQVMHooks(); + DetachMSGBoxHooks(); + + /////////////////////////////////////////////////////////////////////////////// + // Commit the transaction + DetourTransactionCommit(); +} + +//################################################################################# +// TOGGLES +//################################################################################# + +void ToggleDevCommands() +{ + static bool bDev = true; + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + if (!bDev) + { + AttachIConVarHooks(); + AttachConCommandHooks(); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + + } + else + { + DetachIConVarHooks(); + DetachConCommandHooks(); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + + if (DetourTransactionCommit() != NO_ERROR) + { + TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); + } + + bDev = !bDev; +} + +void ToggleNetTrace() +{ + static bool bNet = true; + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + if (!bNet) + { + AttachCNetChanHooks(); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + else + { + DetachCNetChanHooks(); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + + if (DetourTransactionCommit() != NO_ERROR) + { + TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); + } + + bNet = !bNet; +} diff --git a/r5dedicated/hooks.h b/r5dedicated/hooks.h new file mode 100644 index 00000000..cdded7a3 --- /dev/null +++ b/r5dedicated/hooks.h @@ -0,0 +1,89 @@ +#pragma once +#include "pch.h" +#include "iconvar.h" +#include "concommand.h" +#include "cvengineserver.h" +#include "cnetchan.h" +#include "sqvm.h" +#include "msgbox.h" +// Define the signatures or offsets to be searched and hooked +namespace +{ + Module r5_patterns = Module("r5apex.exe"); // Create module class instance. + +#pragma region Console + /*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()); + + /*0x14046FE90*/ + FUNC_AT_ADDRESS(org_IConVar_IsFlagSet, bool(*)(int**, int), r5_patterns.PatternSearch("48 8B 41 48 85 50 38").GetPtr()); + + /*0x14046F490*/ + FUNC_AT_ADDRESS(org_ConCommand_IsFlagSet, bool(*)(int*, int), r5_patterns.PatternSearch("85 51 38 0F 95 C0 C3").GetPtr()); +#pragma endregion + +#pragma region Squirrel + /*0x141057FD0*/ + FUNC_AT_ADDRESS(org_SQVM_PrintFunc, void*, r5_patterns.PatternSearch("83 F8 01 48 8D 3D ? ? ? ?").OffsetSelf(0x3).FollowNearCallSelf(0x3, 0x7).GetPtr()); + + //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 + + /*0x141055630*/ + // 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*/ + 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()); +#pragma endregion + +#pragma region NetChannel + /*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*/ + 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 + +#pragma region CHLClient + /*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 + /*0x140315CF0*/ + FUNC_AT_ADDRESS(org_Persistence_IsAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr()); +#pragma endregion + +#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").GetPtr()); +#pragma endregion + + inline bool g_bDebugConsole = false; + inline bool g_bReturnAllFalse = false; + inline bool g_bDebugLoading = false; + + void PrintHAddress() // Test the sigscan results + { + std::cout << "+--------------------------------------------------------+" << std::endl; + PRINT_ADDRESS("CommandExecute", org_CommandExecute); + PRINT_ADDRESS("IConVar_IsFlagSet", org_IConVar_IsFlagSet); + PRINT_ADDRESS("ConCommand_IsFlagSet", org_ConCommand_IsFlagSet); + PRINT_ADDRESS("SQVM_Print", org_SQVM_PrintFunc); + 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::Persistence_IsAvailable", org_Persistence_IsAvailable); + PRINT_ADDRESS("MSG_EngineError", org_MSG_EngineError); + std::cout << "+--------------------------------------------------------+" << std::endl; + // TODO implement error handling when sigscan fails or result is 0 + } +} + +void InstallHooks(); +void RemoveHooks(); + +void ToggleDevCommands(); +void ToggleNetTrace(); \ No newline at end of file diff --git a/r5dedicated/iconvar.cpp b/r5dedicated/iconvar.cpp new file mode 100644 index 00000000..169c9060 --- /dev/null +++ b/r5dedicated/iconvar.cpp @@ -0,0 +1,39 @@ +#include "pch.h" +#include "iconvar.h" + +//----------------------------------------------------------------------------- +// Purpose: test each ConVar query before setting the cvar +// Input : **cvar - flag +// Output : true if change is not permitted, false if permitted +//----------------------------------------------------------------------------- +bool HConVar_IsFlagSet(int** cvar, int flag) +{ + int real_flags = *(*(cvar + (72 / (sizeof(void*)))) + (56 / sizeof(int))); + if (g_bDebugConsole) + { + printf("--------------------------------------------------\n"); + printf(" Flaged: %08X\n", real_flags); + } + // Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY + real_flags &= 0xFFFFBFFD; + if (g_bDebugConsole) + { + printf(" Masked: %08X\n", real_flags); + printf(" Verify: %08X\n", flag); + printf("--------------------------------------------------\n"); + } + if (flag & 0x80000) { return true; } + + if (!g_bReturnAllFalse) { return (real_flags & flag) != 0; } + else { return false; } // Returning false on all queries may cause problems +} + +void AttachIConVarHooks() +{ + DetourAttach((LPVOID*)&org_IConVar_IsFlagSet, &HConVar_IsFlagSet); +} + +void DetachIConVarHooks() +{ + DetourDetach((LPVOID*)&org_IConVar_IsFlagSet, &HConVar_IsFlagSet); +} \ No newline at end of file diff --git a/r5dedicated/iconvar.h b/r5dedicated/iconvar.h new file mode 100644 index 00000000..25880877 --- /dev/null +++ b/r5dedicated/iconvar.h @@ -0,0 +1,7 @@ +#pragma once +#include "hooks.h" + +bool HConVar_IsFlagSet(int** cvar, int flag); + +void AttachIConVarHooks(); +void DetachIConVarHooks(); \ No newline at end of file diff --git a/r5dedicated/msgbox.cpp b/r5dedicated/msgbox.cpp new file mode 100644 index 00000000..24e1ea15 --- /dev/null +++ b/r5dedicated/msgbox.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "hooks.h" + +//----------------------------------------------------------------------------- +// Engine Error message box +//----------------------------------------------------------------------------- +int HMSG_EngineError(char* fmt, va_list args) +{ + printf("\nENGINE ERROR #####################################\n"); + vprintf(fmt, args); + + /////////////////////////////////////////////////////////////////////////// + return org_MSG_EngineError(fmt, args); +} + +void AttachMSGBoxHooks() +{ + DetourAttach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); +} + +void DetachMSGBoxHooks() +{ + DetourDetach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); +} \ No newline at end of file diff --git a/r5dedicated/msgbox.h b/r5dedicated/msgbox.h new file mode 100644 index 00000000..ea1e094d --- /dev/null +++ b/r5dedicated/msgbox.h @@ -0,0 +1,7 @@ +#pragma once +#include "hooks.h" + +int HMSG_EngineError(char* fmt, va_list args); + +void AttachMSGBoxHooks(); +void DetachMSGBoxHooks(); \ No newline at end of file diff --git a/r5dedicated/opcodes.cpp b/r5dedicated/opcodes.cpp new file mode 100644 index 00000000..d91b6b44 --- /dev/null +++ b/r5dedicated/opcodes.cpp @@ -0,0 +1,29 @@ +#include "pch.h" +#include "opcodes.h" + +/*----------------------------------------------------------------------------- + * _opcodes.cpp + *-----------------------------------------------------------------------------*/ + +void InstallOpcodes() /* .TEXT */ +{ + //------------------------------------------------------------------------- + // JNZ --> JMP | Prevent OriginSDK from initializing on the client + //Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 }); + //Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 }); + //------------------------------------------------------------------------- + // JNE --> JMP | Allow games to be loaded without the optional texture streaming file + dst002.Offset(0x8E5).Patch({ 0xEB, 0x19 }); + //------------------------------------------------------------------------- + // JNE --> JMP | Prevent connect command from crashing by invalid call to UI function + dst004.Offset(0x1D6).Patch({ 0xEB, 0x27 }); + //------------------------------------------------------------------------- + // JNE --> JMP | Prevent connect localhost from being executed after listenserver init + //Host_NewGame.Offset(0x637).Patch({ 0xE9, 0xC1, 0x00, 0x00, 0x00}); + //------------------------------------------------------------------------- + // JA --> JMP | Disable server-side verification for duplicate accounts on the server + CServer_Auth.Offset(0x284).Patch({ 0x90, 0x90 }); + //------------------------------------------------------------------------- + // JA --> JMP | Prevent FairFight anti-cheat from initializing on the server + FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 }); +} \ No newline at end of file diff --git a/r5dedicated/opcodes.h b/r5dedicated/opcodes.h new file mode 100644 index 00000000..4c44dcd5 --- /dev/null +++ b/r5dedicated/opcodes.h @@ -0,0 +1,53 @@ +#pragma once + +void InstallOpcodes(); +inline HANDLE GameProcess = GetCurrentProcess(); + +namespace +{ + Module r5_op = Module("r5apex.exe"); // Create module class instance. + +#pragma region Origin + /*0x14032EEA0*/ + MemoryAddress Origin_Init = r5_op.PatternSearch("48 83 EC 28 80 3D ? ? ? 23 ? 0F 85 ? 02 ?"); + + /*0x140330290*/ + MemoryAddress Origin_SetState = r5_op.PatternSearch("48 81 EC 58 04 ? ? 80 3D ? ? ? ? ? 0F 84"); +#pragma endregion + +#pragma region Engine + /*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 CServer_Auth = r5_op.PatternSearch("40 55 57 41 55 41 57 48 8D AC 24 ? ? ? ?"); +#pragma endregion + +#pragma region FairFight + /*0x140303AE0*/ + MemoryAddress FairFight_Init = 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 + { + std::cout << "+--------------------------------------------------------+" << std::endl; + PRINT_ADDRESS("Origin_Init", Origin_Init.GetPtr()); + PRINT_ADDRESS("Origin_SetState", Origin_SetState.GetPtr()); + PRINT_ADDRESS("dst002", dst002.GetPtr()); + PRINT_ADDRESS("dst004", dst004.GetPtr()); + PRINT_ADDRESS("Host_NewGame", Host_NewGame.GetPtr()); + PRINT_ADDRESS("CServer_Auth", CServer_Auth.GetPtr()); + PRINT_ADDRESS("FairFight_Init", FairFight_Init.GetPtr()); + std::cout << "+--------------------------------------------------------+" << std::endl; + + // TODO implement error handling when sigscan fails or result is 0 + } +} \ No newline at end of file diff --git a/r5dedicated/pch.cpp b/r5dedicated/pch.cpp new file mode 100644 index 00000000..17305716 --- /dev/null +++ b/r5dedicated/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/r5dedicated/pch.h b/r5dedicated/pch.h new file mode 100644 index 00000000..975aba77 --- /dev/null +++ b/r5dedicated/pch.h @@ -0,0 +1,39 @@ +#pragma once +#pragma message("Pre-compiling headers.\n") + +#define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Our headers + +#include "spdlog.h" +#include "sinks/basic_file_sink.h" +#include "utility.h" +//#include "httplib.h" +//#include "json.hpp" + +#include "address.h" + +#pragma once + +#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; diff --git a/r5dedicated/r5dedicated.def b/r5dedicated/r5dedicated.def new file mode 100644 index 00000000..adb0127b --- /dev/null +++ b/r5dedicated/r5dedicated.def @@ -0,0 +1,4 @@ +LIBRARY dedicated + +EXPORTS + DummyExport @1 \ No newline at end of file diff --git a/r5dedicated/r5dedicated.vcxproj b/r5dedicated/r5dedicated.vcxproj new file mode 100644 index 00000000..7e6fe2bd --- /dev/null +++ b/r5dedicated/r5dedicated.vcxproj @@ -0,0 +1,305 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {71988d92-343c-49ab-b52b-0ae0e83b0401} + r5dedicated + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + MultiByte + + + DynamicLibrary + false + v142 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + dedicated + + + false + dedicated + + + true + dedicated + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)external\detours\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dedicated;$(IncludePath) + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)external\detours\libs;$(LibraryPath) + + + false + dedicated + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)external\detours\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dedicated;$(IncludePath) + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)external\detours\libs;$(LibraryPath) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + Default + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + Default + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + stdc17 + Use + pch.h + $(IntDir)$(TargetName).pch + + + Console + true + detours.lib;%(AdditionalDependencies) + r5dedicated.def + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + stdc17 + Disabled + Speed + false + true + Use + pch.h + $(IntDir)$(TargetName).pch + + + Console + true + true + true + detours.lib;%(AdditionalDependencies) + r5dedicated.def + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/r5dedicated/r5dedicated.vcxproj.filters b/r5dedicated/r5dedicated.vcxproj.filters new file mode 100644 index 00000000..b0039216 --- /dev/null +++ b/r5dedicated/r5dedicated.vcxproj.filters @@ -0,0 +1,438 @@ + + + + + {b5a2491a-0f04-4b55-bc24-bbdd9cd6fc2e} + + + {ef65ed91-551f-4f5d-b2a9-efc26e1af0f6} + + + {22b58a18-d1d7-4e3e-b5de-d9338f3177d3} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {a0165b58-06b1-4b6a-b5d1-5d643517ad14} + + + {06affed3-5a59-4b95-88ca-72d92c91909b} + + + {0742106d-702f-499e-99f1-e43f2a6ae561} + + + {338a4fb7-7519-4628-9206-679d33824965} + + + {cc424eef-0c7a-4fb0-9d84-30bf8db2e253} + + + {74afa89f-72af-4e13-aa90-70f7a1957154} + + + {35b40ed1-12bd-4bcf-9c05-5a42a0096619} + + + {05e6e9a7-801b-49b0-9c5a-21c4868befb7} + + + {a7199092-e8a9-49fa-97e1-b2d0ea21001b} + + + {bd5aef1a-dad8-45a0-85f2-82bc8f86bed8} + + + {c947552e-2623-4672-b3fa-3b50fe819628} + + + {19dd0a10-5185-4b03-9466-693b86a17dff} + + + {cb271201-f518-4dc4-9ab4-5d7f6a54c175} + + + {12259d0c-172a-4a26-a1d4-5d784f4c3d25} + + + {13bdf72b-f7c0-4658-9899-932f31d03da7} + + + {eaefe9b7-d14d-48b6-878a-53a5ada7454b} + + + + + shared\include + + + shared\include + + + shared\include + + + shared\include + + + core\include + + + hooks\netchannel + + + core\include + + + hooks\concommand + + + hooks\cvengineserver + + + hooks\squirrel + + + hooks\other + + + hooks + + + core\include + + + hooks\other + + + hooks\iconvar + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include + + + shared\libraries\spdlog\include\cfg + + + shared\libraries\spdlog\include\cfg + + + shared\libraries\spdlog\include\cfg + + + shared\libraries\spdlog\include\cfg + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\details + + + shared\libraries\spdlog\include\fmt + + + shared\libraries\spdlog\include\fmt + + + shared\libraries\spdlog\include\fmt + + + shared\libraries\spdlog\include\fmt + + + shared\libraries\spdlog\include\fmt + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\fmt\bundled + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + shared\libraries\spdlog\include\sinks + + + + + core + + + core + + + core + + + hooks + + + hooks\netchannel + + + hooks\concommand + + + hooks\cvengineserver + + + hooks\squirrel + + + hooks\other + + + hooks\other + + + hooks\iconvar + + + shared + + + + + core\resource + + + \ No newline at end of file diff --git a/r5dedicated/sqvm.cpp b/r5dedicated/sqvm.cpp new file mode 100644 index 00000000..b94a76b3 --- /dev/null +++ b/r5dedicated/sqvm.cpp @@ -0,0 +1,100 @@ +#include "pch.h" +#include "sqvm.h" + +//--------------------------------------------------------------------------------- +// Print the output of the VM. +// TODO: separate SV CL and UI +//--------------------------------------------------------------------------------- +void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + return NULL; +} + +//--------------------------------------------------------------------------------- +// Load the include file from the mods directory +//--------------------------------------------------------------------------------- +__int64 HSQVM_LoadRson(const char* rson_name) +{ + char filepath[MAX_PATH] = { 0 }; + sprintf_s(filepath, MAX_PATH, "platform\\%s", rson_name); + + // Flip forward slashes in filepath to windows-style backslash + for (int i = 0; i < strlen(filepath); i++) + { + if (filepath[i] == '/') + { + filepath[i] = '\\'; + } + } + + // Returns the new path if the rson exists on the disk + if (FileExists(filepath) && org_SQVM_LoadRson(rson_name)) + { + printf("\n"); + printf("##################################################\n"); + printf("] '%s'\n", filepath); + printf("##################################################\n"); + printf("\n"); + return org_SQVM_LoadRson(filepath); + } + + printf("\n"); + printf("##################################################\n"); + printf("] '%s'\n", rson_name); + printf("##################################################\n"); + printf("\n"); + return org_SQVM_LoadRson(rson_name); +} + +//--------------------------------------------------------------------------------- +// Load the script file from the mods directory +//--------------------------------------------------------------------------------- +bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag) +{ + char filepath[MAX_PATH] = { 0 }; + sprintf_s(filepath, MAX_PATH, "platform\\%s", script_path); + + // Flip forward slashes in filepath to windows-style backslash + for (int i = 0; i < strlen(filepath); i++) + { + if (filepath[i] == '/') + { + filepath[i] = '\\'; + } + } + if (g_bDebugLoading) + { + printf(" [+] Loading SQVM Script '%s' ...\n", filepath); + } + + // Returns true if the script exists on the disk + if (FileExists(filepath) && org_SQVM_LoadScript(sqvm, filepath, script_name, flag)) + { + return true; + } + if (g_bDebugLoading) + { + printf(" [!] FAILED. Try SP / VPK for '%s'\n", filepath); + } + + /////////////////////////////////////////////////////////////////////////////// + return org_SQVM_LoadScript(sqvm, script_path, script_name, flag); +} + +void AttachSQVMHooks() +{ + DetourAttach((LPVOID*)&org_SQVM_PrintFunc, &HSQVM_PrintFunc); + DetourAttach((LPVOID*)&org_SQVM_LoadRson, &HSQVM_LoadRson); + DetourAttach((LPVOID*)&org_SQVM_LoadScript, &HSQVM_LoadScript); +} + +void DetachSQVMHooks() +{ + DetourDetach((LPVOID*)&org_SQVM_PrintFunc, &HSQVM_PrintFunc); + DetourDetach((LPVOID*)&org_SQVM_LoadRson, &HSQVM_LoadRson); + DetourDetach((LPVOID*)&org_SQVM_LoadScript, &HSQVM_LoadScript); +} \ No newline at end of file diff --git a/r5dedicated/sqvm.h b/r5dedicated/sqvm.h new file mode 100644 index 00000000..2798c54d --- /dev/null +++ b/r5dedicated/sqvm.h @@ -0,0 +1,10 @@ +#pragma once +#include "pch.h" +#include "hooks.h" + +void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...); +__int64 HSQVM_LoadRson(const char* rson_name); +bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag); + +void AttachSQVMHooks(); +void DetachSQVMHooks(); \ No newline at end of file diff --git a/r5dev/include/gameclasses.h b/r5dev/include/gameclasses.h index dccd107e..c495cc2e 100644 --- a/r5dev/include/gameclasses.h +++ b/r5dev/include/gameclasses.h @@ -517,12 +517,68 @@ public: } }; -struct CVValue_t +class ConCommandBase { - char* m_pszString; - __int64 m_StringLength; - float m_fValue; - int m_nValue; +public: + void* m_pConCommandBaseVTable; //0x0000 + ConCommandBase* m_pNext; //0x0008 + bool m_bRegistered; //0x0010 +private: + char pad_0011[7]; //0x0011 +public: + const char* m_pszName; //0x0018 + const char* m_pszHelpString; //0x0020 +private: + char pad_0028[16]; //0x0028 +public: + __int32 m_nFlags; //0x0038 +private: + char pad_003C[4]; //0x003C +}; //Size: 0x0038 + +class ConVar +{ +public: + ConCommandBase m_ConCommandBase; // 0x0000 + void* m_pConVarVTable; //0x0040 + ConVar* m_pParent; //0x0048 + const char* n_pszDefaultValue; //0x0050 + const char* m_pzsCurrentValue; //0x0058 + __int64 m_iStringLength; //0x0060 + float m_flValue; //0x0068 + __int64 m_iValue; //0x006C + bool m_bHasMin; //0x0070 +private: + char pad_0071[3]; //0x0071 +public: + float m_flMinValue; //0x0074 + bool m_bHasMax; //0x0078 +private: + char pad_0079[3]; //0x0079 +public: + float m_flMaxValue; //0x007C +}; //Size: 0x0080 + +class CCVar +{ +public: + ConCommandBase* FindCommandBase(const char* szCommandName) // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = ConCommandBase*(__thiscall*)(CCVar*, const char*); + return (*reinterpret_cast(this))[14](this, szCommandName); + } + + ConVar* FindVar(const char* szVarName) // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = ConVar*(__thiscall*)(CCVar*, const char*); + return (*reinterpret_cast(this))[16](this, szVarName); + } + + void* /*Implement ConCommand class.*/ FindCommand(const char* szCommandName) // @0x1405983F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM + { + using OriginalFn = void*(__thiscall*)(CCVar*, const char*); + return (*reinterpret_cast(this))[18](this, szCommandName); + } }; ///////////////////////////////////////////////////////////////////////////// @@ -532,6 +588,7 @@ namespace GameGlobals { extern CHostState* HostState; extern CInputSystem* InputSystem; + extern CCVar* Cvar; void InitGameGlobals(); extern bool IsInitialized; diff --git a/r5dev/include/pch.h b/r5dev/include/pch.h index 3d46b534..63fe41cf 100644 --- a/r5dev/include/pch.h +++ b/r5dev/include/pch.h @@ -1,7 +1,6 @@ #pragma once #pragma message("Pre-compiling headers.\n") -#include "httplib.h" #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition. #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include @@ -30,7 +28,9 @@ #include "imgui_impl_dx11.h" #include "imgui_impl_win32.h" #include "spdlog.h" +#include "sinks/basic_file_sink.h" #include "utility.h" +#include "httplib.h" #include "json.hpp" #include "address.h" diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index d4a19fb6..09852b54 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -82,12 +82,12 @@ true - $(SolutionDir)external\detours\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)r5dev\include;$(IncludePath) + $(SolutionDir)external\detours\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dev\include;$(IncludePath) $(SolutionDir)external\detours\libs;$(LibraryPath) false - $(SolutionDir)external\detours\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)external\stb\include;$(SolutionDir)r5dev\include;$(IncludePath) + $(SolutionDir)external\detours\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dev\include;$(IncludePath) $(SolutionDir)external\detours\libs;$(LibraryPath) @@ -132,9 +132,8 @@ true _DEBUG;R5DEV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true - NotUsing - - + Use + pch.h stdc17 stdcpp17 @@ -286,17 +285,17 @@ - - + + + + - - @@ -304,33 +303,40 @@ - NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing NotUsing + NotUsing NotUsing + NotUsing + Use pch.h @@ -366,15 +372,13 @@ Create pch.h + Create + pch.h Use pch.h - - Use - pch.h - diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index fe847e7e..ad690856 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -1,56 +1,63 @@  + + {a80939e5-3b3c-4873-885e-834e95d68d34} + + + {927ea852-3616-4fc4-8b32-781f65853a6b} + + + {b421eb0e-1e3d-4a7a-a8d8-f9b397911702} + + + {c2ad07a8-ef40-4faa-b86c-19b31bf3209d} + + + {633d6e7a-c709-4d64-a134-b383d43c8c8e} + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {7cef4f92-94d9-43af-bea5-c6963d68fff2} - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {a80939e5-3b3c-4873-885e-834e95d68d34} - - - {c72b9789-72e9-4657-8a42-8712aaf8690e} - - - {c18fb898-adc3-4aa8-902c-4777bbc76e5b} - - - {c3bd7c47-4a04-43da-b79f-b8ef22ba72d4} - - + {584562a8-0382-488c-909c-67bbb1d1af3c} - - {3fa7f9a9-dc07-4d42-9172-0944829c010f} + + {c72b9789-72e9-4657-8a42-8712aaf8690e} - + {757af774-e575-4623-8582-71efb0ae53a4} - + + {3fa7f9a9-dc07-4d42-9172-0944829c010f} + + + {c18fb898-adc3-4aa8-902c-4777bbc76e5b} + + {7b737633-f8a6-464b-868c-c63854984082} - + {f832e462-9066-45a9-8f58-f865d5c24de3} - + {af02cb01-8e1d-49f9-b3da-cff2cf7dc7a1} - + {9d3b7c40-958a-4f6e-9ab6-72c3caea9591} - + + {6faf53e7-9be1-439f-92f9-16ab96c005b7} + + {e38cd6c5-b355-4bb5-bf65-bfd51fef296b} - - {6faf53e7-9be1-439f-92f9-16ab96c005b7} + + {30005d10-4213-441c-b18b-4dd47fcb8812} {10c4f432-81f6-46f2-9ab0-ac70ee08bff7} @@ -60,42 +67,15 @@ - - Source Files - Source Files Source Files - - Source Files - Source Files - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - - - External Libraries\imgui\Source Files - Source Files @@ -111,8 +91,35 @@ Source Files + + core + - Source Files + core + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared\libraries\imgui + + + shared External Libraries\imgui\Source Files @@ -137,41 +144,38 @@ Header Files - - Header Files - - External Libraries\detours\Header Files + shared\libraries\detours\include - External Libraries\detours\Header Files + shared\libraries\detours\include - External Libraries\detours\Header Files + shared\libraries\detours\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include - External Libraries\imgui\Header Files + shared\libraries\imgui\include Header Files @@ -186,304 +190,307 @@ Header Files - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files + shared\libraries\spdlog\include - External Libraries\spdlog\Header Files\cfg + shared\libraries\spdlog\include\cfg - External Libraries\spdlog\Header Files\cfg + shared\libraries\spdlog\include\cfg - External Libraries\spdlog\Header Files\cfg + shared\libraries\spdlog\include\cfg - External Libraries\spdlog\Header Files\cfg + shared\libraries\spdlog\include\cfg - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\details + shared\libraries\spdlog\include\details - External Libraries\spdlog\Header Files\fmt + shared\libraries\spdlog\include\fmt - External Libraries\spdlog\Header Files\fmt + shared\libraries\spdlog\include\fmt - External Libraries\spdlog\Header Files\fmt + shared\libraries\spdlog\include\fmt - External Libraries\spdlog\Header Files\fmt + shared\libraries\spdlog\include\fmt - External Libraries\spdlog\Header Files\fmt + shared\libraries\spdlog\include\fmt - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\fmt\bundled + shared\libraries\spdlog\include\fmt\bundled - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks - External Libraries\spdlog\Header Files\sinks + shared\libraries\spdlog\include\sinks Header Files - - Header Files - Header Files - - Header Files + + shared\include - - Header Files + + shared\include + + + shared\include + + + shared\include - Header Files + core\include External Libraries\imgui\Header Files @@ -494,7 +501,7 @@ - Resource Files + core\resource \ No newline at end of file diff --git a/r5dev/src/gameclasses.cpp b/r5dev/src/gameclasses.cpp index 336dc377..6f22b711 100644 --- a/r5dev/src/gameclasses.cpp +++ b/r5dev/src/gameclasses.cpp @@ -6,11 +6,13 @@ namespace GameGlobals bool IsInitialized = false; CHostState* HostState = nullptr; CInputSystem* InputSystem = nullptr; + CCVar* Cvar = nullptr; void InitGameGlobals() { HostState = reinterpret_cast(0x141736120); // Get CHostState from memory. InputSystem = *reinterpret_cast(0x14D40B380); // Get IInputSystem from memory. + Cvar = *reinterpret_cast(0x14D40B348); // Get CCVar from memory. IsInitialized = true; } diff --git a/r5dev/src/hooks.cpp b/r5dev/src/hooks.cpp index aee0c18f..d1bc3689 100644 --- a/r5dev/src/hooks.cpp +++ b/r5dev/src/hooks.cpp @@ -155,7 +155,7 @@ int HMSG_EngineError(char* fmt, va_list args) } // TODO: turn this into a playerstruct constructor if it ever becomes necessary -bool HCVEngineClient_IsPersistenceDataAvailable(__int64 thisptr, int client) +bool HCVEngineServer_IsPersistenceDataAvailable(__int64 thisptr, int client) { static bool isPersistenceVarSet[256]; @@ -205,7 +205,7 @@ void InstallENHooks() /////////////////////////////////////////////////////////////////////////////// // Hook Utility functions DetourAttach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); - DetourAttach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineClient_IsPersistenceDataAvailable); + DetourAttach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineServer_IsPersistenceDataAvailable); /////////////////////////////////////////////////////////////////////////////// // Commit the transaction @@ -241,7 +241,7 @@ void RemoveENHooks() /////////////////////////////////////////////////////////////////////////////// // Unhook Utility functions DetourDetach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); - DetourDetach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineClient_IsPersistenceDataAvailable); + DetourDetach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineServer_IsPersistenceDataAvailable); /////////////////////////////////////////////////////////////////////////////// // Commit the transaction diff --git a/r5dev/src/overlay.cpp b/r5dev/src/overlay.cpp index 3cb81728..21fd4a88 100644 --- a/r5dev/src/overlay.cpp +++ b/r5dev/src/overlay.cpp @@ -356,12 +356,11 @@ CCompanion::CCompanion() void CCompanion::UpdateMyServerInfo() { MyServer.map = GameGlobals::HostState->m_levelName; - MyServer.port = ((CVValue_t*)(0x141734DD0 + 0x58))->m_pszString; } void CCompanion::UpdateHostingStatus() { - if (!GameGlobals::HostState) // Is HostState valid? + if (!GameGlobals::HostState || !GameGlobals::Cvar) // Is HostState and Cvar valid? return; GameGlobals::HostState->m_bActiveGame ? HostingStatus = EHostStatus::Hosting : HostingStatus = EHostStatus::NotHosting; // Are we hosting a server? @@ -431,12 +430,13 @@ void CCompanion::SendHostingPostRequest() nlohmann::json body = nlohmann::json::object(); body["name"] = MyServer.name; body["map"] = MyServer.map; - body["port"] = MyServer.port; + static ConVar* hostport = GameGlobals::Cvar->FindVar("hostport"); // static since it won't move memory locations. + body["port"] = hostport->m_pzsCurrentValue; //body["port"] = MyServer.port; body["password"] = MyServer.password; - std::string body_str = body.dump(); - + + std::string body_str = body.dump(); #ifdef OVERLAY_DEBUG std::cout << " [+CCompanion+] Sending request now, Body: " << body_str << "\n"; @@ -740,8 +740,8 @@ void CCompanion::HostServerSection() { static std::string ServerNameErr = ""; - ImGui::InputTextWithHint("Server Name##ServerHost_ServerName", "Server Name (Required)", &MyServer.name); - ImGui::InputTextWithHint("Server Name##ServerHost_ServerPassword", "Password (Optional)", &MyServer.password); + ImGui::InputTextWithHint("##ServerHost_ServerName", "Server Name (Required)", &MyServer.name); + ImGui::InputTextWithHint("##ServerHost_ServerPassword", "Password (Optional)", &MyServer.password); ImGui::Spacing(); if (ImGui::BeginCombo("Map##ServerHost_MapListBox", MyServer.map.c_str())) { diff --git a/r5dev/include/address.h b/shared/include/address.h similarity index 100% rename from r5dev/include/address.h rename to shared/include/address.h diff --git a/r5dev/include/httplib.h b/shared/include/httplib.h similarity index 100% rename from r5dev/include/httplib.h rename to shared/include/httplib.h diff --git a/r5dev/include/json.hpp b/shared/include/json.hpp similarity index 100% rename from r5dev/include/json.hpp rename to shared/include/json.hpp diff --git a/r5dev/include/utility.h b/shared/include/utility.h similarity index 100% rename from r5dev/include/utility.h rename to shared/include/utility.h diff --git a/r5dev/src/utility.cpp b/shared/utility.cpp similarity index 99% rename from r5dev/src/utility.cpp rename to shared/utility.cpp index 9e966e4b..9e85ef8d 100644 --- a/r5dev/src/utility.cpp +++ b/shared/utility.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "utility.h" -#include "hooks.h" /*----------------------------------------------------------------------------- * _utility.cpp