diff --git a/external/minhook/include/MinHook.h b/external/minhook/include/MinHook.h new file mode 100644 index 00000000..15c0a875 --- /dev/null +++ b/external/minhook/include/MinHook.h @@ -0,0 +1,186 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) + #error MinHook supports only x86 and x64 systems. +#endif + +#include + +// MinHook Error Codes. +typedef enum MH_STATUS +{ + // Unknown error. Should not be returned. + MH_UNKNOWN = -1, + + // Successful. + MH_OK = 0, + + // MinHook is already initialized. + MH_ERROR_ALREADY_INITIALIZED, + + // MinHook is not initialized yet, or already uninitialized. + MH_ERROR_NOT_INITIALIZED, + + // The hook for the specified target function is already created. + MH_ERROR_ALREADY_CREATED, + + // The hook for the specified target function is not created yet. + MH_ERROR_NOT_CREATED, + + // The hook for the specified target function is already enabled. + MH_ERROR_ENABLED, + + // The hook for the specified target function is not enabled yet, or already + // disabled. + MH_ERROR_DISABLED, + + // The specified pointer is invalid. It points the address of non-allocated + // and/or non-executable region. + MH_ERROR_NOT_EXECUTABLE, + + // The specified target function cannot be hooked. + MH_ERROR_UNSUPPORTED_FUNCTION, + + // Failed to allocate memory. + MH_ERROR_MEMORY_ALLOC, + + // Failed to change the memory protection. + MH_ERROR_MEMORY_PROTECT, + + // The specified module is not loaded. + MH_ERROR_MODULE_NOT_FOUND, + + // The specified function is not found. + MH_ERROR_FUNCTION_NOT_FOUND +} +MH_STATUS; + +// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, +// MH_QueueEnableHook or MH_QueueDisableHook. +#define MH_ALL_HOOKS NULL + +#ifdef __cplusplus +extern "C" { +#endif + + // Initialize the MinHook library. You must call this function EXACTLY ONCE + // at the beginning of your program. + MH_STATUS WINAPI MH_Initialize(VOID); + + // Uninitialize the MinHook library. You must call this function EXACTLY + // ONCE at the end of your program. + MH_STATUS WINAPI MH_Uninitialize(VOID); + + // Creates a Hook for the specified target function, in disabled state. + // Parameters: + // pTarget [in] A pointer to the target function, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + // ppTarget [out] A pointer to the target function, which will be used + // with other functions. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); + + // Removes an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); + + // Enables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // enabled in one go. + MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); + + // Disables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // disabled in one go. + MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); + + // Queues to enable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be enabled. + MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); + + // Queues to disable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be disabled. + MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); + + // Applies all queued changes in one go. + MH_STATUS WINAPI MH_ApplyQueued(VOID); + + // Translates the MH_STATUS to its name as a string. + const char * WINAPI MH_StatusToString(MH_STATUS status); + +#ifdef __cplusplus +} +#endif + diff --git a/external/minhook/lib/libMinHook.x64.lib b/external/minhook/lib/libMinHook.x64.lib new file mode 100644 index 00000000..27efcff2 Binary files /dev/null and b/external/minhook/lib/libMinHook.x64.lib differ diff --git a/r5dedicated/cnetchan.cpp b/r5dedicated/cnetchan.cpp deleted file mode 100644 index bfd915ba..00000000 --- a/r5dedicated/cnetchan.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#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 deleted file mode 100644 index b0e425db..00000000 --- a/r5dedicated/cnetchan.h +++ /dev/null @@ -1,34 +0,0 @@ -#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 deleted file mode 100644 index bbe14b4d..00000000 --- a/r5dedicated/concommand.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#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 deleted file mode 100644 index 6442c1e1..00000000 --- a/r5dedicated/concommand.h +++ /dev/null @@ -1,7 +0,0 @@ -#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 index 8c22fb47..3d77c848 100644 --- a/r5dedicated/console.cpp +++ b/r5dedicated/console.cpp @@ -1,8 +1,6 @@ #include "pch.h" #include "hooks.h" #include "console.h" -#include "iconvar.h" -#include "concommand.h" //############################################################################# // INITIALIZATION @@ -71,8 +69,8 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) /////////////////////////////////////////////////////////////////////// // Engine toggles - if (sCommand == "toggle net") { ToggleNetTrace(); continue; } - if (sCommand == "toggle dev") { ToggleDevCommands(); continue; } + if (sCommand == "toggle net") { Hooks::ToggleNetHooks(); continue; } + if (sCommand == "toggle dev") { Hooks::ToggleDevCommands(); continue; } if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } /////////////////////////////////////////////////////////////////////// // Debug toggles @@ -80,12 +78,12 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) if (sCommand == "console test") { g_bDebugConsole = !g_bDebugConsole; continue; } /////////////////////////////////////////////////////////////////////// // Exec toggles - if (sCommand == "1") { org_CommandExecute(NULL, "exec autoexec_dev"); } + if (sCommand == "1") { addr_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()); + addr_CommandExecute(NULL, sCommand.c_str()); sCommand.clear(); /////////////////////////////////////////////////////////////////////// diff --git a/r5dedicated/cvengineserver.cpp b/r5dedicated/cvengineserver.cpp index bf15cee5..450639f4 100644 --- a/r5dedicated/cvengineserver.cpp +++ b/r5dedicated/cvengineserver.cpp @@ -1,10 +1,15 @@ #include "pch.h" -#include "cvengineserver.h" +#include "hooks.h" + +namespace Hooks +{ + IsPersistenceDataAvailableFn originalIsPersistenceDataAvailable = nullptr; +} //----------------------------------------------------------------------------- -// Sets the persistence var in the playerstruct to ready for each client +// Sets the persistence var in the playerstruct to ready for each client //----------------------------------------------------------------------------- -bool HPersistence_IsAvailable(__int64 thisptr, int client) +bool Hooks::IsPersistenceDataAvailable(__int64 thisptr, int client) { static bool isPersistenceVarSet[256]; @@ -27,16 +32,5 @@ bool HPersistence_IsAvailable(__int64 thisptr, int client) 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); + return originalIsPersistenceDataAvailable(thisptr, client); } \ No newline at end of file diff --git a/r5dedicated/cvengineserver.h b/r5dedicated/cvengineserver.h deleted file mode 100644 index 933c2a15..00000000 --- a/r5dedicated/cvengineserver.h +++ /dev/null @@ -1,8 +0,0 @@ -#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 index 8d135d1e..89df758c 100644 --- a/r5dedicated/dllmain.cpp +++ b/r5dedicated/dllmain.cpp @@ -10,7 +10,7 @@ void InitializeR5Dedicated() { SetupConsole(); - InstallHooks(); + Hooks::InstallHooks(); printf("+-----------------------------------------------------------------------------+\n"); printf("| R5 DEDICATED SERVER --------------------------------------------------- |\n"); printf("+-----------------------------------------------------------------------------+\n"); @@ -20,7 +20,7 @@ void InitializeR5Dedicated() void TerminateR5Dedicated() { FreeConsole(); - RemoveHooks(); + Hooks::RemoveHooks(); } //############################################################################# diff --git a/r5dedicated/hooks.cpp b/r5dedicated/hooks.cpp index 90e52c41..67fa4dc9 100644 --- a/r5dedicated/hooks.cpp +++ b/r5dedicated/hooks.cpp @@ -1,78 +1,99 @@ #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() +void Hooks::InstallHooks() { /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction, to hook the the process - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + // Initialize Minhook + MH_Initialize(); + + // Hook Squirrel functions + MH_CreateHook(addr_SQVM_Print, &Hooks::SQVM_Print, NULL); + MH_CreateHook(addr_SQVM_LoadRson, &Hooks::SQVM_LoadRson, reinterpret_cast(&originalSQVM_LoadRson)); + MH_CreateHook(addr_SQVM_LoadScript, &Hooks::SQVM_LoadScript, reinterpret_cast(&originalSQVM_LoadScript)); /////////////////////////////////////////////////////////////////////////////// - // Hook functions - AttachIConVarHooks(); - AttachConCommandHooks(); - AttachCEngineServerHooks(); - AttachSQVMHooks(); - AttachMSGBoxHooks(); + // Hook Game Functions + // MH_CreateHook(addr_CHLClient_FrameStageNotify, &Hooks::FrameStageNotify, reinterpret_cast(&originalFrameStageNotify)); + MH_CreateHook(addr_CVEngineServer_IsPersistenceDataAvailable, &Hooks::IsPersistenceDataAvailable, reinterpret_cast(&originalIsPersistenceDataAvailable)); /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - if (DetourTransactionCommit() != NO_ERROR) - { - // Failed to hook into the process, terminate - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } + // Hook Netchan functions + MH_CreateHook(addr_NET_ReceiveDatagram, &Hooks::NET_ReceiveDatagram, reinterpret_cast(&originalNET_ReceiveDatagram)); + MH_CreateHook(addr_NET_SendDatagram, &Hooks::NET_SendDatagram, reinterpret_cast(&originalNET_SendDatagram)); + + /////////////////////////////////////////////////////////////////////////////// + // Hook ConVar | ConCommand functions. + MH_CreateHook(addr_ConVar_IsFlagSet, &Hooks::ConVar_IsFlagSet, NULL); + MH_CreateHook(addr_ConCommand_IsFlagSet, &Hooks::ConCommand_IsFlagSet, NULL); + + /////////////////////////////////////////////////////////////////////////////// + // Hook Utility functions + MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast(&originalMSG_EngineError)); + + /////////////////////////////////////////////////////////////////////////////// + // Enable Squirrel hooks + MH_EnableHook(addr_SQVM_Print); + MH_EnableHook(addr_SQVM_LoadRson); + MH_EnableHook(addr_SQVM_LoadScript); + + /////////////////////////////////////////////////////////////////////////////// + // Enable Game hooks + MH_EnableHook(addr_CHLClient_FrameStageNotify); + MH_EnableHook(addr_CVEngineServer_IsPersistenceDataAvailable); + + /////////////////////////////////////////////////////////////////////////////// + // Enabled Utility hooks + MH_EnableHook(addr_MSG_EngineError); InstallOpcodes(); } -void RemoveHooks() +void Hooks::RemoveHooks() { /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction, to unhook the the process - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + // Unhook Squirrel functions + MH_RemoveHook(addr_SQVM_Print); + MH_RemoveHook(addr_SQVM_LoadRson); + MH_RemoveHook(addr_SQVM_LoadScript); /////////////////////////////////////////////////////////////////////////////// - // Unhook functions - DetachIConVarHooks(); - DetachConCommandHooks(); - DetachCEngineServerHooks(); - DetachSQVMHooks(); - DetachMSGBoxHooks(); + // Unhook Game Functions + MH_RemoveHook(addr_CHLClient_FrameStageNotify); + MH_RemoveHook(addr_CVEngineServer_IsPersistenceDataAvailable); /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - DetourTransactionCommit(); + // Unhook Netchan functions + MH_RemoveHook(addr_NET_ReceiveDatagram); + MH_RemoveHook(addr_NET_SendDatagram); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook ConVar | ConCommand functions. + MH_RemoveHook(addr_ConVar_IsFlagSet); + MH_RemoveHook(addr_ConCommand_IsFlagSet); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook Utility functions + MH_RemoveHook(addr_MSG_EngineError); + + /////////////////////////////////////////////////////////////////////////////// + // Reset Minhook + MH_Uninitialize(); } //################################################################################# // TOGGLES //################################################################################# -void ToggleDevCommands() +void Hooks::ToggleDevCommands() { - static bool bDev = true; - - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + static bool bDev = true;; if (!bDev) { - AttachIConVarHooks(); - AttachConCommandHooks(); + MH_EnableHook(addr_ConVar_IsFlagSet); + MH_EnableHook(addr_ConCommand_IsFlagSet); printf("\n"); printf("+--------------------------------------------------------+\n"); printf("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n"); @@ -82,8 +103,8 @@ void ToggleDevCommands() } else { - DetachIConVarHooks(); - DetachConCommandHooks(); + MH_DisableHook(addr_ConVar_IsFlagSet); + MH_DisableHook(addr_ConCommand_IsFlagSet); printf("\n"); printf("+--------------------------------------------------------+\n"); printf("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n"); @@ -91,24 +112,17 @@ void ToggleDevCommands() printf("\n"); } - if (DetourTransactionCommit() != NO_ERROR) - { - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } - bDev = !bDev; } -void ToggleNetTrace() +void Hooks::ToggleNetHooks() { static bool bNet = true; - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - if (!bNet) { - AttachCNetChanHooks(); + MH_EnableHook(addr_NET_ReceiveDatagram); + MH_EnableHook(addr_NET_SendDatagram); printf("\n"); printf("+--------------------------------------------------------+\n"); printf("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n"); @@ -117,7 +131,8 @@ void ToggleNetTrace() } else { - DetachCNetChanHooks(); + MH_DisableHook(addr_NET_ReceiveDatagram); + MH_DisableHook(addr_NET_SendDatagram); printf("\n"); printf("+--------------------------------------------------------+\n"); printf("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n"); @@ -125,10 +140,5 @@ void ToggleNetTrace() printf("\n"); } - if (DetourTransactionCommit() != NO_ERROR) - { - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } - bNet = !bNet; } diff --git a/r5dedicated/hooks.h b/r5dedicated/hooks.h index cdded7a3..66ab2187 100644 --- a/r5dedicated/hooks.h +++ b/r5dedicated/hooks.h @@ -1,11 +1,5 @@ #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 { @@ -13,77 +7,130 @@ namespace #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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_ConVar_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_SQVM_Print, 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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_CVEngineServer_IsPersistenceDataAvailable, 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()); + FUNC_AT_ADDRESS(addr_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; + // Un-used atm. + // DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45")); 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); + PRINT_ADDRESS("CommandExecute", addr_CommandExecute); + PRINT_ADDRESS("ConVar_IsFlagSet", addr_ConVar_IsFlagSet); + PRINT_ADDRESS("ConCommand_IsFlagSet", addr_ConCommand_IsFlagSet); + PRINT_ADDRESS("SQVM_Print", addr_SQVM_Print); + PRINT_ADDRESS("SQVM_LoadScript", addr_SQVM_LoadScript); + PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson); + PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram); + PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram); + PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify); + PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable); + PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError); std::cout << "+--------------------------------------------------------+" << std::endl; // TODO implement error handling when sigscan fails or result is 0 } } -void InstallHooks(); -void RemoveHooks(); +inline bool g_bDebugLoading = false; +inline bool g_bReturnAllFalse = false; +inline bool g_bDebugConsole = false; -void ToggleDevCommands(); -void ToggleNetTrace(); \ No newline at end of file +namespace Hooks +{ +#pragma region CHLClient +// void __fastcall FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage); + +// using FrameStageNotifyFn = void(__fastcall*)(CHLClient*, ClientFrameStage_t); +// extern FrameStageNotifyFn originalFrameStageNotify; +#pragma endregion + +#pragma region Squirrel + void* SQVM_Print(void* sqvm, char* fmt, ...); + __int64 SQVM_LoadRson(const char* rson_name); + bool SQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag); + + using SQVM_LoadRsonFn = __int64(*)(const char*); + extern SQVM_LoadRsonFn originalSQVM_LoadRson; + + using SQVM_LoadScriptFn = bool(*)(void*, const char*, const char*, int); + extern SQVM_LoadScriptFn originalSQVM_LoadScript; +#pragma endregion + +#pragma region CVEngineServer + bool IsPersistenceDataAvailable(__int64 thisptr, int client); + + using IsPersistenceDataAvailableFn = bool(*)(__int64, int); + extern IsPersistenceDataAvailableFn originalIsPersistenceDataAvailable; +#pragma endregion + +#pragma region NetChannel + bool NET_ReceiveDatagram(int sock, void* inpacket, bool raw); + unsigned int NET_SendDatagram(SOCKET s, const char* buf, int len, int flags); + + using NET_ReceiveDatagramFn = bool(*)(int, void*, bool); + extern NET_ReceiveDatagramFn originalNET_ReceiveDatagram; + + using NET_SendDatagramFn = unsigned int(*)(SOCKET, const char*, int, int); + extern NET_SendDatagramFn originalNET_SendDatagram; +#pragma endregion + +#pragma region ConVar + bool ConVar_IsFlagSet(int** cvar, int flag); + bool ConCommand_IsFlagSet(int* cmd, int flag); +#pragma endregion + +#pragma region Other + int MSG_EngineError(char* fmt, va_list args); + + using MSG_EngineErrorFn = int(*)(char*, va_list); + extern MSG_EngineErrorFn originalMSG_EngineError; +#pragma endregion + + void InstallHooks(); + void RemoveHooks(); + void ToggleNetHooks(); + void ToggleDevCommands(); +} \ No newline at end of file diff --git a/r5dedicated/iconvar.cpp b/r5dedicated/iconvar.cpp index 169c9060..75002dff 100644 --- a/r5dedicated/iconvar.cpp +++ b/r5dedicated/iconvar.cpp @@ -1,12 +1,13 @@ #include "pch.h" -#include "iconvar.h" +#include "hooks.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) + +bool Hooks::ConVar_IsFlagSet(int** cvar, int flag) { int real_flags = *(*(cvar + (72 / (sizeof(void*)))) + (56 / sizeof(int))); if (g_bDebugConsole) @@ -24,16 +25,46 @@ bool HConVar_IsFlagSet(int** cvar, int flag) } if (flag & 0x80000) { return true; } - if (!g_bReturnAllFalse) { return (real_flags & flag) != 0; } - else { return false; } // Returning false on all queries may cause problems + if (!g_bReturnAllFalse) + { + return (real_flags & flag) != 0; + } + else + { + return false; + } } -void AttachIConVarHooks() -{ - DetourAttach((LPVOID*)&org_IConVar_IsFlagSet, &HConVar_IsFlagSet); -} +//----------------------------------------------------------------------------- +// Purpose: test each ConCommand query before execution +// Input : *cmd - flag +// Output : true if execution is not permitted, false if permitted +//----------------------------------------------------------------------------- -void DetachIConVarHooks() +bool Hooks::ConCommand_IsFlagSet(int* cmd, int flag) { - DetourDetach((LPVOID*)&org_IConVar_IsFlagSet, &HConVar_IsFlagSet); + 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; + } } \ No newline at end of file diff --git a/r5dedicated/iconvar.h b/r5dedicated/iconvar.h deleted file mode 100644 index 25880877..00000000 --- a/r5dedicated/iconvar.h +++ /dev/null @@ -1,7 +0,0 @@ -#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 index 24e1ea15..58a7727b 100644 --- a/r5dedicated/msgbox.cpp +++ b/r5dedicated/msgbox.cpp @@ -1,24 +1,19 @@ #include "pch.h" #include "hooks.h" +namespace Hooks +{ + MSG_EngineErrorFn originalMSG_EngineError = nullptr; +} + //----------------------------------------------------------------------------- // Engine Error message box //----------------------------------------------------------------------------- -int HMSG_EngineError(char* fmt, va_list args) + +int Hooks::MSG_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); + return originalMSG_EngineError(fmt, args); } \ No newline at end of file diff --git a/r5dedicated/msgbox.h b/r5dedicated/msgbox.h deleted file mode 100644 index ea1e094d..00000000 --- a/r5dedicated/msgbox.h +++ /dev/null @@ -1,7 +0,0 @@ -#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/net.cpp b/r5dedicated/net.cpp new file mode 100644 index 00000000..340a4be2 --- /dev/null +++ b/r5dedicated/net.cpp @@ -0,0 +1,71 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + NET_ReceiveDatagramFn originalNET_ReceiveDatagram = nullptr; + NET_SendDatagramFn originalNET_SendDatagram = nullptr; +} + +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; +}; + +//----------------------------------------------------------------------------- +// Hook and log the receive datagram +//----------------------------------------------------------------------------- + +bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) +{ + bool result = originalNET_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 Hooks::NET_SendDatagram(SOCKET s, const char* buf, int len, int flags) +{ + unsigned int result = originalNET_SendDatagram(s, buf, len, flags); + if (result) + { + /////////////////////////////////////////////////////////////////////////// + // Log transmitted packet data + HexDump("[+] NET_SendDatagram", 0, buf, len); + } + + return result; +} \ No newline at end of file diff --git a/r5dedicated/pch.h b/r5dedicated/pch.h index 975aba77..7159ba8a 100644 --- a/r5dedicated/pch.h +++ b/r5dedicated/pch.h @@ -3,7 +3,7 @@ #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition. #include -#include +#include #include #include #include diff --git a/r5dedicated/r5dedicated.vcxproj b/r5dedicated/r5dedicated.vcxproj index 7e6fe2bd..055520ed 100644 --- a/r5dedicated/r5dedicated.vcxproj +++ b/r5dedicated/r5dedicated.vcxproj @@ -87,8 +87,8 @@ 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) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)external\minhook\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dedicated;$(IncludePath) + $(SolutionDir)external\minhook\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(LibraryPath) @@ -164,19 +164,18 @@ true true true - detours.lib;%(AdditionalDependencies) + libMinHook.x64.lib r5dedicated.def - - + Create @@ -186,6 +185,7 @@ + @@ -284,17 +284,11 @@ - - - - - - diff --git a/r5dedicated/r5dedicated.vcxproj.filters b/r5dedicated/r5dedicated.vcxproj.filters index b0039216..c95890fb 100644 --- a/r5dedicated/r5dedicated.vcxproj.filters +++ b/r5dedicated/r5dedicated.vcxproj.filters @@ -17,27 +17,9 @@ {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} @@ -62,6 +44,42 @@ {eaefe9b7-d14d-48b6-878a-53a5ada7454b} + + {245e8064-9b24-4631-9326-340dfb761fde} + + + {485b5648-149f-4664-a961-be9cd520e9e3} + + + {f5326cf2-826e-4499-98de-e818e096939d} + + + {4c680991-cc41-4265-a6f3-b46d698bd72f} + + + {8aac7eb6-9810-4fa2-bbfe-499fb2950f01} + + + {f28b1a49-9b41-48d2-9462-1674af3d72a2} + + + {cc424eef-0c7a-4fb0-9d84-30bf8db2e253} + + + {74afa89f-72af-4e13-aa90-70f7a1957154} + + + {05e6e9a7-801b-49b0-9c5a-21c4868befb7} + + + {06affed3-5a59-4b95-88ca-72d92c91909b} + + + {338a4fb7-7519-4628-9206-679d33824965} + + + {31cdde4d-3641-497c-9b34-20d3d7c89d87} + @@ -79,36 +97,12 @@ 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 @@ -391,6 +385,15 @@ shared\libraries\spdlog\include\sinks + + shared\libraries\minhook\include + + + r5-sdk\include + + + hooks\include + @@ -402,33 +405,30 @@ core - - hooks - - - hooks\netchannel - - - hooks\concommand + + hooks\src\netchannel - hooks\cvengineserver + hooks\src\cvengineserver - hooks\squirrel + hooks\src\squirrel - hooks\other - - - hooks\other - - - hooks\iconvar + hooks\src\other shared + + hooks\src\iconvar + + + r5-sdk\src + + + hooks\src + diff --git a/r5dedicated/sqvm.cpp b/r5dedicated/sqvm.cpp index b94a76b3..c3654922 100644 --- a/r5dedicated/sqvm.cpp +++ b/r5dedicated/sqvm.cpp @@ -1,11 +1,18 @@ #include "pch.h" -#include "sqvm.h" +#include "hooks.h" + +namespace Hooks +{ + SQVM_LoadRsonFn originalSQVM_LoadRson = nullptr; + SQVM_LoadScriptFn originalSQVM_LoadScript = nullptr; +} //--------------------------------------------------------------------------------- // Print the output of the VM. // TODO: separate SV CL and UI //--------------------------------------------------------------------------------- -void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...) + +void* Hooks::SQVM_Print(void* sqvm, char* fmt, ...) { va_list args; va_start(args, fmt); @@ -17,11 +24,13 @@ void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...) //--------------------------------------------------------------------------------- // Load the include file from the mods directory //--------------------------------------------------------------------------------- -__int64 HSQVM_LoadRson(const char* rson_name) + +__int64 Hooks::SQVM_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++) { @@ -31,15 +40,17 @@ __int64 HSQVM_LoadRson(const char* rson_name) } } + /////////////////////////////////////////////////////////////////////////////// // Returns the new path if the rson exists on the disk - if (FileExists(filepath) && org_SQVM_LoadRson(rson_name)) + if (FileExists(filepath) && originalSQVM_LoadRson(rson_name)) { printf("\n"); printf("##################################################\n"); printf("] '%s'\n", filepath); printf("##################################################\n"); printf("\n"); - return org_SQVM_LoadRson(filepath); + + return originalSQVM_LoadRson(filepath); } printf("\n"); @@ -47,17 +58,20 @@ __int64 HSQVM_LoadRson(const char* rson_name) printf("] '%s'\n", rson_name); printf("##################################################\n"); printf("\n"); - return org_SQVM_LoadRson(rson_name); + + return originalSQVM_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) + +bool Hooks::SQVM_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++) { @@ -70,9 +84,9 @@ bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_na { 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)) + if (FileExists(filepath) && originalSQVM_LoadScript(sqvm, filepath, script_name, flag)) { return true; } @@ -81,20 +95,5 @@ bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_na 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); + return originalSQVM_LoadScript(sqvm, script_path, script_name, flag); } \ No newline at end of file diff --git a/r5dedicated/sqvm.h b/r5dedicated/sqvm.h deleted file mode 100644 index 2798c54d..00000000 --- a/r5dedicated/sqvm.h +++ /dev/null @@ -1,10 +0,0 @@ -#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/console.h b/r5dev/include/console.h index a7879bb3..6e5f6aed 100644 --- a/r5dev/include/console.h +++ b/r5dev/include/console.h @@ -2,18 +2,4 @@ ///////////////////////////////////////////////////////////////////////////// // Initialization -void SetupConsole(); -void RemoveCMHooks(); -void ToggleDevCommands(); - -///////////////////////////////////////////////////////////////////////////// -// Hooks -bool HConVar_IsFlagSet(int** cvar, int flag); -bool HConCommand_IsFlagSet(int* cmd, int flag); - -///////////////////////////////////////////////////////////////////////////// -// Globals -inline bool g_bDebugConsole = false; -inline bool g_bReturnAllFalse = false; - -///////////////////////////////////////////////////////////////////////////// +void SetupConsole(); \ No newline at end of file diff --git a/r5dev/include/enums.h b/r5dev/include/enums.h index 4d75b736..9d0d470b 100644 --- a/r5dev/include/enums.h +++ b/r5dev/include/enums.h @@ -79,3 +79,255 @@ enum class DXGISwapChainVTbl : short GetFrameStatistics = 16, GetLastPresentCount = 17, }; + +#define MAX_SPLITSCREEN_CLIENT_BITS 2 +#define MAX_SPLITSCREEN_CLIENTS ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 4 + +enum +{ + MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS, + MOUSE_BUTTON_COUNT = 5, +}; + +enum JoystickAxis_t +{ + JOY_AXIS_X = 0, + JOY_AXIS_Y, + JOY_AXIS_Z, + JOY_AXIS_R, + JOY_AXIS_U, + JOY_AXIS_V, + MAX_JOYSTICK_AXES, +}; + +enum +{ + JOYSTICK_MAX_BUTTON_COUNT = 32, + JOYSTICK_POV_BUTTON_COUNT = 4, + JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, +}; + +#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) +#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) +#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) ) + +#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ) +#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ) +#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ) + +enum ButtonCode_t +{ + BUTTON_CODE_INVALID = -1, + BUTTON_CODE_NONE = 0, + + KEY_FIRST = 0, + + KEY_NONE = KEY_FIRST, + KEY_0, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_A, + KEY_B, + KEY_C, + KEY_D, + KEY_E, + KEY_F, + KEY_G, + KEY_H, + KEY_I, + KEY_J, + KEY_K, + KEY_L, + KEY_M, + KEY_N, + KEY_O, + KEY_P, + KEY_Q, + KEY_R, + KEY_S, + KEY_T, + KEY_U, + KEY_V, + KEY_W, + KEY_X, + KEY_Y, + KEY_Z, + KEY_PAD_0, + KEY_PAD_1, + KEY_PAD_2, + KEY_PAD_3, + KEY_PAD_4, + KEY_PAD_5, + KEY_PAD_6, + KEY_PAD_7, + KEY_PAD_8, + KEY_PAD_9, + KEY_PAD_DIVIDE, + KEY_PAD_MULTIPLY, + KEY_PAD_MINUS, + KEY_PAD_PLUS, + KEY_PAD_ENTER, + KEY_PAD_DECIMAL, + KEY_LBRACKET, + KEY_RBRACKET, + KEY_SEMICOLON, + KEY_APOSTROPHE, + KEY_BACKQUOTE, + KEY_COMMA, + KEY_PERIOD, + KEY_SLASH, + KEY_BACKSLASH, + KEY_MINUS, + KEY_EQUAL, + KEY_ENTER, + KEY_SPACE, + KEY_BACKSPACE, + KEY_TAB, + KEY_CAPSLOCK, + KEY_NUMLOCK, + KEY_ESCAPE, + KEY_SCROLLLOCK, + KEY_INSERT, + KEY_DELETE, + KEY_HOME, + KEY_END, + KEY_PAGEUP, + KEY_PAGEDOWN, + KEY_BREAK, + KEY_LSHIFT, + KEY_RSHIFT, + KEY_LALT, + KEY_RALT, + KEY_LCONTROL, + KEY_RCONTROL, + KEY_LWIN, + KEY_RWIN, + KEY_APP, + KEY_UP, + KEY_LEFT, + KEY_DOWN, + KEY_RIGHT, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_F11, + KEY_F12, + KEY_CAPSLOCKTOGGLE, + KEY_NUMLOCKTOGGLE, + KEY_SCROLLLOCKTOGGLE, + + KEY_LAST = KEY_SCROLLLOCKTOGGLE, + KEY_COUNT = KEY_LAST - KEY_FIRST + 1, + + // Mouse + MOUSE_FIRST = KEY_LAST + 1, + + MOUSE_LEFT = MOUSE_FIRST, + MOUSE_RIGHT, + MOUSE_MIDDLE, + MOUSE_4, + MOUSE_5, + MOUSE_WHEEL_UP, // A fake button which is 'pressed' and 'released' when the wheel is moved up + MOUSE_WHEEL_DOWN, // A fake button which is 'pressed' and 'released' when the wheel is moved down + + MOUSE_LAST = MOUSE_WHEEL_DOWN, + MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1, + + // Joystick + JOYSTICK_FIRST = MOUSE_LAST + 1, + + JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST, + JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_MAX_BUTTON_COUNT - 1), + JOYSTICK_FIRST_POV_BUTTON, + JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_POV_BUTTON_COUNT - 1), + JOYSTICK_FIRST_AXIS_BUTTON, + JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1), + + JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON, + + BUTTON_CODE_LAST, + BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1, + + // Helpers for XBox 360 + KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons + KEY_XBUTTON_RIGHT, + KEY_XBUTTON_DOWN, + KEY_XBUTTON_LEFT, + + KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons + KEY_XBUTTON_B, + KEY_XBUTTON_X, + KEY_XBUTTON_Y, + KEY_XBUTTON_LEFT_SHOULDER, + KEY_XBUTTON_RIGHT_SHOULDER, + KEY_XBUTTON_BACK, + KEY_XBUTTON_START, + KEY_XBUTTON_STICK1, + KEY_XBUTTON_STICK2, + KEY_XBUTTON_INACTIVE_START, + + KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE + KEY_XSTICK1_LEFT, // XAXIS NEGATIVE + KEY_XSTICK1_DOWN, // YAXIS POSITIVE + KEY_XSTICK1_UP, // YAXIS NEGATIVE + KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE + KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE + KEY_XSTICK2_RIGHT, // UAXIS POSITIVE + KEY_XSTICK2_LEFT, // UAXIS NEGATIVE + KEY_XSTICK2_DOWN, // VAXIS POSITIVE + KEY_XSTICK2_UP, // VAXIS NEGATIVE +}; + +// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them. + +enum KeyValuesTypes +{ + TYPE_NONE = 0x0, + TYPE_STRING = 0x1, + TYPE_INT = 0x2, + TYPE_FLOAT = 0x3, + TYPE_PTR = 0x4, + TYPE_WSTRING = 0x5, + TYPE_COLOR = 0x6, + TYPE_UINT64 = 0x7, + TYPE_COMPILED_INT_BYTE = 0x8, + TYPE_COMPILED_INT_0 = 0x9, + TYPE_COMPILED_INT_1 = 0xA, + TYPE_NUMTYPES = 0xB, +}; + +enum ClientFrameStage_t +{ + FRAME_UNDEFINED = -1, // (haven't run any frames yet) + FRAME_START, + + // A network packet is being recieved + FRAME_NET_UPDATE_START, + // Data has been received and we're going to start calling PostDataUpdate + FRAME_NET_UPDATE_POSTDATAUPDATE_START, + // Data has been received and we've called PostDataUpdate on all data recipients + FRAME_NET_UPDATE_POSTDATAUPDATE_END, + // We've received all packets, we can now do interpolation, prediction, etc.. + FRAME_NET_UPDATE_END, + + // We're about to start rendering the scene + FRAME_RENDER_START, + // We've finished rendering the scene. + FRAME_RENDER_END, + + FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE +}; diff --git a/r5dev/include/gameclasses.h b/r5dev/include/gameclasses.h index c495cc2e..e0cb8599 100644 --- a/r5dev/include/gameclasses.h +++ b/r5dev/include/gameclasses.h @@ -1,223 +1,6 @@ #pragma once #include "patterns.h" -///////////////////////////////////////////////////////////////////////////// -// Enums - -#define MAX_SPLITSCREEN_CLIENT_BITS 2 -#define MAX_SPLITSCREEN_CLIENTS ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 4 - -enum -{ - MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS, - MOUSE_BUTTON_COUNT = 5, -}; - -enum JoystickAxis_t -{ - JOY_AXIS_X = 0, - JOY_AXIS_Y, - JOY_AXIS_Z, - JOY_AXIS_R, - JOY_AXIS_U, - JOY_AXIS_V, - MAX_JOYSTICK_AXES, -}; - -enum -{ - JOYSTICK_MAX_BUTTON_COUNT = 32, - JOYSTICK_POV_BUTTON_COUNT = 4, - JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, -}; - -#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) -#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) -#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) ) - -#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ) -#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ) -#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ) - -enum ButtonCode_t -{ - BUTTON_CODE_INVALID = -1, - BUTTON_CODE_NONE = 0, - - KEY_FIRST = 0, - - KEY_NONE = KEY_FIRST, - KEY_0, - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_A, - KEY_B, - KEY_C, - KEY_D, - KEY_E, - KEY_F, - KEY_G, - KEY_H, - KEY_I, - KEY_J, - KEY_K, - KEY_L, - KEY_M, - KEY_N, - KEY_O, - KEY_P, - KEY_Q, - KEY_R, - KEY_S, - KEY_T, - KEY_U, - KEY_V, - KEY_W, - KEY_X, - KEY_Y, - KEY_Z, - KEY_PAD_0, - KEY_PAD_1, - KEY_PAD_2, - KEY_PAD_3, - KEY_PAD_4, - KEY_PAD_5, - KEY_PAD_6, - KEY_PAD_7, - KEY_PAD_8, - KEY_PAD_9, - KEY_PAD_DIVIDE, - KEY_PAD_MULTIPLY, - KEY_PAD_MINUS, - KEY_PAD_PLUS, - KEY_PAD_ENTER, - KEY_PAD_DECIMAL, - KEY_LBRACKET, - KEY_RBRACKET, - KEY_SEMICOLON, - KEY_APOSTROPHE, - KEY_BACKQUOTE, - KEY_COMMA, - KEY_PERIOD, - KEY_SLASH, - KEY_BACKSLASH, - KEY_MINUS, - KEY_EQUAL, - KEY_ENTER, - KEY_SPACE, - KEY_BACKSPACE, - KEY_TAB, - KEY_CAPSLOCK, - KEY_NUMLOCK, - KEY_ESCAPE, - KEY_SCROLLLOCK, - KEY_INSERT, - KEY_DELETE, - KEY_HOME, - KEY_END, - KEY_PAGEUP, - KEY_PAGEDOWN, - KEY_BREAK, - KEY_LSHIFT, - KEY_RSHIFT, - KEY_LALT, - KEY_RALT, - KEY_LCONTROL, - KEY_RCONTROL, - KEY_LWIN, - KEY_RWIN, - KEY_APP, - KEY_UP, - KEY_LEFT, - KEY_DOWN, - KEY_RIGHT, - KEY_F1, - KEY_F2, - KEY_F3, - KEY_F4, - KEY_F5, - KEY_F6, - KEY_F7, - KEY_F8, - KEY_F9, - KEY_F10, - KEY_F11, - KEY_F12, - KEY_CAPSLOCKTOGGLE, - KEY_NUMLOCKTOGGLE, - KEY_SCROLLLOCKTOGGLE, - - KEY_LAST = KEY_SCROLLLOCKTOGGLE, - KEY_COUNT = KEY_LAST - KEY_FIRST + 1, - - // Mouse - MOUSE_FIRST = KEY_LAST + 1, - - MOUSE_LEFT = MOUSE_FIRST, - MOUSE_RIGHT, - MOUSE_MIDDLE, - MOUSE_4, - MOUSE_5, - MOUSE_WHEEL_UP, // A fake button which is 'pressed' and 'released' when the wheel is moved up - MOUSE_WHEEL_DOWN, // A fake button which is 'pressed' and 'released' when the wheel is moved down - - MOUSE_LAST = MOUSE_WHEEL_DOWN, - MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1, - - // Joystick - JOYSTICK_FIRST = MOUSE_LAST + 1, - - JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST, - JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_MAX_BUTTON_COUNT - 1), - JOYSTICK_FIRST_POV_BUTTON, - JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_POV_BUTTON_COUNT - 1), - JOYSTICK_FIRST_AXIS_BUTTON, - JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1), - - JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON, - - BUTTON_CODE_LAST, - BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1, - - // Helpers for XBox 360 - KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons - KEY_XBUTTON_RIGHT, - KEY_XBUTTON_DOWN, - KEY_XBUTTON_LEFT, - - KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons - KEY_XBUTTON_B, - KEY_XBUTTON_X, - KEY_XBUTTON_Y, - KEY_XBUTTON_LEFT_SHOULDER, - KEY_XBUTTON_RIGHT_SHOULDER, - KEY_XBUTTON_BACK, - KEY_XBUTTON_START, - KEY_XBUTTON_STICK1, - KEY_XBUTTON_STICK2, - KEY_XBUTTON_INACTIVE_START, - - KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE - KEY_XSTICK1_LEFT, // XAXIS NEGATIVE - KEY_XSTICK1_DOWN, // YAXIS POSITIVE - KEY_XSTICK1_UP, // YAXIS NEGATIVE - KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE - KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE - KEY_XSTICK2_RIGHT, // UAXIS POSITIVE - KEY_XSTICK2_LEFT, // UAXIS NEGATIVE - KEY_XSTICK2_DOWN, // VAXIS POSITIVE - KEY_XSTICK2_UP, // VAXIS NEGATIVE -}; - -// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them. - ///////////////////////////////////////////////////////////////////////////// // Classes and Structs @@ -351,22 +134,6 @@ public: int m_mutex; // 0x0130 }; -enum KeyValuesTypes -{ - TYPE_NONE = 0x0, - TYPE_STRING = 0x1, - TYPE_INT = 0x2, - TYPE_FLOAT = 0x3, - TYPE_PTR = 0x4, - TYPE_WSTRING = 0x5, - TYPE_COLOR = 0x6, - TYPE_UINT64 = 0x7, - TYPE_COMPILED_INT_BYTE = 0x8, - TYPE_COMPILED_INT_0 = 0x9, - TYPE_COMPILED_INT_1 = 0xA, - TYPE_NUMTYPES = 0xB, -}; - class KeyValues { public: @@ -485,28 +252,6 @@ public: bool m_bWorkshopMapDownloadPending; //0x026A }; -enum ClientFrameStage_t -{ - FRAME_UNDEFINED = -1, // (haven't run any frames yet) - FRAME_START, - - // A network packet is being recieved - FRAME_NET_UPDATE_START, - // Data has been received and we're going to start calling PostDataUpdate - FRAME_NET_UPDATE_POSTDATAUPDATE_START, - // Data has been received and we've called PostDataUpdate on all data recipients - FRAME_NET_UPDATE_POSTDATAUPDATE_END, - // We've received all packets, we can now do interpolation, prediction, etc.. - FRAME_NET_UPDATE_END, - - // We're about to start rendering the scene - FRAME_RENDER_START, - // We've finished rendering the scene. - FRAME_RENDER_END, - - FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE -}; - class CHLClient { public: diff --git a/r5dev/include/hooks.h b/r5dev/include/hooks.h index 025eb1e0..ab484fd0 100644 --- a/r5dev/include/hooks.h +++ b/r5dev/include/hooks.h @@ -1,14 +1,87 @@ #pragma once +#include "patterns.h" +#include "structs.h" +#include "overlay.h" +#include "hooks.h" +#include "gameclasses.h" -///////////////////////////////////////////////////////////////////////////// -// Initialization -void InstallENHooks(); -void RemoveENHooks(); -void ToggleDevCommands(); -void ToggleNetHooks(); - -///////////////////////////////////////////////////////////////////////////// -// Globals inline bool g_bDebugLoading = false; +inline bool g_bReturnAllFalse = false; +inline bool g_bDebugConsole = false; +extern bool g_bBlockInput; -///////////////////////////////////////////////////////////////////////////// \ No newline at end of file +namespace Hooks +{ +#pragma region CHLClient + void __fastcall FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage); + + using FrameStageNotifyFn = void(__fastcall*)(CHLClient*, ClientFrameStage_t); + extern FrameStageNotifyFn originalFrameStageNotify; +#pragma endregion + +#pragma region Squirrel + void* SQVM_Print(void* sqvm, char* fmt, ...); + __int64 SQVM_LoadRson(const char* rson_name); + bool SQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag); + + using SQVM_LoadRsonFn = __int64(*)(const char*); + extern SQVM_LoadRsonFn originalSQVM_LoadRson; + + using SQVM_LoadScriptFn = bool(*)(void*, const char*, const char*, int); + extern SQVM_LoadScriptFn originalSQVM_LoadScript; +#pragma endregion + +#pragma region CVEngineServer + bool IsPersistenceDataAvailable(__int64 thisptr, int client); + + using IsPersistenceDataAvailableFn = bool(*)(__int64, int); + extern IsPersistenceDataAvailableFn originalIsPersistenceDataAvailable; +#pragma endregion + +#pragma region NetChannel + bool NET_ReceiveDatagram(int sock, void* inpacket, bool raw); + unsigned int NET_SendDatagram(SOCKET s, const char* buf, int len, int flags); + + using NET_ReceiveDatagramFn = bool(*)(int, void*, bool); + extern NET_ReceiveDatagramFn originalNET_ReceiveDatagram; + + using NET_SendDatagramFn = unsigned int(*)(SOCKET, const char*, int, int); + extern NET_SendDatagramFn originalNET_SendDatagram; +#pragma endregion + +#pragma region ConVar + bool ConVar_IsFlagSet(int** cvar, int flag); + bool ConCommand_IsFlagSet(int* cmd, int flag); +#pragma endregion + +#pragma region WinAPI + BOOL WINAPI GetCursorPos(LPPOINT lpPoint); + BOOL WINAPI SetCursorPos(int X, int Y); + BOOL WINAPI ClipCursor(const RECT* lpRect); + BOOL WINAPI ShowCursor(BOOL bShow); + + using GetCursorPosFn = BOOL(WINAPI*)(LPPOINT); + extern GetCursorPosFn originalGetCursorPos; + + using SetCursorPosFn = BOOL(WINAPI*)(int, int); + extern SetCursorPosFn originalSetCursorPos; + + using ClipCursorFn = BOOL(WINAPI*)(const RECT*); + extern ClipCursorFn originalClipCursor; + + using ShowCursorFn = BOOL(WINAPI*)(BOOL); + extern ShowCursorFn originalShowCursor; +#pragma endregion + +#pragma region Other + int MSG_EngineError(char* fmt, va_list args); + + using MSG_EngineErrorFn = int(*)(char*, va_list); + extern MSG_EngineErrorFn originalMSG_EngineError; +#pragma endregion + + void InstallHooks(); + void RemoveHooks(); + void ToggleNetHooks(); + void ToggleDevCommands(); +} \ No newline at end of file diff --git a/r5dev/include/input.h b/r5dev/include/input.h index d686f3c7..7b9637ef 100644 --- a/r5dev/include/input.h +++ b/r5dev/include/input.h @@ -1,11 +1 @@ -#pragma once - -///////////////////////////////////////////////////////////////////////////// -// Internals -void InstallIPHooks(); -void RemoveIPHooks(); - -///////////////////////////////////////////////////////////////////////////// -// Globals -extern BOOL g_bBlockInput; -///////////////////////////////////////////////////////////////////////////// +#pragma once \ No newline at end of file diff --git a/r5dev/include/patterns.h b/r5dev/include/patterns.h index 567abe9b..e262cfd7 100644 --- a/r5dev/include/patterns.h +++ b/r5dev/include/patterns.h @@ -7,50 +7,50 @@ namespace #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()); + FUNC_AT_ADDRESS(addr_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_ConVar_IsFlagSet, bool(*)(int**, int), r5_patterns.PatternSearch("48 8B 41 48 85 50 38").GetPtr()); + FUNC_AT_ADDRESS(addr_ConVar_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()); + FUNC_AT_ADDRESS(addr_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_Print, void*, r5_patterns.PatternSearch("83 F8 01 48 8D 3D ? ? ? ?").OffsetSelf(0x3).FollowNearCallSelf(0x3, 0x7).GetPtr()); + FUNC_AT_ADDRESS(addr_SQVM_Print, 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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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()); + FUNC_AT_ADDRESS(addr_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_CVEngineServer_IsPersistenceDataAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr()); + FUNC_AT_ADDRESS(addr_CVEngineServer_IsPersistenceDataAvailable, 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()); + FUNC_AT_ADDRESS(addr_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 // Un-used atm. // DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45")); @@ -58,17 +58,17 @@ namespace void PrintHAddress() // Test the sigscan results { std::cout << "+--------------------------------------------------------+" << std::endl; - PRINT_ADDRESS("CommandExecute", org_CommandExecute); - PRINT_ADDRESS("ConVar_IsFlagSet", org_ConVar_IsFlagSet); - PRINT_ADDRESS("ConCommand_IsFlagSet", org_ConCommand_IsFlagSet); - PRINT_ADDRESS("SQVM_Print", org_SQVM_Print); - PRINT_ADDRESS("SQVM_LoadScript", org_SQVM_LoadScript); - PRINT_ADDRESS("SQVM_LoadRson", org_SQVM_LoadRson); - PRINT_ADDRESS("NET_ReceiveDatagram", org_NET_ReceiveDatagram); - PRINT_ADDRESS("NET_SendDatagram ", org_NET_SendDatagram); - PRINT_ADDRESS("CHLClient::FrameStageNotify", org_CHLClient_FrameStageNotify); - PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", org_CVEngineServer_IsPersistenceDataAvailable); - PRINT_ADDRESS("MSG_EngineError", org_MSG_EngineError); + PRINT_ADDRESS("CommandExecute", addr_CommandExecute); + PRINT_ADDRESS("ConVar_IsFlagSet", addr_ConVar_IsFlagSet); + PRINT_ADDRESS("ConCommand_IsFlagSet", addr_ConCommand_IsFlagSet); + PRINT_ADDRESS("SQVM_Print", addr_SQVM_Print); + PRINT_ADDRESS("SQVM_LoadScript", addr_SQVM_LoadScript); + PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson); + PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram); + PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram); + PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify); + PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable); + PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError); std::cout << "+--------------------------------------------------------+" << std::endl; // TODO implement error handling when sigscan fails or result is 0 } diff --git a/r5dev/include/pch.h b/r5dev/include/pch.h index e4cb717f..37c8e86e 100644 --- a/r5dev/include/pch.h +++ b/r5dev/include/pch.h @@ -3,7 +3,7 @@ #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition. #include -#include +#include #include #include #include @@ -19,8 +19,6 @@ #include #include - - // Our headers #include "imgui.h" @@ -33,6 +31,7 @@ #include "json.hpp" #include "address.h" +#include "enums.h" #define FUNC_AT_ADDRESS(name, funcbody, addr) \ using _##name = funcbody; \ diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index 1c771135..c87b1ab0 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -87,8 +87,8 @@ false - $(SolutionDir)external\detours\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dev\include;$(IncludePath) - $(SolutionDir)external\detours\libs;$(LibraryPath) + $(SolutionDir)external\minhook\include;$(SolutionDir)external\imgui\include;$(SolutionDir)external\spdlog\include;$(SolutionDir)shared\include;$(SolutionDir)r5dev\include;$(IncludePath) + $(SolutionDir)external\minhook\lib;$(LibraryPath) @@ -165,6 +165,7 @@ Speed true true + MultiThreadedDLL Windows @@ -173,16 +174,13 @@ true false r5dev.def - detours.lib;%(AdditionalDependencies) + libMinHook.x64.lib;%(AdditionalDependencies) del "$(TargetDir)\r5detours.dll" && rename "$(TargetPath)" "r5detours.dll" - - - @@ -191,6 +189,7 @@ + @@ -345,10 +344,14 @@ Use pch.h - - Use - pch.h - + + + + + + + + Use pch.h diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index 89f3a4a9..34b18dc7 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -1,9 +1,6 @@  - - {a80939e5-3b3c-4873-885e-834e95d68d34} - {927ea852-3616-4fc4-8b32-781f65853a6b} @@ -16,25 +13,15 @@ {633d6e7a-c709-4d64-a134-b383d43c8c8e} - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - {7cef4f92-94d9-43af-bea5-c6963d68fff2} - - {584562a8-0382-488c-909c-67bbb1d1af3c} - {c72b9789-72e9-4657-8a42-8712aaf8690e} {757af774-e575-4623-8582-71efb0ae53a4} - - {3fa7f9a9-dc07-4d42-9172-0944829c010f} - {c18fb898-adc3-4aa8-902c-4777bbc76e5b} @@ -59,32 +46,62 @@ {30005d10-4213-441c-b18b-4dd47fcb8812} + + {e901ef66-ddeb-4aff-9d7e-786d74a791e9} + + + {da82c6eb-abba-4b52-84bf-9f3758a169bf} + + + {6a6d7e33-2ce0-4b53-bcf6-41dc6dacdc5f} + + + {e449786f-692c-4d6c-a292-b0720bf9e2a9} + + + {46b49d69-ea42-467c-86d8-00611f2718ff} + + + {2ec9179b-7320-47da-b170-f021d0279310} + + + {83391c47-4a5b-4231-a9ef-29e119c5bb69} + + + {c27e3539-0070-40fa-b262-0ecd39f47919} + + + {afb847fc-853f-4e6f-bde6-91bf345369b4} + + + {9f8f15a7-6e69-4a79-b644-a92ad815c600} + + + {25c5fe7f-23c0-4d44-b92d-ea4b127eec05} + + + {0420f99f-468e-4ba5-abe3-960cc332b636} + + + {a40dcf17-855b-4965-b58d-6c7d24edc627} + + + {03d79a58-4706-4ee0-b0ea-6251a2fafada} + + + {89bf5311-5686-4077-9b79-c6306dc1bd91} + + + {3a4ca756-24d2-47e8-af7f-0e8a75933c4b} + + + {58dbc5f6-cf3c-4d71-80c8-caefffb39beb} + + + {0136e8e8-91ef-45c1-8661-476b5c20fc48} + - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - core @@ -115,35 +132,53 @@ shared + + hooks\src\chlclient + + + hooks\src\squirrel + + + hooks\src\cvengineserver + + + hooks\src\other + + + hooks\src\netchannel + + + hooks\src\iconvar + + + hooks\src\winapi + + + hooks\src + + + gui\src + + + gui\src + + + gui\src + + + r5-sdk\src + + + core + + + core + + + r5-sdk\src + - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - shared\libraries\detours\include - - - shared\libraries\detours\include - - - shared\libraries\detours\include - shared\libraries\imgui\include @@ -168,18 +203,6 @@ shared\libraries\imgui\include - - Header Files - - - Header Files - - - Header Files - - - Header Files - shared\libraries\spdlog\include @@ -462,12 +485,6 @@ shared\libraries\spdlog\include\sinks - - Header Files - - - Header Files - shared\include @@ -483,6 +500,45 @@ core\include + + shared\libraries\minhook\include + + + hooks\include + + + gui\include + + + gui\include + + + gui\include + + + r5-sdk\include + + + core\include + + + core + + + r5-sdk\include + + + r5-sdk\include + + + r5-sdk\include + + + r5-sdk\include + + + core\include + diff --git a/r5dev/src/console.cpp b/r5dev/src/console.cpp index c5ab1a52..7efe42c6 100644 --- a/r5dev/src/console.cpp +++ b/r5dev/src/console.cpp @@ -54,62 +54,13 @@ void SetupConsole() } } -//############################################################################# -// CONSOLE HOOKS -//############################################################################# - -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; } -} - -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; } -} - //############################################################################# // WORKER THREAD //############################################################################# DWORD __stdcall ProcessConsoleWorker(LPVOID) { - // Loop forever - while (true) + while (true) // Loop forever { std::string sCommand; @@ -120,8 +71,8 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) /////////////////////////////////////////////////////////////////////// // Engine toggles - if (sCommand == "toggle net") { ToggleNetHooks(); continue; } - if (sCommand == "toggle dev") { ToggleDevCommands(); continue; } + if (sCommand == "toggle net") { Hooks::ToggleNetHooks(); continue; } + if (sCommand == "toggle dev") { Hooks::ToggleDevCommands(); continue; } if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } /////////////////////////////////////////////////////////////////////// // Debug toggles @@ -130,12 +81,12 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) if (sCommand == "console test") { g_bDebugConsole = !g_bDebugConsole; continue; } /////////////////////////////////////////////////////////////////////// // Exec toggles - if (sCommand == "1") { ToggleDevCommands(); org_CommandExecute(NULL, "exec autoexec_dev"); } + if (sCommand == "1") { Hooks::ToggleDevCommands(); addr_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()); + addr_CommandExecute(NULL, sCommand.c_str()); sCommand.clear(); /////////////////////////////////////////////////////////////////////// @@ -144,66 +95,4 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) } return 0; -} - -//############################################################################# -// MANAGEMENT -//############################################################################# - -void RemoveCMHooks() -{ - /////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction, to unhook the the process - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - /////////////////////////////////////////////////////////////////////////// - // Unhook Console functions - DetourDetach((LPVOID*)&org_ConVar_IsFlagSet, &HConVar_IsFlagSet); - DetourDetach((LPVOID*)&org_ConCommand_IsFlagSet, &HConCommand_IsFlagSet); - - /////////////////////////////////////////////////////////////////////////// - // Commit the transaction - DetourTransactionCommit(); -} - -//############################################################################# -// TOGGLES -//############################################################################# - -void ToggleDevCommands() -{ - static bool g_dev = false; - - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - if (!g_dev) - { - DetourAttach((LPVOID*)&org_ConVar_IsFlagSet, &HConVar_IsFlagSet); - DetourAttach((LPVOID*)&org_ConCommand_IsFlagSet, &HConCommand_IsFlagSet); - printf("\n"); - printf("+--------------------------------------------------------+\n"); - printf("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n"); - printf("+--------------------------------------------------------+\n"); - printf("\n"); - - } - else - { - DetourDetach((LPVOID*)&org_ConVar_IsFlagSet, &HConVar_IsFlagSet); - DetourDetach((LPVOID*)&org_ConCommand_IsFlagSet, &HConCommand_IsFlagSet); - printf("\n"); - printf("+--------------------------------------------------------+\n"); - printf("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n"); - printf("+--------------------------------------------------------+\n"); - printf("\n"); - } - - if (DetourTransactionCommit() != NO_ERROR) - { - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } - - g_dev = !g_dev; -} +} \ No newline at end of file diff --git a/r5dev/src/dllmain.cpp b/r5dev/src/dllmain.cpp index 4c2f5c93..c996b69b 100644 --- a/r5dev/src/dllmain.cpp +++ b/r5dev/src/dllmain.cpp @@ -5,7 +5,6 @@ #include "hooks.h" #include "opcptc.h" #include "console.h" -#include "gameclasses.h" //############################################################################# // INITIALIZATION @@ -14,9 +13,7 @@ void InitializeR5Dev() { SetupConsole(); - InstallENHooks(); - InstallIPHooks(); - InstallDXHooks(); + Hooks::InstallHooks(); InstallOpcodes(); SetupDXSwapChain(); printf("+-----------------------------------------------------------------------------+\n"); @@ -27,10 +24,8 @@ void InitializeR5Dev() void TerminateR5Dev() { - RemoveCMHooks(); - RemoveENHooks(); - RemoveIPHooks(); RemoveDXHooks(); + Hooks::RemoveHooks(); FreeConsole(); } @@ -38,7 +33,7 @@ void TerminateR5Dev() // ENTRYPOINT //############################################################################# -BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) +BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) diff --git a/r5dev/src/hooks.cpp b/r5dev/src/hooks.cpp deleted file mode 100644 index d1bc3689..00000000 --- a/r5dev/src/hooks.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include "pch.h" -#include "patterns.h" -#include "structs.h" -#include "overlay.h" -#include "hooks.h" -#include "gameclasses.h" - -//################################################################################# -// NETCHANNEL HOOKS -//################################################################################# - -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; -} - -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; -} - -//################################################################################# -// CHLCLIENT HOOKS -//################################################################################# - -void __fastcall HCHLClient__FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage) /* __fastcall so we can make sure first argument will be RCX and second RDX. */ -{ - switch (curStage) - { - case FRAME_START: // FrameStageNotify gets called every frame by CEngine::Frame with the stage being FRAME_START. We can use this to check/set global variables. - { - if (!GameGlobals::IsInitialized) - GameGlobals::InitGameGlobals(); - - break; - } - default: - break; - } - - org_CHLClient_FrameStageNotify(rcx, curStage); -} - -//################################################################################# -// SQUIRRELVM HOOKS -//################################################################################# - -void* HSQVM_Print(void* sqvm, char* fmt, ...) -{ - char buf[1024]; - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf) - 1] = 0; - va_end(args); - Items.push_back(Strdup(buf)); - return NULL; -} - -__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); -} - -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); -} - -//################################################################################# -// UTILITY HOOKS -//################################################################################# - -int HMSG_EngineError(char* fmt, va_list args) -{ - printf("\nENGINE ERROR #####################################\n"); - vprintf(fmt, args); - return org_MSG_EngineError(fmt, args); -} - -// TODO: turn this into a playerstruct constructor if it ever becomes necessary -bool HCVEngineServer_IsPersistenceDataAvailable(__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_CVEngineServer_IsPersistenceDataAvailable(thisptr, client); -} - -//################################################################################# -// MANAGEMENT -//################################################################################# - -void InstallENHooks() -{ - /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - /////////////////////////////////////////////////////////////////////////////// - // Hook Squirrel functions - DetourAttach((LPVOID*)&org_SQVM_Print, &HSQVM_Print); - DetourAttach((LPVOID*)&org_SQVM_LoadRson, &HSQVM_LoadRson); - DetourAttach((LPVOID*)&org_SQVM_LoadScript, &HSQVM_LoadScript); - - /////////////////////////////////////////////////////////////////////////////// - // Hook Game Functions - DetourAttach((LPVOID*)&org_CHLClient_FrameStageNotify, &HCHLClient__FrameStageNotify); - - /////////////////////////////////////////////////////////////////////////////// - // Hook Utility functions - DetourAttach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); - DetourAttach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineServer_IsPersistenceDataAvailable); - - /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - if (DetourTransactionCommit() != NO_ERROR) - { - // Failed to hook into the process, terminate - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } -} - -void RemoveENHooks() -{ - /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction, to unhook the the process - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - /////////////////////////////////////////////////////////////////////////////// - // Unhook Squirrel functions - DetourDetach((LPVOID*)&org_SQVM_Print, &HSQVM_Print); - DetourDetach((LPVOID*)&org_SQVM_LoadRson, &HSQVM_LoadRson); - DetourDetach((LPVOID*)&org_SQVM_LoadScript, &HSQVM_LoadScript); - - /////////////////////////////////////////////////////////////////////////////// - // Unhook Game Functions - DetourDetach((LPVOID*)&org_CHLClient_FrameStageNotify, &HCHLClient__FrameStageNotify); - - /////////////////////////////////////////////////////////////////////////////// - // Unhook Netchan functions - DetourDetach((LPVOID*)&org_NET_SendDatagram, &HNET_SendDatagram); - DetourDetach((LPVOID*)&org_NET_ReceiveDatagram, &HNET_ReceiveDatagram); - - /////////////////////////////////////////////////////////////////////////////// - // Unhook Utility functions - DetourDetach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError); - DetourDetach((LPVOID*)&org_CVEngineServer_IsPersistenceDataAvailable, &HCVEngineServer_IsPersistenceDataAvailable); - - /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - DetourTransactionCommit(); -} - -//################################################################################# -// TOGGLES -//################################################################################# - -void ToggleNetHooks() -{ - static bool g_net = false; - - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - if (!g_net) - { - DetourAttach((LPVOID*)&org_NET_SendDatagram, &HNET_SendDatagram); - DetourAttach((LPVOID*)&org_NET_ReceiveDatagram, &HNET_ReceiveDatagram); - printf("\n"); - printf("+--------------------------------------------------------+\n"); - printf("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n"); - printf("+--------------------------------------------------------+\n"); - printf("\n"); - } - else - { - DetourDetach((LPVOID*)&org_NET_SendDatagram, &HNET_SendDatagram); - DetourDetach((LPVOID*)&org_NET_ReceiveDatagram, &HNET_ReceiveDatagram); - printf("\n"); - printf("+--------------------------------------------------------+\n"); - printf("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n"); - printf("+--------------------------------------------------------+\n"); - printf("\n"); - } - - if (DetourTransactionCommit() != NO_ERROR) - { - TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); - } - - g_net = !g_net; -} diff --git a/r5dev/src/hooks/chlclient.cpp b/r5dev/src/hooks/chlclient.cpp new file mode 100644 index 00000000..4ae9839b --- /dev/null +++ b/r5dev/src/hooks/chlclient.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + FrameStageNotifyFn originalFrameStageNotify = nullptr; +} + +void __fastcall Hooks::FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage) +{ + switch (curStage) + { + case FRAME_START: // FrameStageNotify gets called every frame by CEngine::Frame with the stage being FRAME_START. We can use this to check/set global variables. + { + if (!GameGlobals::IsInitialized) + GameGlobals::InitGameGlobals(); + + break; + } + default: + break; + } + + originalFrameStageNotify(rcx, curStage); +} \ No newline at end of file diff --git a/r5dev/src/hooks/cvengineserver.cpp b/r5dev/src/hooks/cvengineserver.cpp new file mode 100644 index 00000000..0c7cad18 --- /dev/null +++ b/r5dev/src/hooks/cvengineserver.cpp @@ -0,0 +1,34 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + IsPersistenceDataAvailableFn originalIsPersistenceDataAvailable = nullptr; +} + +// TODO: turn this into a playerstruct constructor if it ever becomes necessary +bool Hooks::IsPersistenceDataAvailable(__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 originalIsPersistenceDataAvailable(thisptr, client); +} \ No newline at end of file diff --git a/r5dev/src/hooks/hooks.cpp b/r5dev/src/hooks/hooks.cpp new file mode 100644 index 00000000..054083b8 --- /dev/null +++ b/r5dev/src/hooks/hooks.cpp @@ -0,0 +1,173 @@ +#include "pch.h" +#include "hooks.h" + +bool g_bBlockInput = false; + +void Hooks::InstallHooks() +{ + /////////////////////////////////////////////////////////////////////////////// + // Initialize Minhook + MH_Initialize(); + + /////////////////////////////////////////////////////////////////////////////// + // Hook Squirrel functions + MH_CreateHook(addr_SQVM_Print, &Hooks::SQVM_Print, NULL); + MH_CreateHook(addr_SQVM_LoadRson, &Hooks::SQVM_LoadRson, reinterpret_cast(&originalSQVM_LoadRson)); + MH_CreateHook(addr_SQVM_LoadScript, &Hooks::SQVM_LoadScript, reinterpret_cast(&originalSQVM_LoadScript)); + + /////////////////////////////////////////////////////////////////////////////// + // Hook Game Functions + MH_CreateHook(addr_CHLClient_FrameStageNotify, &Hooks::FrameStageNotify, reinterpret_cast(&originalFrameStageNotify)); + MH_CreateHook(addr_CVEngineServer_IsPersistenceDataAvailable, &Hooks::IsPersistenceDataAvailable, reinterpret_cast(&originalIsPersistenceDataAvailable)); + + /////////////////////////////////////////////////////////////////////////////// + // Hook Netchan functions + MH_CreateHook(addr_NET_ReceiveDatagram, &Hooks::NET_ReceiveDatagram, reinterpret_cast(&originalNET_ReceiveDatagram)); + MH_CreateHook(addr_NET_SendDatagram, &Hooks::NET_SendDatagram, reinterpret_cast(&originalNET_SendDatagram)); + + /////////////////////////////////////////////////////////////////////////////// + // Hook ConVar | ConCommand functions. + MH_CreateHook(addr_ConVar_IsFlagSet, &Hooks::ConVar_IsFlagSet, NULL); + MH_CreateHook(addr_ConCommand_IsFlagSet, &Hooks::ConCommand_IsFlagSet, NULL); + + /////////////////////////////////////////////////////////////////////////////// + // Hook WinAPI + HMODULE user32dll = GetModuleHandleA("user32.dll"); + void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); + void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); + void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); + void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); + + MH_CreateHook(SetCursorPosPtr, &Hooks::SetCursorPos, reinterpret_cast(&originalSetCursorPos)); + MH_CreateHook(ClipCursorPtr, &Hooks::ClipCursor, reinterpret_cast(&originalClipCursor)); + MH_CreateHook(GetCursorPosPtr, &Hooks::GetCursorPos, reinterpret_cast(&originalGetCursorPos)); + MH_CreateHook(ShowCursorPtr, &Hooks::ShowCursor, reinterpret_cast(&originalShowCursor)); + + /////////////////////////////////////////////////////////////////////////////// + // Hook Utility functions + MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast(&originalMSG_EngineError)); + + /////////////////////////////////////////////////////////////////////////////// + // Enable Squirrel hooks + MH_EnableHook(addr_SQVM_Print); + MH_EnableHook(addr_SQVM_LoadRson); + MH_EnableHook(addr_SQVM_LoadScript); + + /////////////////////////////////////////////////////////////////////////////// + // Enable Game hooks + MH_EnableHook(addr_CHLClient_FrameStageNotify); + MH_EnableHook(addr_CVEngineServer_IsPersistenceDataAvailable); + + /////////////////////////////////////////////////////////////////////////////// + // Enable WinAPI hooks + MH_EnableHook(SetCursorPosPtr); + MH_EnableHook(ClipCursorPtr); + MH_EnableHook(GetCursorPosPtr); + MH_EnableHook(ShowCursorPtr); + + /////////////////////////////////////////////////////////////////////////////// + // Enabled Utility hooks + MH_EnableHook(addr_MSG_EngineError); +} + +void Hooks::RemoveHooks() +{ + /////////////////////////////////////////////////////////////////////////////// + // Unhook Squirrel functions + MH_RemoveHook(addr_SQVM_Print); + MH_RemoveHook(addr_SQVM_LoadRson); + MH_RemoveHook(addr_SQVM_LoadScript); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook Game Functions + MH_RemoveHook(addr_CHLClient_FrameStageNotify); + MH_RemoveHook(addr_CVEngineServer_IsPersistenceDataAvailable); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook Netchan functions + MH_RemoveHook(addr_NET_ReceiveDatagram); + MH_RemoveHook(addr_NET_SendDatagram); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook ConVar | ConCommand functions. + MH_RemoveHook(addr_ConVar_IsFlagSet); + MH_RemoveHook(addr_ConCommand_IsFlagSet); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook WinAPI + HMODULE user32dll = GetModuleHandleA("user32.dll"); + void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); + void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); + void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); + void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); + + MH_RemoveHook(SetCursorPosPtr); + MH_RemoveHook(ClipCursorPtr); + MH_RemoveHook(GetCursorPosPtr); + MH_RemoveHook(ShowCursorPtr); + + /////////////////////////////////////////////////////////////////////////////// + // Unhook Utility functions + MH_RemoveHook(addr_MSG_EngineError); + + /////////////////////////////////////////////////////////////////////////////// + // Reset Minhook + MH_Uninitialize(); +} + +void Hooks::ToggleNetHooks() +{ + static bool g_net = false; + + if (!g_net) + { + MH_EnableHook(addr_NET_ReceiveDatagram); + MH_EnableHook(addr_NET_SendDatagram); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + else + { + MH_DisableHook(addr_NET_ReceiveDatagram); + MH_DisableHook(addr_NET_SendDatagram); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + + g_net = !g_net; +} + +void Hooks::ToggleDevCommands() +{ + static bool g_dev = false; + + if (!g_dev) + { + MH_EnableHook(addr_ConVar_IsFlagSet); + MH_EnableHook(addr_ConCommand_IsFlagSet); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + + } + else + { + MH_DisableHook(addr_ConVar_IsFlagSet); + MH_DisableHook(addr_ConCommand_IsFlagSet); + printf("\n"); + printf("+--------------------------------------------------------+\n"); + printf("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n"); + printf("+--------------------------------------------------------+\n"); + printf("\n"); + } + + g_dev = !g_dev; +} diff --git a/r5dev/src/hooks/iconvar.cpp b/r5dev/src/hooks/iconvar.cpp new file mode 100644 index 00000000..ab5f4a61 --- /dev/null +++ b/r5dev/src/hooks/iconvar.cpp @@ -0,0 +1,58 @@ +#include "pch.h" +#include "hooks.h" + +bool Hooks::ConVar_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; + } +} + +bool Hooks::ConCommand_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; + } +} \ No newline at end of file diff --git a/r5dev/src/hooks/msgbox.cpp b/r5dev/src/hooks/msgbox.cpp new file mode 100644 index 00000000..4592d1f1 --- /dev/null +++ b/r5dev/src/hooks/msgbox.cpp @@ -0,0 +1,15 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + MSG_EngineErrorFn originalMSG_EngineError = nullptr; +} + +int Hooks::MSG_EngineError(char* fmt, va_list args) +{ + printf("\nENGINE ERROR #####################################\n"); + vprintf(fmt, args); + + return originalMSG_EngineError(fmt, args); +} \ No newline at end of file diff --git a/r5dev/src/hooks/net.cpp b/r5dev/src/hooks/net.cpp new file mode 100644 index 00000000..59eb65f0 --- /dev/null +++ b/r5dev/src/hooks/net.cpp @@ -0,0 +1,37 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + NET_ReceiveDatagramFn originalNET_ReceiveDatagram = nullptr; + NET_SendDatagramFn originalNET_SendDatagram = nullptr; +} + +bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) +{ + bool result = originalNET_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; +} + +unsigned int Hooks::NET_SendDatagram(SOCKET s, const char* buf, int len, int flags) +{ + unsigned int result = originalNET_SendDatagram(s, buf, len, flags); + if (result) + { + /////////////////////////////////////////////////////////////////////////// + // Log transmitted packet data + HexDump("[+] NET_SendDatagram", 0, buf, len); + } + + return result; +} \ No newline at end of file diff --git a/r5dev/src/hooks/sqvm.cpp b/r5dev/src/hooks/sqvm.cpp new file mode 100644 index 00000000..5285507c --- /dev/null +++ b/r5dev/src/hooks/sqvm.cpp @@ -0,0 +1,90 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + SQVM_LoadRsonFn originalSQVM_LoadRson = nullptr; + SQVM_LoadScriptFn originalSQVM_LoadScript = nullptr; +} + +void* Hooks::SQVM_Print(void* sqvm, char* fmt, ...) +{ + char buf[1024]; + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); + buf[IM_ARRAYSIZE(buf) - 1] = 0; + va_end(args); + Items.push_back(Strdup(buf)); + return NULL; +} + +__int64 Hooks::SQVM_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) && originalSQVM_LoadRson(rson_name)) + { + printf("\n"); + printf("##################################################\n"); + printf("] '%s'\n", filepath); + printf("##################################################\n"); + printf("\n"); + + return originalSQVM_LoadRson(filepath); + } + + printf("\n"); + printf("##################################################\n"); + printf("] '%s'\n", rson_name); + printf("##################################################\n"); + printf("\n"); + + return originalSQVM_LoadRson(rson_name); +} + +bool Hooks::SQVM_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) && originalSQVM_LoadScript(sqvm, filepath, script_name, flag)) + { + return true; + } + if (g_bDebugLoading) + { + printf(" [!] FAILED. Try SP / VPK for '%s'\n", filepath); + } + + return originalSQVM_LoadScript(sqvm, script_path, script_name, flag); +} \ No newline at end of file diff --git a/r5dev/src/hooks/winapi.cpp b/r5dev/src/hooks/winapi.cpp new file mode 100644 index 00000000..a9a96905 --- /dev/null +++ b/r5dev/src/hooks/winapi.cpp @@ -0,0 +1,59 @@ +#include "pch.h" +#include "hooks.h" + +namespace Hooks +{ + namespace + { + static POINT g_pLastCursorPos{ 0 }; + } + + GetCursorPosFn originalGetCursorPos = nullptr; + SetCursorPosFn originalSetCursorPos = nullptr; + ClipCursorFn originalClipCursor = nullptr; + ShowCursorFn originalShowCursor = nullptr; +} + +BOOL WINAPI Hooks::GetCursorPos(LPPOINT lpPoint) +{ + if (g_bBlockInput) + { + assert(lpPoint != nullptr); + *lpPoint = g_pLastCursorPos; + } + + return originalGetCursorPos(lpPoint); +} + +BOOL WINAPI Hooks::SetCursorPos(int X, int Y) +{ + g_pLastCursorPos.x = X; + g_pLastCursorPos.y = Y; + + if (g_bBlockInput) + { + return TRUE; + } + + return originalSetCursorPos(X, Y); +} + +BOOL WINAPI Hooks::ClipCursor(const RECT* lpRect) +{ + if (g_bBlockInput) + { + lpRect = nullptr; + } + + return originalClipCursor(lpRect); +} + +BOOL WINAPI Hooks::ShowCursor(BOOL bShow) +{ + if (g_bBlockInput) + { + bShow = TRUE; + } + + return originalShowCursor(bShow); +} \ No newline at end of file diff --git a/r5dev/src/id3dx.cpp b/r5dev/src/id3dx.cpp index 8b672a56..013f4c06 100644 --- a/r5dev/src/id3dx.cpp +++ b/r5dev/src/id3dx.cpp @@ -1,9 +1,7 @@ #include "pch.h" #include "id3dx.h" -#include "input.h" -#include "enums.h" +#include "hooks.h" #include "console.h" -#include "detours.h" #include "overlay.h" #include "patterns.h" #include "gameclasses.h" @@ -269,7 +267,7 @@ void DrawImGui() GameGlobals::InputSystem->EnableInput(false); // Disable input. DrawConsole(); } - if(g_bShowBrowser) + if (g_bShowBrowser) { GameGlobals::InputSystem->EnableInput(false); // Disable input. DrawBrowser(); @@ -354,6 +352,8 @@ HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device** return ret; } +IDXGIResizeBuffers originalResizeBuffers = nullptr; + HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags) { g_bShowConsole = false; @@ -369,16 +369,18 @@ HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount ImGui_ImplDX11_CreateDeviceObjects(); /////////////////////////////////////////////////////////////////////////////// - return g_oResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags); + return originalResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags); } +IDXGISwapChainPresent originalPresent = nullptr; + HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags) { if (!g_bInitialized) { if (FAILED(GetDeviceAndCtxFromSwapchain(pSwapChain, &g_pDevice, &g_pDeviceContext))) { - return g_fnIDXGISwapChainPresent(pSwapChain, nSyncInterval, nFlags); + return originalPresent(pSwapChain, nSyncInterval, nFlags); std::cout << "+--------------------------------------------------------+" << std::endl; std::cout << "| >>>>>>>>>>| GET DVS AND CTX FROM SCP FAILED |<<<<<<<<< |" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl; @@ -399,7 +401,7 @@ HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT n DrawImGui(); g_bInitialized = true; /////////////////////////////////////////////////////////////////////////////// - return g_fnIDXGISwapChainPresent(pSwapChain, nSyncInterval, nFlags); + return originalPresent(pSwapChain, nSyncInterval, nFlags); } //################################################################################# @@ -408,42 +410,45 @@ HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT n void InstallDXHooks() { - g_oPostMessageA = (IPostMessageA)DetourFindFunction("user32.dll", "PostMessageA"); - g_oPostMessageW = (IPostMessageW)DetourFindFunction("user32.dll", "PostMessageW"); - /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + HMODULE user32dll = GetModuleHandleA("user32.dll"); + + IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); + IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + /////////////////////////////////////////////////////////////////////////////// // Hook PostMessage - DetourAttach(&(LPVOID&)g_oPostMessageA, (PBYTE)HPostMessageA); - DetourAttach(&(LPVOID&)g_oPostMessageW, (PBYTE)HPostMessageW); + MH_CreateHook(PostMessageA, &HPostMessageA, reinterpret_cast(&g_oPostMessageA)); + MH_CreateHook(PostMessageW, &HPostMessageW, reinterpret_cast(&g_oPostMessageW)); + /////////////////////////////////////////////////////////////////////////////// // Hook SwapChain - DetourAttach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present); - DetourAttach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers); + MH_CreateHook(g_fnIDXGISwapChainPresent, &Present, reinterpret_cast(&originalPresent)); + MH_CreateHook(g_oResizeBuffers, &GetResizeBuffers, reinterpret_cast(&originalResizeBuffers)); + /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - DetourTransactionCommit(); + // Enable hooks + MH_EnableHook(PostMessageA); + MH_EnableHook(PostMessageW); + MH_EnableHook(g_fnIDXGISwapChainPresent); + MH_EnableHook(g_oResizeBuffers); } void RemoveDXHooks() { - /////////////////////////////////////////////////////////////////////////////// - // Begin the detour transaction - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + HMODULE user32dll = GetModuleHandleA("user32.dll"); + + IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); + IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + /////////////////////////////////////////////////////////////////////////////// // Unhook PostMessage - DetourDetach(&(LPVOID&)g_oPostMessageA, (PBYTE)HPostMessageA); - DetourDetach(&(LPVOID&)g_oPostMessageW, (PBYTE)HPostMessageW); + MH_RemoveHook(PostMessageA); + MH_RemoveHook(PostMessageW); + /////////////////////////////////////////////////////////////////////////////// // Unhook SwapChain - DetourDetach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present); - DetourDetach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers); - /////////////////////////////////////////////////////////////////////////////// - // Commit the transaction - DetourTransactionCommit(); + MH_RemoveHook(g_fnIDXGISwapChainPresent); + MH_RemoveHook(g_oResizeBuffers); /////////////////////////////////////////////////////////////////////////////// // Shutdown ImGui diff --git a/r5dev/src/input.cpp b/r5dev/src/input.cpp index d1403e21..e85ccc19 100644 --- a/r5dev/src/input.cpp +++ b/r5dev/src/input.cpp @@ -1,119 +1,2 @@ #include "pch.h" -#include "input.h" - -/*----------------------------------------------------------------------------- - * _input.cpp - *-----------------------------------------------------------------------------*/ - -/////////////////////////////////////////////////////////////////////////////// -typedef BOOL(WINAPI* IGetCursorPos)(LPPOINT lpPoint); -typedef BOOL(WINAPI* ISetCursorPos)(int nX, int nY); -typedef BOOL(WINAPI* IClipCursor)(const RECT* lpRect); -typedef BOOL(WINAPI* IShowCursor)(BOOL bShow); - -/////////////////////////////////////////////////////////////////////////////// -static IGetCursorPos g_oGetCursorPos = nullptr; -static ISetCursorPos g_oSetCursorPos = nullptr; -static IClipCursor g_oClipCursor = nullptr; -static IShowCursor g_oShowCursor = nullptr; - -/////////////////////////////////////////////////////////////////////////////// -static POINT g_pLastCursorPos { 0 }; -extern BOOL g_bBlockInput = false; - -//############################################################################# -// INITIALIZATION -//############################################################################# - -void SetupIPHooks() -{ - g_oSetCursorPos = (ISetCursorPos)DetourFindFunction("user32.dll", "SetCursorPos"); - g_oClipCursor = (IClipCursor )DetourFindFunction("user32.dll", "ClipCursor" ); - g_oGetCursorPos = (IGetCursorPos)DetourFindFunction("user32.dll", "GetCursorPos"); - g_oShowCursor = (IShowCursor )DetourFindFunction("user32.dll", "ShowCursor" ); -} - -//############################################################################# -// INPUT HOOKS -//############################################################################# - -BOOL WINAPI HGetCursorPos(LPPOINT lpPoint) -{ - if (g_bBlockInput) - { - assert(lpPoint != nullptr); - *lpPoint = g_pLastCursorPos; - } - - return g_oGetCursorPos(lpPoint); -} - -BOOL WINAPI HSetCursorPos(int X, int Y) -{ - g_pLastCursorPos.x = X; - g_pLastCursorPos.y = Y; - - if (g_bBlockInput) - { - return TRUE; - } - - return g_oSetCursorPos(X, Y); -} - -BOOL WINAPI HClipCursor(const RECT* lpRect) -{ - if (g_bBlockInput) - { - lpRect = nullptr; - } - - return g_oClipCursor(lpRect); -} - -BOOL WINAPI HShowCursor(BOOL bShow) -{ - if (g_bBlockInput) - { - bShow = TRUE; - } - - return g_oShowCursor(bShow); -} - -//############################################################################# -// MANAGEMENT -//############################################################################# - -void InstallIPHooks() -{ - SetupIPHooks(); - /////////////////////////////////////////////////////////////////////////// - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - /////////////////////////////////////////////////////////////////////////// - DetourAttach(&(LPVOID&)g_oGetCursorPos, (PBYTE)HGetCursorPos); - DetourAttach(&(LPVOID&)g_oSetCursorPos, (PBYTE)HSetCursorPos); - DetourAttach(&(LPVOID&)g_oClipCursor, (PBYTE)HClipCursor); - DetourAttach(&(LPVOID&)g_oShowCursor, (PBYTE)HShowCursor); - - /////////////////////////////////////////////////////////////////////////// - DetourTransactionCommit(); -} - -void RemoveIPHooks() -{ - /////////////////////////////////////////////////////////////////////////// - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - /////////////////////////////////////////////////////////////////////////// - DetourDetach(&(LPVOID&)g_oGetCursorPos, (PBYTE)HGetCursorPos); - DetourDetach(&(LPVOID&)g_oSetCursorPos, (PBYTE)HSetCursorPos); - DetourDetach(&(LPVOID&)g_oClipCursor, (PBYTE)HClipCursor); - DetourDetach(&(LPVOID&)g_oShowCursor, (PBYTE)HShowCursor); - - /////////////////////////////////////////////////////////////////////////// - DetourTransactionCommit(); -} +#include "input.h" \ No newline at end of file diff --git a/r5dev/src/overlay.cpp b/r5dev/src/overlay.cpp index cfce7624..898e63d6 100644 --- a/r5dev/src/overlay.cpp +++ b/r5dev/src/overlay.cpp @@ -67,7 +67,7 @@ void CGameConsole::Draw(const char* title) /////////////////////////////////////////////////////////////////////// if (ImGui::SmallButton("Developer mode")) { - ToggleDevCommands(); + Hooks::ToggleDevCommands(); AddLog("+--------------------------------------------------------+\n"); AddLog("|>>>>>>>>>>>>>>| DEVONLY COMMANDS TOGGLED |<<<<<<<<<<<<<<|\n"); AddLog("+--------------------------------------------------------+\n"); @@ -76,7 +76,7 @@ void CGameConsole::Draw(const char* title) ImGui::SameLine(); if (ImGui::SmallButton("Netchannel Trace")) { - ToggleNetHooks(); + Hooks::ToggleNetHooks(); AddLog("+--------------------------------------------------------+\n"); AddLog("|>>>>>>>>>>>>>>| NETCHANNEL TRACE TOGGLED |<<<<<<<<<<<<<<|\n"); AddLog("+--------------------------------------------------------+\n"); @@ -266,7 +266,7 @@ void CGameConsole::ProcessCommand(const char* command_line) void CGameConsole::ExecCommand(const char* command_line) { - org_CommandExecute(NULL, command_line); + addr_CommandExecute(NULL, command_line); } /////////////////////////////////////////////////////////////////////////// @@ -589,7 +589,7 @@ void CCompanion::HostServerSection() if (StartAsDedi) { - ToggleDevCommands(); + Hooks::ToggleDevCommands(); } } else @@ -671,7 +671,7 @@ void CCompanion::ProcessCommand(const char* command_line) void CCompanion::ExecCommand(const char* command_line) { - org_CommandExecute(NULL, command_line); + addr_CommandExecute(NULL, command_line); } //#############################################################################