diff --git a/r5dev/common/netmessages.cpp b/r5dev/common/netmessages.cpp new file mode 100644 index 00000000..4d4ebfea --- /dev/null +++ b/r5dev/common/netmessages.cpp @@ -0,0 +1,33 @@ +//===============================================================================// +// +// Purpose: +// +// $NoKeywords: $ +// +//===============================================================================// +// netmessages.cpp: implementation of the CNetMessage types. +// +/////////////////////////////////////////////////////////////////////////////////// +#include "core/stdafx.h" +#include "common/netmessages.h" +#include "engine/sys_utils.h" + +bool HSVC_Print_Process(SVC_Print* thisptr) +{ + if (thisptr->m_szText) + { + DevMsg(eDLL_T::SERVER, thisptr->m_szText); + } + + return true; // Original just return true also. +} + +void CNetMessages_Attach() +{ + CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VTable, (LPVOID)HSVC_Print_Process, (LPVOID*)&SVC_Print_Process, 3); +} + +void CNetMessages_Detach() +{ + CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VTable, (LPVOID)p_SVC_Print_Process, (LPVOID*)&SVC_Print_Process, 3); +} \ No newline at end of file diff --git a/r5dev/common/netmessages.h b/r5dev/common/netmessages.h index bbd7a939..76684bc6 100644 --- a/r5dev/common/netmessages.h +++ b/r5dev/common/netmessages.h @@ -1,7 +1,8 @@ #pragma once -struct CNetMessage +class CNetMessage { +public: void* iNetMessageVTable; int m_nGroup; bool m_bReliable; @@ -9,6 +10,17 @@ struct CNetMessage void* m_NetChannel; }; +class SVC_Print : CNetMessage +{ +public: + void* m_pMessageHandler; + char padding[8]; + const char* m_szText; + +private: + char m_szTextBuffer[2048]; +}; + struct VecNetMessages { CNetMessage** items; @@ -32,20 +44,41 @@ struct VecNetDataFragments //------------------------------------------------------------------------- inline CMemory MM_Heartbeat__ToString; // server HeartBeat? (baseserver.cpp). +//------------------------------------------------------------------------- +// SVC_Print +//------------------------------------------------------------------------- +inline CMemory p_SVC_Print_Process; +inline auto SVC_Print_Process = p_SVC_Print_Process.RCast(); + +inline void* g_pSVC_Print_VTable; + +void CNetMessages_Attach(); +void CNetMessages_Detach(); + /////////////////////////////////////////////////////////////////////////////// class HMM_Heartbeat : public IDetour { virtual void GetAdr(void) const { std::cout << "| FUN: MM_Heartbeat::ToString : 0x" << std::hex << std::uppercase << MM_Heartbeat__ToString.GetPtr() << std::setw(nPad) << " |" << std::endl; + std::cout << "| FUN: SVC_Print_Process : 0x" << std::hex << std::uppercase << p_SVC_Print_Process.GetPtr() << std::setw(nPad) << " |" << std::endl; + std::cout << "| VAR: SVC_Print_VTable : 0x" << std::hex << std::uppercase << g_pSVC_Print_VTable << std::setw(nPad) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; } virtual void GetFun(void) const { MM_Heartbeat__ToString = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x38\xE8\x00\x00\x00\x00\x3B\x05\x00\x00\x00\x00"), "xxxxx????xx????"); - // 0x1402312A0 // 48 83 EC 38 E8 ? ? ? ? 3B 05 ? ? ? ? // + // 0x1402312A0 // 48 83 EC 38 E8 ? ? ? ? 3B 05 ? ? ? ? + p_SVC_Print_Process = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\xD1\x48\x8B\x49\x18\x48\x8B\x01\x48\xFF\x60\x28"), "xxxxxxxxxxxxxx"); + // 0x1402D0810 // 48 8B D1 48 8B 49 18 48 8B 01 48 FF 60 28 + + SVC_Print_Process = p_SVC_Print_Process.RCast(); + } + virtual void GetVar(void) const + { + // We get the actual address of the vtable here, not the class instance. + g_pSVC_Print_VTable = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x74\x1E\x48\x8D\x05\x00\x00\x00\x00\x89\x5F\x08"), "xxxxx????xxx").OffsetSelf(0x2).ResolveRelativeAddressSelf(0x3, 0x7); } - virtual void GetVar(void) const { } virtual void GetCon(void) const { } virtual void Attach(void) const { } virtual void Detach(void) const { } diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 7e0852d7..4eb5f6f6 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -165,6 +165,10 @@ void Systems_Init() CHostState_Attach(); //CModelLoader_Attach(); +#if !defined(DEDICATED) && defined (GAMEDLL_S3) + CNetMessages_Attach(); // S1 and S2 require certification. +#endif // !DEDICATED && GAMEDLL_S3 + NET_Attach(); ConCommand_Attach(); IConVar_Attach(); @@ -269,6 +273,10 @@ void Systems_Shutdown() CHostState_Detach(); //CModelLoader_Detach(); +#if !defined(DEDICATED) && defined (GAMEDLL_S3) + CNetMessages_Detach(); // S1 and S2 require certification. +#endif // !DEDICATED && GAMEDLL_S3 + NET_Detach(); ConCommand_Detach(); IConVar_Detach(); diff --git a/r5dev/public/include/memaddr.h b/r5dev/public/include/memaddr.h index 81f49ffc..919d6a67 100644 --- a/r5dev/public/include/memaddr.h +++ b/r5dev/public/include/memaddr.h @@ -112,6 +112,7 @@ public: CMemory FollowNearCallSelf(ptrdiff_t opcodeOffset = 0x1, ptrdiff_t nextInstructionOffset = 0x5); CMemory ResolveRelativeAddress(ptrdiff_t registerOffset = 0x0, ptrdiff_t nextInstructionOffset = 0x4) const; CMemory ResolveRelativeAddressSelf(ptrdiff_t registerOffset = 0x0, ptrdiff_t nextInstructionOffset = 0x4); + static void HookVirtualMethod(uintptr_t virtualTable, void* pHookMethod, void** pOriginalMethod, ptrdiff_t methodIndex); private: uintptr_t ptr = 0; diff --git a/r5dev/public/memaddr.cpp b/r5dev/public/memaddr.cpp index 0d82f9c7..3133cee1 100644 --- a/r5dev/public/memaddr.cpp +++ b/r5dev/public/memaddr.cpp @@ -229,4 +229,35 @@ CMemory CMemory::ResolveRelativeAddressSelf(ptrdiff_t registerOffset, ptrdiff_t // Get function location via adding relative Address to next instruction. ptr = nextInstruction + relativeAddress; return *this; +} + +//----------------------------------------------------------------------------- +// Purpose: patch virtual method to point to a user set function +// Input : virtualTable - +// pHookMethod - +// methodIndex - +// pOriginalMethod - +// Output : void** via pOriginalMethod +//----------------------------------------------------------------------------- +void CMemory::HookVirtualMethod(uintptr_t virtualTable, void* pHookMethod, void** pOriginalMethod, ptrdiff_t methodIndex) +{ + DWORD oldProt = NULL; + + // Calculate delta to next virtual method. + uintptr_t virtualMethod = virtualTable + (methodIndex * sizeof(ptrdiff_t)); + + // Preserve original function. + uintptr_t originalFunction = *reinterpret_cast(virtualMethod); + + // Set page for current virtual method to execute n read n write. + VirtualProtect(reinterpret_cast(virtualMethod), sizeof(virtualMethod), PAGE_EXECUTE_READWRITE, &oldProt); + + // Set virtual method to our hook. + *reinterpret_cast(virtualMethod) = reinterpret_cast(pHookMethod); + + // Restore original page. + VirtualProtect(reinterpret_cast(virtualMethod), sizeof(virtualMethod), oldProt, &oldProt); + + // Move original function into argument. + *pOriginalMethod = reinterpret_cast(originalFunction); } \ No newline at end of file diff --git a/r5dev/vproj/clientsdk.vcxproj b/r5dev/vproj/clientsdk.vcxproj index 40bf68a3..7ac72918 100644 --- a/r5dev/vproj/clientsdk.vcxproj +++ b/r5dev/vproj/clientsdk.vcxproj @@ -14,6 +14,7 @@ + diff --git a/r5dev/vproj/clientsdk.vcxproj.filters b/r5dev/vproj/clientsdk.vcxproj.filters index 2e7a8e01..3d22e6f0 100644 --- a/r5dev/vproj/clientsdk.vcxproj.filters +++ b/r5dev/vproj/clientsdk.vcxproj.filters @@ -426,6 +426,9 @@ windows + + sdk\common + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index bebe8ac9..f336e4f0 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -14,6 +14,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index def9a965..15e43c09 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -456,6 +456,9 @@ windows + + sdk\common +