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/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..1d19feb3 --- /dev/null +++ b/r5dedicated/pch.h @@ -0,0 +1,39 @@ +#pragma once +#pragma message("Pre-compiling DEDICATED 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..ce43ea49 --- /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..68571f2a --- /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 + + + + + shared + + + core + + + core + + + core + + + hooks + + + hooks\netchannel + + + hooks\concommand + + + hooks\cvengineserver + + + hooks\squirrel + + + hooks\other + + + hooks\other + + + hooks\iconvar + + + + + 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/pch.h b/r5dev/include/pch.h index d05f4e31..3de39433 100644 --- a/r5dev/include/pch.h +++ b/r5dev/include/pch.h @@ -1,10 +1,10 @@ #pragma once #pragma message("Pre-compiling headers.\n") -#include "httplib.h" #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition. #include #include +#include #include #include #include @@ -18,7 +18,6 @@ #include #include #include -#include #include @@ -29,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 271412f4..4e4a7042 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)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,15 +285,16 @@ - + + + + - - @@ -302,30 +302,37 @@ - NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing NotUsing + NotUsing + Use pch.h @@ -361,6 +368,8 @@ Create pch.h + Create + pch.h Use diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index 069110c7..d2a08ea6 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -1,6 +1,21 @@  + + {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 @@ -9,54 +24,44 @@ {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 - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + {7cef4f92-94d9-43af-bea5-c6963d68fff2} - - {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} - - {e38cd6c5-b355-4bb5-bf65-bfd51fef296b} - - + {6faf53e7-9be1-439f-92f9-16ab96c005b7} + + {e38cd6c5-b355-4bb5-bf65-bfd51fef296b} + - - Source Files - Source Files @@ -69,27 +74,6 @@ 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 @@ -105,8 +89,35 @@ Source Files + + shared + + + 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 @@ -128,41 +139,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 @@ -177,304 +185,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 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/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/shared/utility.cpp b/shared/utility.cpp new file mode 100644 index 00000000..9e85ef8d --- /dev/null +++ b/shared/utility.cpp @@ -0,0 +1,191 @@ +#include "pch.h" +#include "utility.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 + +std::uint8_t* PatternScan(const char* module, const char* signature) +{ + static auto PatternToBytes = [](const char* pattern) + { + char* PatternStart = const_cast(pattern); // Cast const away and get start of pattern. + char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern. + + std::vector Bytes = std::vector{ }; // Initialize byte vector. + + for (char* CurrentByte = PatternStart; CurrentByte < PatternEnd; ++CurrentByte) + { + if (*CurrentByte == '?') // Is current char(byte) a wildcard? + { + ++CurrentByte; // Skip 1 character. + + if (*CurrentByte == '?') // Is it a double wildcard pattern? + ++CurrentByte; // If so skip the next space that will come up so we can reach the next byte. + + Bytes.push_back(-1); // Push the byte back as invalid. + } + else + { + // https://stackoverflow.com/a/43860875/12541255 + // Here we convert our string to a unsigned long integer. We pass our string then we use 16 as the base because we want it as hexadecimal. + // Afterwards we push the byte into our bytes vector. + Bytes.push_back(std::strtoul(CurrentByte, &CurrentByte, 16)); + } + } + return Bytes; + }; + + const MODULEINFO mInfo = GetModuleInfo(module); // Get module info. + const DWORD64 SizeOfModule = (DWORD64)mInfo.SizeOfImage; // Grab the module size. + std::uint8_t* ScanBytes = reinterpret_cast(mInfo.lpBaseOfDll); // Get the base of the module. + + const std::vector PatternBytes = PatternToBytes(signature); // Convert our pattern to a byte array. + const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes. + + for (DWORD i = 0ul; i < SizeOfModule - BytesInfo.first; ++i) + { + bool FoundAddress = true; + + for (DWORD j = 0ul; j < BytesInfo.first; ++j) + { + // If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard + // our if clause will be false. + if (ScanBytes[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1) + { + FoundAddress = false; + break; + } + } + + if (FoundAddress) + { + return &ScanBytes[i]; + } + + } + + return nullptr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +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, int nFunc, const void* pData, int nSize) +{ + static std::atomic i, j, k = 0; + static char ascii[17] = { 0 }; + static auto logger = spdlog::get("default_logger"); + auto pattern = std::make_unique("%v", spdlog::pattern_time_type::local, std::string("")); + + // Loop until the function returned to the first caller + while (k == 1) { /*Sleep(75);*/ } + + k = 1; + ascii[16] = '\0'; + + // Add new loggers here to replace the placeholder + if (nFunc == 0) { logger = g_spdnetchan_logger; } + + // Add timestamp + logger->set_level(spdlog::level::trace); + logger->set_pattern("%v [%H:%M:%S.%f]"); + logger->trace("---------------------------------------------------------"); + + // Disable EOL and create block header + logger->set_formatter(std::move(pattern)); + logger->trace("{:s} ---- LEN BYTES: {}\n:\n", szHeader, nSize); + logger->trace("-------- 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) { logger->trace(" 0x{:04X} ", i); } + logger->trace("{:02x} ", ((unsigned char*)pData)[i]); + + 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) + { + logger->trace(" "); + + if ((i + 1) % 16 == 0) + { + if (i + 1 == nSize) + { + logger->trace("{:s}\n", ascii); + logger->trace("---------------------------------------------------------------------------\n"); + logger->trace("\n"); + } + else + { + i++; + logger->trace("{:s}\n ", ascii); + logger->trace("0x{:04X} ", i--); + } + } + else if (i + 1 == nSize) + { + ascii[(i + 1) % 16] = '\0'; + if ((i + 1) % 16 <= 8) + { + logger->trace(" "); + } + for (j = (i + 1) % 16; j < 16; j++) + { + logger->trace(" "); + } + logger->trace("{:s}\n", ascii); + logger->trace("---------------------------------------------------------------------------\n"); + logger->trace("\n"); + } + } + } + k = 0; + /////////////////////////////////////////////////////////////////////////// +} \ No newline at end of file