From 52dc6d143fec8eabb9958bacbdbf6f1b4b4af592 Mon Sep 17 00:00:00 2001 From: BobTheBob9 Date: Sun, 24 Jul 2022 20:55:34 +0100 Subject: add new memory lib --- NorthstarDLL/NorthstarDLL.vcxproj | 3 +- NorthstarDLL/NorthstarDLL.vcxproj.filters | 9 +- NorthstarDLL/audio.cpp | 4 +- NorthstarDLL/bansystem.cpp | 2 +- NorthstarDLL/buildainfile.cpp | 13 +- NorthstarDLL/chatcommand.cpp | 4 +- NorthstarDLL/clientauthhooks.cpp | 2 +- NorthstarDLL/clientchathooks.cpp | 2 +- NorthstarDLL/clientruihooks.cpp | 2 +- NorthstarDLL/clientvideooverrides.cpp | 2 +- NorthstarDLL/concommand.cpp | 4 +- NorthstarDLL/convar.cpp | 10 +- NorthstarDLL/debugoverlay.cpp | 12 +- NorthstarDLL/dedicated.cpp | 98 +++--- NorthstarDLL/dedicatedmaterialsystem.cpp | 5 +- NorthstarDLL/demofixes.cpp | 9 +- NorthstarDLL/exploitfixes.cpp | 37 +-- NorthstarDLL/exploitfixes_utf8parser.cpp | 11 +- NorthstarDLL/filesystem.cpp | 2 +- NorthstarDLL/hooks.cpp | 4 + NorthstarDLL/hooks.h | 4 +- NorthstarDLL/host.cpp | 2 +- NorthstarDLL/hoststate.cpp | 6 +- NorthstarDLL/keyvalues.cpp | 2 +- NorthstarDLL/languagehooks.cpp | 2 +- NorthstarDLL/latencyflex.cpp | 2 +- NorthstarDLL/limits.cpp | 2 +- NorthstarDLL/localchatwriter.cpp | 12 +- NorthstarDLL/logging.cpp | 6 +- NorthstarDLL/masterserver.cpp | 2 +- NorthstarDLL/maxplayers.cpp | 323 ++++++++++--------- NorthstarDLL/memory.cpp | 350 +++++++++++++++++++++ NorthstarDLL/memory.h | 87 +++++ NorthstarDLL/miscclientfixes.cpp | 6 - NorthstarDLL/miscserverfixes.cpp | 8 +- NorthstarDLL/miscserverscript.cpp | 2 +- NorthstarDLL/modlocalisation.cpp | 2 +- NorthstarDLL/modmanager.cpp | 2 +- NorthstarDLL/pch.h | 1 + NorthstarDLL/playlist.cpp | 15 +- NorthstarDLL/plugins.cpp | 2 +- NorthstarDLL/r2client.cpp | 8 +- NorthstarDLL/r2engine.cpp | 18 +- NorthstarDLL/r2server.cpp | 6 +- NorthstarDLL/rpakfilesystem.cpp | 6 +- NorthstarDLL/runframe.cpp | 4 +- NorthstarDLL/scriptbrowserhooks.cpp | 4 +- NorthstarDLL/scriptmainmenupromos.cpp | 2 +- NorthstarDLL/scriptmodmenu.cpp | 2 +- NorthstarDLL/scriptserverbrowser.cpp | 2 +- NorthstarDLL/scriptservertoclientstringcommand.cpp | 2 +- NorthstarDLL/serverauthentication.cpp | 20 +- NorthstarDLL/serverchathooks.cpp | 30 +- NorthstarDLL/serverpresence.cpp | 4 +- NorthstarDLL/sourceconsole.cpp | 2 +- NorthstarDLL/sourceinterface.cpp | 6 +- NorthstarDLL/squirrel.cpp | 135 ++++---- NorthstarDLL/tier0.cpp | 14 +- 58 files changed, 869 insertions(+), 469 deletions(-) create mode 100644 NorthstarDLL/memory.cpp create mode 100644 NorthstarDLL/memory.h delete mode 100644 NorthstarDLL/miscclientfixes.cpp diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj index fc3cddf4..081687dd 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj +++ b/NorthstarDLL/NorthstarDLL.vcxproj @@ -121,6 +121,7 @@ + @@ -571,6 +572,7 @@ + @@ -591,7 +593,6 @@ - diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters index c0ae1b24..899e0cc6 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj.filters +++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters @@ -1479,6 +1479,9 @@ Header Files\Server + + Header Files\Hooks + @@ -1517,9 +1520,6 @@ Source Files\Client - - Source Files\Client - Source Files\Server @@ -1676,6 +1676,9 @@ Source Files + + Source Files\Hooks + diff --git a/NorthstarDLL/audio.cpp b/NorthstarDLL/audio.cpp index 0aa5c9f0..e2f9f3b7 100644 --- a/NorthstarDLL/audio.cpp +++ b/NorthstarDLL/audio.cpp @@ -494,10 +494,10 @@ void, __fastcall, (int level, const char* string)) spdlog::info("[MSS] {} - {}", level, string); } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", AudioHooks, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", AudioHooks, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() Cvar_ns_print_played_sounds = new ConVar("ns_print_played_sounds", "0", FCVAR_NONE, ""); - MilesStopAll = (MilesStopAll_Type)((char*)baseAddress + 0x580850); + MilesStopAll = module.Offset(0x580850).As(); } \ No newline at end of file diff --git a/NorthstarDLL/bansystem.cpp b/NorthstarDLL/bansystem.cpp index 29e07376..989242d3 100644 --- a/NorthstarDLL/bansystem.cpp +++ b/NorthstarDLL/bansystem.cpp @@ -97,7 +97,7 @@ void ConCommand_clearbanlist(const CCommand& args) g_pBanSystem->ClearBanlist(); } -ON_DLL_LOAD_RELIESON("engine.dll", BanSystem, ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", BanSystem, ConCommand, (CModule module)) { g_pBanSystem = new ServerBanSystem; g_pBanSystem->OpenBanlist(); diff --git a/NorthstarDLL/buildainfile.cpp b/NorthstarDLL/buildainfile.cpp index 1ac73b43..c91aa30e 100644 --- a/NorthstarDLL/buildainfile.cpp +++ b/NorthstarDLL/buildainfile.cpp @@ -2,7 +2,6 @@ #include "convar.h" #include "hoststate.h" #include "r2engine.h" -#include "NSMem.h" #include #include @@ -384,16 +383,16 @@ void,, (void* aimanager, void* buf, const char* filename)) } } -ON_DLL_LOAD("server.dll", BuildAINFile, (HMODULE baseAddress)) +ON_DLL_LOAD("server.dll", BuildAINFile, (CModule module)) { AUTOHOOK_DISPATCH() Cvar_ns_ai_dumpAINfileFromLoad = new ConVar( "ns_ai_dumpAINfileFromLoad", "0", FCVAR_NONE, "For debugging: whether we should dump ain data for ains loaded from disk"); - pUnkStruct0Count = (int*)((char*)baseAddress + 0x1063BF8); - pppUnkNodeStruct0s = (UnkNodeStruct0***)((char*)baseAddress + 0x1063BE0); - pUnkLinkStruct1Count = (int*)((char*)baseAddress + 0x1063AA8); - pppUnkStruct1s = (UnkLinkStruct1***)((char*)baseAddress + 0x1063A90); - pUnkServerMapversionGlobal = (char**)((char*)baseAddress + 0xBFBE08); + pUnkStruct0Count = module.Offset(0x1063BF8).As(); + pppUnkNodeStruct0s = module.Offset(0x1063BE0).As(); + pUnkLinkStruct1Count = module.Offset(0x1063AA8).As(); + pppUnkStruct1s = module.Offset(0x1063A90).As(); + pUnkServerMapversionGlobal = module.Offset(0xBFBE08).As(); } \ No newline at end of file diff --git a/NorthstarDLL/chatcommand.cpp b/NorthstarDLL/chatcommand.cpp index 2973711c..e0530dd5 100644 --- a/NorthstarDLL/chatcommand.cpp +++ b/NorthstarDLL/chatcommand.cpp @@ -28,9 +28,9 @@ void ConCommand_log(const CCommand& args) } } -ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientChatCommand, ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientChatCommand, ConCommand, (CModule module)) { - ClientSayText = (ClientSayTextType)((char*)baseAddress + 0x54780); + ClientSayText = module.Offset(0x54780).As(); RegisterConCommand("say", ConCommand_say, "Enters a message in public chat", FCVAR_CLIENTDLL); RegisterConCommand("say_team", ConCommand_say_team, "Enters a message in team chat", FCVAR_CLIENTDLL); RegisterConCommand("log", ConCommand_log, "Log a message to the local chat window", FCVAR_CLIENTDLL); diff --git a/NorthstarDLL/clientauthhooks.cpp b/NorthstarDLL/clientauthhooks.cpp index 3ba66d6f..6d642bc2 100644 --- a/NorthstarDLL/clientauthhooks.cpp +++ b/NorthstarDLL/clientauthhooks.cpp @@ -31,7 +31,7 @@ void,, (void* a1)) AuthWithStryder(a1); } -ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientAuthHooks, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientAuthHooks, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() diff --git a/NorthstarDLL/clientchathooks.cpp b/NorthstarDLL/clientchathooks.cpp index ca783f88..e4364db5 100644 --- a/NorthstarDLL/clientchathooks.cpp +++ b/NorthstarDLL/clientchathooks.cpp @@ -71,7 +71,7 @@ SQRESULT SQ_ChatWriteLine(void* sqvm) return SQRESULT_NULL; } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientChatHooks, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientChatHooks, ClientSquirrel, (CModule module)) { AUTOHOOK_DISPATCH() diff --git a/NorthstarDLL/clientruihooks.cpp b/NorthstarDLL/clientruihooks.cpp index 4c4d54d2..abcf92d2 100644 --- a/NorthstarDLL/clientruihooks.cpp +++ b/NorthstarDLL/clientruihooks.cpp @@ -14,7 +14,7 @@ bool,, (void* a1, float* a2)) return DrawRUIFunc(a1, a2); } -ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", RUI, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", RUI, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() diff --git a/NorthstarDLL/clientvideooverrides.cpp b/NorthstarDLL/clientvideooverrides.cpp index 7729c9c8..2416e1c3 100644 --- a/NorthstarDLL/clientvideooverrides.cpp +++ b/NorthstarDLL/clientvideooverrides.cpp @@ -30,7 +30,7 @@ void*,, (const char* path, uint32_t flags)) return BinkOpen(path, flags); } -ON_DLL_LOAD_CLIENT("client.dll", BinkVideo, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("client.dll", BinkVideo, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/concommand.cpp b/NorthstarDLL/concommand.cpp index 616294f5..10621761 100644 --- a/NorthstarDLL/concommand.cpp +++ b/NorthstarDLL/concommand.cpp @@ -144,8 +144,8 @@ void RegisterConCommand( newCommand->m_pCompletionCallback = completionCallback; } -ON_DLL_LOAD("engine.dll", ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", ConCommand, (CModule module)) { - ConCommandConstructor = (ConCommandConstructorType)((char*)baseAddress + 0x415F60); + ConCommandConstructor = module.Offset(0x415F60).As(); AddMiscConCommands(); } \ No newline at end of file diff --git a/NorthstarDLL/convar.cpp b/NorthstarDLL/convar.cpp index 7bef2f6d..10e7c859 100644 --- a/NorthstarDLL/convar.cpp +++ b/NorthstarDLL/convar.cpp @@ -26,13 +26,13 @@ void* g_pIConVar_Vtable = nullptr; //----------------------------------------------------------------------------- // Purpose: ConVar interface initialization //----------------------------------------------------------------------------- -ON_DLL_LOAD("engine.dll", ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", ConVar, (CModule module)) { - conVarMalloc = (ConVarMallocType)((char*)baseAddress + 0x415C20); - conVarRegister = (ConVarRegisterType)((char*)baseAddress + 0x417230); + conVarMalloc = module.Offset(0x415C20).As(); + conVarRegister = module.Offset(0x417230).As(); - g_pConVar_Vtable = (char*)baseAddress + 0x67FD28; - g_pIConVar_Vtable = (char*)baseAddress + 0x67FDC8; + g_pConVar_Vtable = module.Offset(0x67FD28); + g_pIConVar_Vtable = module.Offset(0x67FDC8); R2::g_pCVarInterface = new SourceInterface("vstdlib.dll", "VEngineCvar007"); R2::g_pCVar = *R2::g_pCVarInterface; diff --git a/NorthstarDLL/debugoverlay.cpp b/NorthstarDLL/debugoverlay.cpp index 2004dae1..ac07c26a 100644 --- a/NorthstarDLL/debugoverlay.cpp +++ b/NorthstarDLL/debugoverlay.cpp @@ -131,17 +131,17 @@ void, __fastcall, (OverlayBase_t * pOverlay)) LeaveCriticalSection((LPCRITICAL_SECTION)((char*)sEngineModule + 0x10DB0A38)); } -ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", DebugOverlay, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", DebugOverlay, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() - RenderLine = reinterpret_cast((char*)baseAddress + 0x192A70); - RenderBox = reinterpret_cast((char*)baseAddress + 0x192520); - RenderWireframeBox = reinterpret_cast((char*)baseAddress + 0x193DA0); - sEngineModule = baseAddress; + RenderLine = module.Offset(0x192A70).As(); + RenderBox = module.Offset(0x192520).As(); + RenderWireframeBox = module.Offset(0x193DA0).As(); + sEngineModule = reinterpret_cast(module.m_nAddress); // not in g_pCVar->FindVar by this point for whatever reason, so have to get from memory - ConVar* Cvar_enable_debug_overlays = (ConVar*)((char*)baseAddress + 0x10DB0990); + ConVar* Cvar_enable_debug_overlays = module.Offset(0x10DB0990).As(); Cvar_enable_debug_overlays->SetValue(false); Cvar_enable_debug_overlays->m_pszDefaultValue = (char*)"0"; Cvar_enable_debug_overlays->AddFlags(FCVAR_CHEAT); diff --git a/NorthstarDLL/dedicated.cpp b/NorthstarDLL/dedicated.cpp index 20e6121f..25986055 100644 --- a/NorthstarDLL/dedicated.cpp +++ b/NorthstarDLL/dedicated.cpp @@ -7,7 +7,6 @@ #include "serverauthentication.h" #include "masterserver.h" #include "printcommand.h" -#include "NSMem.h" AUTOHOOK_INIT() @@ -41,8 +40,6 @@ void Sys_Printf(CDedicatedExports* dedicated, const char* msg) spdlog::info("[DEDICATED SERVER] {}", msg); } -typedef void (*CHostState__InitType)(CHostState* self); - void RunServer(CDedicatedExports* dedicated) { spdlog::info("CDedicatedExports::RunServer(): starting"); @@ -75,14 +72,23 @@ void RunServer(CDedicatedExports* dedicated) } } -AUTOHOOK(IsGameActiveWindow, engine.dll + 0x1CDC80, -bool,, ()) +// use server presence to update window title +class DedicatedConsoleServerPresence : public ServerPresenceReporter { - return true; -} + void ReportPresence(const ServerPresence* pServerPresence) override + { + SetConsoleTitleA(fmt::format( + "{} - {} {}/{} players ({})", + pServerPresence->m_sServerName, + pServerPresence->m_MapName, + pServerPresence->m_iPlayerCount, + pServerPresence->m_iMaxPlayers, + pServerPresence->m_PlaylistName) + .c_str()); + } +}; HANDLE consoleInputThreadHandle = NULL; - DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter) { while (!g_pEngine || !g_pHostState || g_pHostState->m_iCurrentState != HostState_t::HS_RUN) @@ -101,113 +107,96 @@ DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter) { input += "\n"; Cbuf_AddText(Cbuf_GetCurrentPlayer(), input.c_str(), cmd_source_t::kCommandSrcCode); - TryPrintCvarHelpForCommand(input.c_str()); + //TryPrintCvarHelpForCommand(input.c_str()); // this needs to be done on main thread, unstable in this one } } return 0; } -// use server presence to update window title -class DedicatedConsoleServerPresence : public ServerPresenceReporter +AUTOHOOK(IsGameActiveWindow, engine.dll + 0x1CDC80, bool, , ()) { - void ReportPresence(const ServerPresence* pServerPresence) override - { - SetConsoleTitleA(fmt::format("{} - {} {}/{} players ({})", - pServerPresence->m_sServerName, - pServerPresence->m_MapName, - pServerPresence->m_iPlayerCount, - pServerPresence->m_iMaxPlayers, - pServerPresence->m_PlaylistName).c_str()); - } -}; + return true; +} -ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (HMODULE engineAddress)) +ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModule module)) { spdlog::info("InitialiseDedicated"); AUTOHOOK_DISPATCH_MODULE("engine.dll") - uintptr_t ea = (uintptr_t)engineAddress; - // Host_Init // prevent a particle init that relies on client dll - NSMem::NOP(ea + 0x156799, 5); + module.Offset(0x156799).NOP(5); // Host_Init // don't call Key_Init to avoid loading some extra rsons from rpak (will be necessary to boot if we ever wanna disable rpaks entirely on dedi) - NSMem::NOP(ea + 0x1565B0, 5); + module.Offset(0x1565B0).NOP(5); { // CModAppSystemGroup::Create // force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment - auto ptr = ea + 0x1C4EBD; + MemoryAddress base = module.Offset(0x1C4EBD); // cmp => mov - NSMem::BytePatch(ptr + 1, "C6 87"); + base.Offset(1).Patch("C6 87"); // 00 => 01 - NSMem::BytePatch(ptr + 7, "01"); + base.Offset(7).Patch("01"); } // Some init that i'm not sure of that crashes // nop the call to it - NSMem::NOP(ea + 0x156A63, 5); + module.Offset(0x156A63).NOP(5); // runframeserver // nop some access violations - NSMem::NOP(ea + 0x159819, 17); + module.Offset(0x159819).NOP(17); - NSMem::NOP(ea + 0x156B4C, 7); + module.Offset(0x156B4C).NOP(7); // previously patched these, took me a couple weeks to figure out they were the issue // removing these will mess up register state when this function is over, so we'll write HS_RUN to the wrong address // so uhh, don't do that // NSMem::NOP(ea + 0x156B4C + 7, 8); - NSMem::NOP(ea + 0x156B4C + 15, 9); + module.Offset(0x156B4C).Offset(15).NOP(9); // HostState_State_NewGame // nop an access violation - NSMem::NOP(ea + 0xB934C, 9); + module.Offset(0xB934C).NOP(9); // CEngineAPI::Connect // remove call to Shader_Connect - NSMem::NOP(ea + 0x1C4D7D, 5); + module.Offset(0x1C4D7D).NOP(5); // Host_Init // remove call to ui loading stuff - NSMem::NOP(ea + 0x156595, 5); + module.Offset(0x156595).NOP(5); // some function that gets called from RunFrameServer // nop a function that makes requests to stryder, this will eventually access violation if left alone and isn't necessary anyway - NSMem::NOP(ea + 0x15A0BB, 5); + module.Offset(0x15A0BB).NOP(5); // RunFrameServer // nop a function that access violations - NSMem::NOP(ea + 0x159BF3, 5); + module.Offset(0x159BF3).NOP(5); // func that checks if origin is inited // always return 1 - NSMem::BytePatch( - ea + 0x183B70, - { - 0xB0, - 0x01, // mov al,01 - 0xC3 // ret - }); + module.Offset(0x183B70).Patch("B0 01 C3"); // mov al,01 ret // HostState_State_ChangeLevel // nop clientinterface call - NSMem::NOP(ea + 0x1552ED, 16); + module.Offset(0x1552ED).NOP(16); // HostState_State_ChangeLevel // nop clientinterface call - NSMem::NOP(ea + 0x155363, 16); + module.Offset(0x155363).NOP(16); // IVideoMode::CreateGameWindow // nop call to ShowWindow - NSMem::NOP(ea + 0x1CD146, 5); + module.Offset(0x1CD146).NOP(5); CDedicatedExports* dedicatedExports = new CDedicatedExports; @@ -215,8 +204,7 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (HMODUL dedicatedExports->Sys_Printf = Sys_Printf; dedicatedExports->RunServer = RunServer; - CDedicatedExports** exports = (CDedicatedExports**)((char*)engineAddress + 0x13F0B668); - *exports = dedicatedExports; + *module.Offset(0x13F0B668).As() = dedicatedExports; // extra potential patches: // nop engine.dll+1c67d1 and +1c67d8 to skip videomode creategamewindow @@ -268,16 +256,12 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (HMODUL spdlog::info("Console input disabled by user request"); } -ON_DLL_LOAD_DEDI("tier0.dll", DedicatedServerOrigin, (HMODULE baseAddress)) +ON_DLL_LOAD_DEDI("tier0.dll", DedicatedServerOrigin, (CModule module)) { // disable origin on dedicated // for any big ea lawyers, this can't be used to play the game without origin, game will throw a fit if you try to do anything without // an origin id as a client for dedi it's fine though, game doesn't care if origin is disabled as long as there's only a server - - NSMem::BytePatch((uintptr_t)GetProcAddress(GetModuleHandleA("tier0.dll"), "Tier0_InitOrigin"), - { - 0xC3 // ret - }); + module.GetExport("Tier0_InitOrigin").Patch("C3"); } AUTOHOOK(PrintFatalSquirrelError, server.dll + 0x794D0, @@ -287,7 +271,7 @@ void, , (void* sqvm)) g_pEngine->m_nQuitting = EngineQuitState::QUIT_TODESKTOP; } -ON_DLL_LOAD_DEDI("server.dll", DedicatedServerGameDLL, (HMODULE baseAddress)) +ON_DLL_LOAD_DEDI("server.dll", DedicatedServerGameDLL, (CModule module)) { AUTOHOOK_DISPATCH_MODULE("server.dll") } \ No newline at end of file diff --git a/NorthstarDLL/dedicatedmaterialsystem.cpp b/NorthstarDLL/dedicatedmaterialsystem.cpp index 70a07ba1..a9b7120d 100644 --- a/NorthstarDLL/dedicatedmaterialsystem.cpp +++ b/NorthstarDLL/dedicatedmaterialsystem.cpp @@ -2,7 +2,6 @@ #include "pch.h" #include "dedicated.h" #include "tier0.h" -#include "NSMem.h" AUTOHOOK_INIT() @@ -31,11 +30,11 @@ HRESULT, __stdcall, ( pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext); } -ON_DLL_LOAD_DEDI("materialsystem_dx11.dll", DedicatedServerMaterialSystem, (HMODULE baseAddress)) +ON_DLL_LOAD_DEDI("materialsystem_dx11.dll", DedicatedServerMaterialSystem, (CModule module)) { AUTOHOOK_DISPATCH() // CMaterialSystem::FindMaterial // make the game always use the error material - NSMem::BytePatch((uintptr_t)baseAddress + 0x5F0F1, {0xE9, 0x34, 0x03, 0x00}); + module.Offset(0x5F0F1).Patch("E9 34 03 00"); } \ No newline at end of file diff --git a/NorthstarDLL/demofixes.cpp b/NorthstarDLL/demofixes.cpp index fbd14d45..57a28dfc 100644 --- a/NorthstarDLL/demofixes.cpp +++ b/NorthstarDLL/demofixes.cpp @@ -1,15 +1,14 @@ #include "pch.h" #include "convar.h" -#include "NSMem.h" -ON_DLL_LOAD_CLIENT("engine.dll", EngineDemoFixes, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("engine.dll", EngineDemoFixes, (CModule module)) { // allow demo recording on loopback - NSMem::NOP((uintptr_t)baseAddress + 0x8E1B1, 2); - NSMem::NOP((uintptr_t)baseAddress + 0x56CC3, 2); + module.Offset(0x8E1B1).NOP(2); + module.Offset(0x56CC3).NOP(2); } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientDemoFixes, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientDemoFixes, ConVar, (CModule module)) { // change default values of demo cvars to enable them by default, but not autorecord // this is before Host_Init, the setvalue calls here will get overwritten by custom cfgs/launch options diff --git a/NorthstarDLL/exploitfixes.cpp b/NorthstarDLL/exploitfixes.cpp index 7c00726b..c9f7dd61 100644 --- a/NorthstarDLL/exploitfixes.cpp +++ b/NorthstarDLL/exploitfixes.cpp @@ -1,5 +1,4 @@ #include "pch.h" -#include "NSMem.h" #include "cvar.h" #include "limits.h" #include "dedicated.h" @@ -122,7 +121,7 @@ bool, __fastcall, (void* pMsg)) // 48 8B D1 48 8B 49 18 48 8B 01 48 FF 60 10 auto entry = msg->m_ConVars + i; // Safety check for memory access - if (NSMem::IsMemoryReadable(entry, sizeof(*entry))) + if (MemoryAddress(entry).IsMemoryReadable(sizeof(*entry))) { // Find null terminators @@ -375,37 +374,37 @@ engine.dll + 0x104FB0, void, , (void* self)) self, 1, "Overflowed CNetworkStringTableContainer::WriteBaselines, try restarting your client and reconnecting"); } -ON_DLL_LOAD("engine.dll", EngineExploitFixes, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", EngineExploitFixes, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(engine.dll) - CCommand__Tokenize = (bool(*)(CCommand&, const char*, R2::cmd_source_t))((char*)baseAddress + 0x418380); + CCommand__Tokenize = module.Offset(0x418380).As(); // allow client/ui to run clientcommands despite restricting servercommands - NSMem::BytePatch((uintptr_t)baseAddress + 0x4FB65, "EB 11"); - NSMem::BytePatch((uintptr_t)baseAddress + 0x4FBAC, "EB 16"); + module.Offset(0x4FB65).Patch("EB 11"); + module.Offset(0x4FBAC).Patch("EB 16"); // patch to set bWasWritingStringTableSuccessful in CNetworkStringTableContainer::WriteBaselines if it fails { - uintptr_t writeAddress = (uintptr_t)(&bWasWritingStringTableSuccessful - ((uintptr_t)baseAddress + 0x234EDC)); + MemoryAddress writeAddress(&bWasWritingStringTableSuccessful - module.Offset(0x234EDC).m_nAddress); - auto addr = (uintptr_t)baseAddress + 0x234ED2; - NSMem::BytePatch(addr, "C7 05"); - NSMem::BytePatch(addr + 2, (BYTE*)&writeAddress, sizeof(writeAddress)); + MemoryAddress addr = module.Offset(0x234ED2); + addr.Patch("C7 05"); + addr.Offset(2).Patch((BYTE*)&writeAddress, sizeof(writeAddress)); - NSMem::BytePatch(addr + 6, "00 00 00 00"); + addr.Offset(6).Patch("00 00 00 00"); - NSMem::NOP(addr + 10, 5); + addr.Offset(10).NOP(5); } } -ON_DLL_LOAD_RELIESON("server.dll", ServerExploitFixes, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("server.dll", ServerExploitFixes, ConVar, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(server.dll) // ret at the start of CServerGameClients::ClientCommandKeyValues as it has no benefit and is forwarded to client (i.e. security issue) // this prevents the attack vector of client=>server=>client, however server=>client also has clientside patches - NSMem::BytePatch((uintptr_t)baseAddress + 0x153920, "C3"); + module.Offset(0x153920).Patch("C3"); // Dumb ANTITAMPER patches (they negatively impact performance and security) constexpr const char* ANTITAMPER_EXPORTS[] = { @@ -417,15 +416,11 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerExploitFixes, ConVar, (HMODULE baseAddr // Prevent these from actually doing anything for (auto exportName : ANTITAMPER_EXPORTS) { - uintptr_t address = (uintptr_t)GetProcAddress(baseAddress, exportName); - if (!address) - { - spdlog::warn("Failed to find AntiTamper function export \"{}\"", exportName); - } - else + MemoryAddress exportAddr = module.GetExport(exportName); + if (exportAddr) { // Just return, none of them have any args or are userpurge - NSMem::BytePatch(address, "C3"); + exportAddr.Patch("C3"); spdlog::info("Patched AntiTamper function export \"{}\"", exportName); } } diff --git a/NorthstarDLL/exploitfixes_utf8parser.cpp b/NorthstarDLL/exploitfixes_utf8parser.cpp index 5627c3e3..8d6399fb 100644 --- a/NorthstarDLL/exploitfixes_utf8parser.cpp +++ b/NorthstarDLL/exploitfixes_utf8parser.cpp @@ -3,10 +3,12 @@ AUTOHOOK_INIT() +INT64(__fastcall* sub_F1320)(DWORD a1, char* a2); + // Reimplementation of an exploitable UTF decoding function in titanfall bool __fastcall CheckUTF8Valid(INT64* a1, DWORD* a2, char* strData) { - static auto sub_F1320 = (INT64(__fastcall*)(DWORD a1, char* a2))NSMem::PatternScan("engine.dll", "83 F9 7F 77 08 88 0A"); + static auto = ()NSMem::PatternScan("engine.dll", ); DWORD v3; // eax char* v4; // rbx @@ -69,8 +71,7 @@ bool __fastcall CheckUTF8Valid(INT64* a1, DWORD* a2, char* strData) { while (1) { - - if (!NSMem::IsMemoryReadable(v4, 1)) + if (!MemoryAddress(v4).IsMemoryReadable(1)) return false; // INVALID v11 = *v4++; // crash potential @@ -184,7 +185,9 @@ bool, __fastcall, (INT64 * a1, DWORD* a2, char* strData)) // 48 89 5C 24 ? 48 89 return Rson_ParseUTF8(a1, a2, strData); } -ON_DLL_LOAD("engine.dll", EngineExploitFixes_UTF8Parser, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", EngineExploitFixes_UTF8Parser, (CModule module)) { AUTOHOOK_DISPATCH() + + sub_F1320 = module.FindPattern("83 F9 7F 77 08 88 0A").As(); } \ No newline at end of file diff --git a/NorthstarDLL/filesystem.cpp b/NorthstarDLL/filesystem.cpp index 18ff3d84..eab48877 100644 --- a/NorthstarDLL/filesystem.cpp +++ b/NorthstarDLL/filesystem.cpp @@ -167,7 +167,7 @@ VPKData*,, (IFileSystem* fileSystem, const char* pVpkPath)) return ret; } -ON_DLL_LOAD("filesystem_stdio.dll", Filesystem, (HMODULE baseAddress)) +ON_DLL_LOAD("filesystem_stdio.dll", Filesystem, (CModule module)) { AUTOHOOK_DISPATCH() diff --git a/NorthstarDLL/hooks.cpp b/NorthstarDLL/hooks.cpp index bb696cdb..1be9736b 100644 --- a/NorthstarDLL/hooks.cpp +++ b/NorthstarDLL/hooks.cpp @@ -251,6 +251,8 @@ LPSTR, WINAPI, ()) std::vector calledTags; void CallLoadLibraryACallbacks(LPCSTR lpLibFileName, HMODULE moduleAddress) { + CModule cModule(moduleAddress); + while (true) { bool bDoneCalling = true; @@ -291,6 +293,8 @@ void CallLoadLibraryACallbacks(LPCSTR lpLibFileName, HMODULE moduleAddress) void CallLoadLibraryWCallbacks(LPCWSTR lpLibFileName, HMODULE moduleAddress) { + CModule cModule(moduleAddress); + while (true) { bool bDoneCalling = true; diff --git a/NorthstarDLL/hooks.h b/NorthstarDLL/hooks.h index 9e33cbbe..b6000953 100644 --- a/NorthstarDLL/hooks.h +++ b/NorthstarDLL/hooks.h @@ -1,10 +1,12 @@ #pragma once +#include "memory.h" + #include #include void InstallInitialHooks(); -typedef void (*DllLoadCallbackFuncType)(HMODULE moduleAddress); +typedef void (*DllLoadCallbackFuncType)(CModule moduleAddress); void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, std::string tag = "", std::vector reliesOn = {}); void AddDllLoadCallbackForDedicatedServer( std::string dll, DllLoadCallbackFuncType callback, std::string tag = "", std::vector reliesOn = {}); diff --git a/NorthstarDLL/host.cpp b/NorthstarDLL/host.cpp index fe5da2c5..2fcea29c 100644 --- a/NorthstarDLL/host.cpp +++ b/NorthstarDLL/host.cpp @@ -65,7 +65,7 @@ void,, (bool bDedicated)) R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "exec autoexec_ns_client", R2::cmd_source_t::kCommandSrcCode); } -ON_DLL_LOAD("engine.dll", Host_Init, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", Host_Init, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/hoststate.cpp b/NorthstarDLL/hoststate.cpp index 39d05ced..9e217a25 100644 --- a/NorthstarDLL/hoststate.cpp +++ b/NorthstarDLL/hoststate.cpp @@ -93,10 +93,10 @@ void, __fastcall, (CHostState* self, double flCurrentTime, float flFrameTime)) } -ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() - g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180); - Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070); + g_pHostState = module.Offset(0x7CF180).As(); + Cvar_hostport = module.Offset(0x13FA6070).As(); } \ No newline at end of file diff --git a/NorthstarDLL/keyvalues.cpp b/NorthstarDLL/keyvalues.cpp index 3dabf227..08c3dac8 100644 --- a/NorthstarDLL/keyvalues.cpp +++ b/NorthstarDLL/keyvalues.cpp @@ -124,7 +124,7 @@ char,, (void* self, const char* resourceName, const char* pBuffer, void* pFileSy return KeyValues__LoadFromBuffer(self, resourceName, pBuffer, pFileSystem, a5, a6, a7); } -ON_DLL_LOAD("engine.dll", KeyValues, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", KeyValues, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/languagehooks.cpp b/NorthstarDLL/languagehooks.cpp index 89db5e8d..9fe28bf2 100644 --- a/NorthstarDLL/languagehooks.cpp +++ b/NorthstarDLL/languagehooks.cpp @@ -110,7 +110,7 @@ char*,, ()) return lang; } -ON_DLL_LOAD_CLIENT("tier0.dll", LanguageHooks, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("tier0.dll", LanguageHooks, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/latencyflex.cpp b/NorthstarDLL/latencyflex.cpp index 608261aa..af223a52 100644 --- a/NorthstarDLL/latencyflex.cpp +++ b/NorthstarDLL/latencyflex.cpp @@ -18,7 +18,7 @@ void,, ()) OnRenderStart(); } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", LatencyFlex, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", LatencyFlex, ConVar, (CModule module)) { // Connect to the LatencyFleX service // LatencyFleX is an open source vendor agnostic replacement for Nvidia Reflex input latency reduction technology. diff --git a/NorthstarDLL/limits.cpp b/NorthstarDLL/limits.cpp index 60c04e16..11545358 100644 --- a/NorthstarDLL/limits.cpp +++ b/NorthstarDLL/limits.cpp @@ -162,7 +162,7 @@ bool, , (void* a1, R2::netpacket_t* packet)) return ProcessConnectionlessPacket(a1, packet); } -ON_DLL_LOAD_RELIESON("engine.dll", ServerLimits, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", ServerLimits, ConVar, (CModule module)) { AUTOHOOK_DISPATCH() diff --git a/NorthstarDLL/localchatwriter.cpp b/NorthstarDLL/localchatwriter.cpp index 62543b95..ed90acb2 100644 --- a/NorthstarDLL/localchatwriter.cpp +++ b/NorthstarDLL/localchatwriter.cpp @@ -442,12 +442,12 @@ void LocalChatWriter::InsertDefaultFade() } } -ON_DLL_LOAD_CLIENT("client.dll", LocalChatWriter, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("client.dll", LocalChatWriter, (CModule module)) { - gGameSettings = (CGameSettings**)((char*)baseAddress + 0x11BAA48); - gChatFadeLength = (CGameFloatVar**)((char*)baseAddress + 0x11BAB78); - gChatFadeSustain = (CGameFloatVar**)((char*)baseAddress + 0x11BAC08); - CHudChat::allHuds = (CHudChat**)((char*)baseAddress + 0x11BA9E8); + gGameSettings = module.Offset(0x11BAA48).As(); + gChatFadeLength = module.Offset(0x11BAB78).As(); + gChatFadeSustain = module.Offset(0x11BAC08).As(); + CHudChat::allHuds = module.Offset(0x11BA9E8).As(); - ConvertANSIToUnicode = (ConvertANSIToUnicodeType)((char*)baseAddress + 0x7339A0); + ConvertANSIToUnicode = module.Offset(0x7339A0).As(); } diff --git a/NorthstarDLL/logging.cpp b/NorthstarDLL/logging.cpp index 702955ab..860fef63 100644 --- a/NorthstarDLL/logging.cpp +++ b/NorthstarDLL/logging.cpp @@ -233,17 +233,17 @@ void InitialiseLogging() spdlog::default_logger()->set_pattern("[%H:%M:%S] [%l] %v"); } -ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", EngineSpewFuncHooks, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", EngineSpewFuncHooks, ConVar, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(engine.dll) Cvar_spewlog_enable = new ConVar("spewlog_enable", "1", FCVAR_NONE, "Enables/disables whether the engine spewfunc should be logged"); } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientPrintHooks, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientPrintHooks, ConVar, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(client.dll) Cvar_cl_showtextmsg = new ConVar("cl_showtextmsg", "1", FCVAR_NONE, "Enable/disable text messages printing on the screen."); - pInternalCenterPrint = (ICenterPrint*)((char*)baseAddress + 0x216E940); + pInternalCenterPrint = module.Offset(0x216E940).As(); } \ No newline at end of file diff --git a/NorthstarDLL/masterserver.cpp b/NorthstarDLL/masterserver.cpp index d19779d7..a3b8a9a8 100644 --- a/NorthstarDLL/masterserver.cpp +++ b/NorthstarDLL/masterserver.cpp @@ -1015,7 +1015,7 @@ void ConCommand_ns_fetchservers(const CCommand& args) MasterServerManager::MasterServerManager() : m_pendingConnectionInfo {}, m_sOwnServerId {""}, m_sOwnClientAuthToken {""} {} -ON_DLL_LOAD_RELIESON("engine.dll", MasterServer, (ConCommand, ServerPresence), (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", MasterServer, (ConCommand, ServerPresence), (CModule module)) { g_pMasterServerManager = new MasterServerManager; diff --git a/NorthstarDLL/maxplayers.cpp b/NorthstarDLL/maxplayers.cpp index 2bede85e..94998d4e 100644 --- a/NorthstarDLL/maxplayers.cpp +++ b/NorthstarDLL/maxplayers.cpp @@ -52,10 +52,9 @@ bool MaxPlayersIncreaseEnabled() return bMaxPlayersIncreaseEnabled; } -#include "NSMem.h" -template void ChangeOffset(void* addr, unsigned int offset) +template void ChangeOffset(MemoryAddress addr, unsigned int offset) { - NSMem::BytePatch((uintptr_t)addr, (BYTE*)&offset, sizeof(T)); + addr.Patch((BYTE*)&offset, sizeof(T)); } AUTOHOOK(StringTables_CreateStringTable, engine.dll + 0x22E220, @@ -74,7 +73,7 @@ void*,, (__int64 thisptr, const char* name, int maxentries, int userdatafixedsiz return StringTables_CreateStringTable(thisptr, name, maxentries, userdatafixedsize, userdatanetworkbits, flags); } -ON_DLL_LOAD("engine.dll", MaxPlayersOverride_Engine, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", MaxPlayersOverride_Engine, (CModule module)) { if (!MaxPlayersIncreaseEnabled()) return; @@ -82,22 +81,22 @@ ON_DLL_LOAD("engine.dll", MaxPlayersOverride_Engine, (HMODULE baseAddress)) AUTOHOOK_DISPATCH_MODULE(engine.dll) // patch GetPlayerLimits to ignore the boundary limit - ChangeOffset((char*)baseAddress + 0x116458, 0xEB); // jle => jmp + module.Offset(0x116458).Patch("0xEB"); // jle => jmp // patch ED_Alloc to change nFirstIndex - ChangeOffset((char*)baseAddress + 0x18F46C + 1, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1) + ChangeOffset(module.Offset(0x18F46C + 1), NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1) // patch CGameServer::SpawnServer to change GetMaxClients inline - ChangeOffset((char*)baseAddress + 0x119543 + 2, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1) + ChangeOffset(module.Offset(0x119543 + 2), NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1) // patch CGameServer::SpawnServer to change for loop - ChangeOffset((char*)baseAddress + 0x11957F + 2, NEW_MAX_PLAYERS); // original: 32 + ChangeOffset(module.Offset(0x11957F + 2), NEW_MAX_PLAYERS); // original: 32 // patch CGameServer::SpawnServer to change for loop (there are two) - ChangeOffset((char*)baseAddress + 0x119586 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1) + ChangeOffset(module.Offset(0x119586 + 2), NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1) // patch max players somewhere in CClientState - ChangeOffset((char*)baseAddress + 0x1A162C + 2, NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1) + ChangeOffset(module.Offset(0x1A162C + 2), NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1) // patch max players in userinfo stringtable creation /*{ @@ -110,10 +109,10 @@ ON_DLL_LOAD("engine.dll", MaxPlayersOverride_Engine, (HMODULE baseAddress)) // proper fix below // patch max players in userinfo stringtable creation loop - ChangeOffset((char*)baseAddress + 0x114C48 + 2, NEW_MAX_PLAYERS); // original: 32 + ChangeOffset(module.Offset(0x114C48 + 2), NEW_MAX_PLAYERS); // original: 32 // do not load prebaked SendTable message list - ChangeOffset((char*)baseAddress + 0x75859, 0xEB); // jnz -> jmp + module.Offset(0x75859).Patch("EB"); // jnz -> jmp } typedef void (*RunUserCmds_Type)(bool a1, float a2); @@ -275,7 +274,7 @@ __int64, __fastcall, (__int64 recvProp, int elements, int flags, const char* nam return SendPropArray2(recvProp, elements, flags, name, proxyFn, unk1); } -ON_DLL_LOAD("server.dll", MaxPlayersOverride_Server, (HMODULE baseAddress)) +ON_DLL_LOAD("server.dll", MaxPlayersOverride_Server, (CModule module)) { if (!MaxPlayersIncreaseEnabled()) return; @@ -283,140 +282,140 @@ ON_DLL_LOAD("server.dll", MaxPlayersOverride_Server, (HMODULE baseAddress)) AUTOHOOK_DISPATCH_MODULE(server.dll) // get required data - serverBase = baseAddress; + serverBase = (HMODULE)module.m_nAddress; RandomIntZeroMax = (decltype(RandomIntZeroMax))(GetProcAddress(GetModuleHandleA("vstdlib.dll"), "RandomIntZeroMax")); // patch max players amount - ChangeOffset((char*)baseAddress + 0x9A44D + 3, NEW_MAX_PLAYERS); // 0x20 (32) => 0x80 (128) + ChangeOffset(module.Offset(0x9A44D + 3), NEW_MAX_PLAYERS); // 0x20 (32) => 0x80 (128) // patch SpawnGlobalNonRewinding to change forced edict index - ChangeOffset((char*)baseAddress + 0x2BC403 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1) + ChangeOffset(module.Offset(0x2BC403 + 2), NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1) constexpr int CPlayerResource_OriginalSize = 4776; constexpr int CPlayerResource_AddedSize = PlayerResource_TotalSize; constexpr int CPlayerResource_ModifiedSize = CPlayerResource_OriginalSize + CPlayerResource_AddedSize; // CPlayerResource class allocation function - allocate a bigger amount to fit all new max player data - ChangeOffset((char*)baseAddress + 0x5C560A + 1, CPlayerResource_ModifiedSize); + ChangeOffset(module.Offset(0x5C560A + 1), CPlayerResource_ModifiedSize); // DT_PlayerResource::m_iPing SendProp - ChangeOffset((char*)baseAddress + 0x5C5059 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0x5C50A8 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0x5C50E2 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C5059 + 2), CPlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x5C50A8 + 2), CPlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x5C50E2 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_iPing DataMap - ChangeOffset((char*)baseAddress + 0xB94598, CPlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0xB9459C, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB945C0, PlayerResource_Ping_Size); + ChangeOffset(module.Offset(0xB94598), CPlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0xB9459C), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB945C0), PlayerResource_Ping_Size); // DT_PlayerResource::m_iTeam SendProp - ChangeOffset((char*)baseAddress + 0x5C5110 + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0x5C519C + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0x5C517E + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C5110 + 2), CPlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x5C519C + 2), CPlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x5C517E + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_iTeam DataMap - ChangeOffset((char*)baseAddress + 0xB94600, CPlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0xB94604, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB94628, PlayerResource_Team_Size); + ChangeOffset(module.Offset(0xB94600), CPlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0xB94604), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB94628), PlayerResource_Team_Size); // DT_PlayerResource::m_iPRHealth SendProp - ChangeOffset((char*)baseAddress + 0x5C51C0 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0x5C5204 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0x5C523E + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C51C0 + 2), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x5C5204 + 2), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x5C523E + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_iPRHealth DataMap - ChangeOffset((char*)baseAddress + 0xB94668, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0xB9466C, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB94690, PlayerResource_PRHealth_Size); + ChangeOffset(module.Offset(0xB94668), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0xB9466C), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB94690), PlayerResource_PRHealth_Size); // DT_PlayerResource::m_bConnected SendProp - ChangeOffset((char*)baseAddress + 0x5C526C + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x5C52B4 + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x5C52EE + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C526C + 2), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C52B4 + 2), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C52EE + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_bConnected DataMap - ChangeOffset((char*)baseAddress + 0xB946D0, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0xB946D4, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB946F8, PlayerResource_Connected_Size); + ChangeOffset(module.Offset(0xB946D0), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0xB946D4), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB946F8), PlayerResource_Connected_Size); // DT_PlayerResource::m_bAlive SendProp - ChangeOffset((char*)baseAddress + 0x5C5321 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0x5C5364 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0x5C539E + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C5321 + 2), CPlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x5C5364 + 2), CPlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x5C539E + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_bAlive DataMap - ChangeOffset((char*)baseAddress + 0xB94738, CPlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0xB9473C, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB94760, PlayerResource_Alive_Size); + ChangeOffset(module.Offset(0xB94738), CPlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0xB9473C), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB94760), PlayerResource_Alive_Size); // DT_PlayerResource::m_boolStats SendProp - ChangeOffset((char*)baseAddress + 0x5C53CC + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0x5C5414 + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0x5C544E + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x5C53CC + 2), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x5C5414 + 2), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x5C544E + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_boolStats DataMap - ChangeOffset((char*)baseAddress + 0xB947A0, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0xB947A4, NEW_MAX_PLAYERS + 1); - ChangeOffset((char*)baseAddress + 0xB947C8, PlayerResource_BoolStats_Size); + ChangeOffset(module.Offset(0xB947A0), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0xB947A4), NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xB947C8), PlayerResource_BoolStats_Size); // DT_PlayerResource::m_killStats SendProp - ChangeOffset((char*)baseAddress + 0x5C547C + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0x5C54E2 + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0x5C54FE + 4, PlayerResource_KillStats_Length); + ChangeOffset(module.Offset(0x5C547C + 2), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x5C54E2 + 2), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x5C54FE + 4), PlayerResource_KillStats_Length); // DT_PlayerResource::m_killStats DataMap - ChangeOffset((char*)baseAddress + 0xB94808, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0xB9480C, PlayerResource_KillStats_Length); - ChangeOffset((char*)baseAddress + 0xB94830, PlayerResource_KillStats_Size); + ChangeOffset(module.Offset(0xB94808), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0xB9480C), PlayerResource_KillStats_Length); + ChangeOffset(module.Offset(0xB94830), PlayerResource_KillStats_Size); // DT_PlayerResource::m_scoreStats SendProp - ChangeOffset((char*)baseAddress + 0x5C5528 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0x5C5576 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0x5C5584 + 4, PlayerResource_ScoreStats_Length); + ChangeOffset(module.Offset(0x5C5528 + 2), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x5C5576 + 2), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x5C5584 + 4), PlayerResource_ScoreStats_Length); // DT_PlayerResource::m_scoreStats DataMap - ChangeOffset((char*)baseAddress + 0xB94870, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0xB94874, PlayerResource_ScoreStats_Length); - ChangeOffset((char*)baseAddress + 0xB94898, PlayerResource_ScoreStats_Size); + ChangeOffset(module.Offset(0xB94870), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0xB94874), PlayerResource_ScoreStats_Length); + ChangeOffset(module.Offset(0xB94898), PlayerResource_ScoreStats_Size); // CPlayerResource::UpdatePlayerData - m_bConnected - ChangeOffset((char*)baseAddress + 0x5C66EE + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x5C672E + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C66EE + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C672E + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); // CPlayerResource::UpdatePlayerData - m_iPing - ChangeOffset((char*)baseAddress + 0x5C6394 + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0x5C63DB + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x5C6394 + 4), CPlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x5C63DB + 4), CPlayerResource_OriginalSize + PlayerResource_Ping_Start); // CPlayerResource::UpdatePlayerData - m_iTeam - ChangeOffset((char*)baseAddress + 0x5C63FD + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0x5C6442 + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x5C63FD + 4), CPlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x5C6442 + 4), CPlayerResource_OriginalSize + PlayerResource_Team_Start); // CPlayerResource::UpdatePlayerData - m_iPRHealth - ChangeOffset((char*)baseAddress + 0x5C645B + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0x5C64A0 + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x5C645B + 4), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x5C64A0 + 4), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start); // CPlayerResource::UpdatePlayerData - m_bConnected - ChangeOffset((char*)baseAddress + 0x5C64AA + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x5C64F0 + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C64AA + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x5C64F0 + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start); // CPlayerResource::UpdatePlayerData - m_bAlive - ChangeOffset((char*)baseAddress + 0x5C650A + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0x5C654F + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x5C650A + 4), CPlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x5C654F + 4), CPlayerResource_OriginalSize + PlayerResource_Alive_Start); // CPlayerResource::UpdatePlayerData - m_boolStats - ChangeOffset((char*)baseAddress + 0x5C6557 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0x5C65A5 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x5C6557 + 4), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x5C65A5 + 4), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start); // CPlayerResource::UpdatePlayerData - m_scoreStats - ChangeOffset((char*)baseAddress + 0x5C65C2 + 3, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0x5C65E3 + 4, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x5C65C2 + 3), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x5C65E3 + 4), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); // CPlayerResource::UpdatePlayerData - m_killStats - ChangeOffset((char*)baseAddress + 0x5C6654 + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0x5C665B + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x5C6654 + 3), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x5C665B + 3), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start); - *(DWORD*)((char*)baseAddress + 0x14E7390) = 0; - auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x5C4FE0); + *module.Offset(0x14E7390).As() = 0; + auto DT_PlayerResource_Construct = module.Offset(0x5C4FE0).As<__int64(__fastcall*)()>(); DT_PlayerResource_Construct(); constexpr int CTeam_OriginalSize = 3336; @@ -424,13 +423,13 @@ ON_DLL_LOAD("server.dll", MaxPlayersOverride_Server, (HMODULE baseAddress)) constexpr int CTeam_ModifiedSize = CTeam_OriginalSize + CTeam_AddedSize; // CTeam class allocation function - allocate a bigger amount to fit all new team player data - ChangeOffset((char*)baseAddress + 0x23924A + 1, CTeam_ModifiedSize); + ChangeOffset(module.Offset(0x23924A + 1), CTeam_ModifiedSize); // CTeam::CTeam - increase memset length to clean newly allocated data - ChangeOffset((char*)baseAddress + 0x2395AE + 2, 256 + CTeam_AddedSize); + ChangeOffset(module.Offset(0x2395AE + 2), 256 + CTeam_AddedSize); - *(DWORD*)((char*)baseAddress + 0xC945A0) = 0; - auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x238F50); + *module.Offset(0xC945A0).As() = 0; + auto DT_Team_Construct = module.Offset(0x238F50).As<__int64(__fastcall*)()>(); DT_Team_Construct(); } @@ -444,7 +443,7 @@ __int64, __fastcall, (__int64 recvProp, int elements, int flags, const char* nam return RecvPropArray2(recvProp, elements, flags, name, proxyFn); } -ON_DLL_LOAD("client.dll", MaxPlayersOverride_Client, (HMODULE baseAddress)) +ON_DLL_LOAD("client.dll", MaxPlayersOverride_Client, (CModule module)) { if (!MaxPlayersIncreaseEnabled()) return; @@ -456,154 +455,154 @@ ON_DLL_LOAD("client.dll", MaxPlayersOverride_Client, (HMODULE baseAddress)) constexpr int C_PlayerResource_ModifiedSize = C_PlayerResource_OriginalSize + C_PlayerResource_AddedSize; // C_PlayerResource class allocation function - allocate a bigger amount to fit all new max player data - ChangeOffset((char*)baseAddress + 0x164C41 + 1, C_PlayerResource_ModifiedSize); + ChangeOffset(module.Offset(0x164C41 + 1), C_PlayerResource_ModifiedSize); // C_PlayerResource::C_PlayerResource - change loop end value - ChangeOffset((char*)baseAddress + 0x1640C4 + 2, NEW_MAX_PLAYERS - 32); + ChangeOffset(module.Offset(0x1640C4 + 2), NEW_MAX_PLAYERS - 32); // C_PlayerResource::C_PlayerResource - change m_szName address ChangeOffset( - (char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class + module.Offset(0x1640D0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class // C_PlayerResource::C_PlayerResource - change m_szName address ChangeOffset( - (char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class + module.Offset(0x1640D0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class // C_PlayerResource::C_PlayerResource - increase memset length to clean newly allocated data - ChangeOffset((char*)baseAddress + 0x1640D0 + 3, 2244 + C_PlayerResource_AddedSize); + ChangeOffset(module.Offset(0x1640D0 + 3), 2244 + C_PlayerResource_AddedSize); // C_PlayerResource::UpdatePlayerName - change m_szName address - ChangeOffset((char*)baseAddress + 0x16431F + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x16431F + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName - change m_szName address 1 - ChangeOffset((char*)baseAddress + 0x1645B1 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x1645B1 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName - change m_szName address 2 - ChangeOffset((char*)baseAddress + 0x1645C0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x1645C0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName - change m_szName address 3 - ChangeOffset((char*)baseAddress + 0x1645DD + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x1645DD + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName internal func - change m_szName address 1 - ChangeOffset((char*)baseAddress + 0x164B71 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164B71 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName internal func - change m_szName address 2 - ChangeOffset((char*)baseAddress + 0x164B9B + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164B9B + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 1 - ChangeOffset((char*)baseAddress + 0x164641 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164641 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 2 - ChangeOffset((char*)baseAddress + 0x164650 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164650 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 3 - ChangeOffset((char*)baseAddress + 0x16466D + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x16466D + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 1 - ChangeOffset((char*)baseAddress + 0x164BA3 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164BA3 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 2 - ChangeOffset((char*)baseAddress + 0x164BCE + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164BCE + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 3 - ChangeOffset((char*)baseAddress + 0x164BE7 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0x164BE7 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // C_PlayerResource::m_szName - ChangeOffset((char*)baseAddress + 0xc350f8, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); - ChangeOffset((char*)baseAddress + 0xc350f8 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc350f8), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); + ChangeOffset(module.Offset(0xc350f8 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource size - ChangeOffset((char*)baseAddress + 0x163415 + 6, C_PlayerResource_ModifiedSize); + ChangeOffset(module.Offset(0x163415 + 6), C_PlayerResource_ModifiedSize); // DT_PlayerResource::m_iPing RecvProp - ChangeOffset((char*)baseAddress + 0x163492 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0x1634D6 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0x163515 + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x163492 + 2), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x1634D6 + 2), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0x163515 + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_iPing - ChangeOffset((char*)baseAddress + 0xc35170, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); - ChangeOffset((char*)baseAddress + 0xc35170 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc35170), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start); + ChangeOffset(module.Offset(0xc35170 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_iTeam RecvProp - ChangeOffset((char*)baseAddress + 0x163549 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0x1635C8 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0x1635AD + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x163549 + 2), C_PlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x1635C8 + 2), C_PlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0x1635AD + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_iTeam - ChangeOffset((char*)baseAddress + 0xc351e8, C_PlayerResource_OriginalSize + PlayerResource_Team_Start); - ChangeOffset((char*)baseAddress + 0xc351e8 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc351e8), C_PlayerResource_OriginalSize + PlayerResource_Team_Start); + ChangeOffset(module.Offset(0xc351e8 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_iPRHealth RecvProp - ChangeOffset((char*)baseAddress + 0x1635F9 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0x163625 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0x163675 + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x1635F9 + 2), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x163625 + 2), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0x163675 + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_iPRHealth - ChangeOffset((char*)baseAddress + 0xc35260, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); - ChangeOffset((char*)baseAddress + 0xc35260 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc35260), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start); + ChangeOffset(module.Offset(0xc35260 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_bConnected RecvProp - ChangeOffset((char*)baseAddress + 0x1636A9 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x1636D5 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0x163725 + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x1636A9 + 2), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x1636D5 + 2), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x163725 + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_bConnected - ChangeOffset((char*)baseAddress + 0xc352d8, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); - ChangeOffset((char*)baseAddress + 0xc352d8 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc352d8), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0xc352d8 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_bAlive RecvProp - ChangeOffset((char*)baseAddress + 0x163759 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0x163785 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0x1637D5 + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x163759 + 2), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x163785 + 2), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0x1637D5 + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_bAlive - ChangeOffset((char*)baseAddress + 0xc35350, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); - ChangeOffset((char*)baseAddress + 0xc35350 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc35350), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start); + ChangeOffset(module.Offset(0xc35350 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_boolStats RecvProp - ChangeOffset((char*)baseAddress + 0x163809 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0x163835 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0x163885 + 5, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0x163809 + 2), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x163835 + 2), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0x163885 + 5), NEW_MAX_PLAYERS + 1); // C_PlayerResource::m_boolStats - ChangeOffset((char*)baseAddress + 0xc353c8, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); - ChangeOffset((char*)baseAddress + 0xc353c8 + 4, NEW_MAX_PLAYERS + 1); + ChangeOffset(module.Offset(0xc353c8), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start); + ChangeOffset(module.Offset(0xc353c8 + 4), NEW_MAX_PLAYERS + 1); // DT_PlayerResource::m_killStats RecvProp - ChangeOffset((char*)baseAddress + 0x1638B3 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0x1638E5 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0x163935 + 5, PlayerResource_KillStats_Length); + ChangeOffset(module.Offset(0x1638B3 + 2), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x1638E5 + 2), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0x163935 + 5), PlayerResource_KillStats_Length); // C_PlayerResource::m_killStats - ChangeOffset((char*)baseAddress + 0xc35440, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); - ChangeOffset((char*)baseAddress + 0xc35440 + 4, PlayerResource_KillStats_Length); + ChangeOffset(module.Offset(0xc35440), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start); + ChangeOffset(module.Offset(0xc35440 + 4), PlayerResource_KillStats_Length); // DT_PlayerResource::m_scoreStats RecvProp - ChangeOffset((char*)baseAddress + 0x163969 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0x163995 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0x1639E5 + 5, PlayerResource_ScoreStats_Length); + ChangeOffset(module.Offset(0x163969 + 2), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x163995 + 2), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0x1639E5 + 5), PlayerResource_ScoreStats_Length); // C_PlayerResource::m_scoreStats - ChangeOffset((char*)baseAddress + 0xc354b8, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); - ChangeOffset((char*)baseAddress + 0xc354b8 + 4, PlayerResource_ScoreStats_Length); + ChangeOffset(module.Offset(0xc354b8), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start); + ChangeOffset(module.Offset(0xc354b8 + 4), PlayerResource_ScoreStats_Length); // C_PlayerResource::GetPlayerName - change m_bConnected address - ChangeOffset((char*)baseAddress + 0x164599 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x164599 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); // C_PlayerResource::GetPlayerName2 (?) - change m_bConnected address - ChangeOffset((char*)baseAddress + 0x164629 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x164629 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); // C_PlayerResource::GetPlayerName internal func - change m_bConnected address - ChangeOffset((char*)baseAddress + 0x164B13 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x164B13 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); // Some other get name func (that seems to be unused) - change m_bConnected address - ChangeOffset((char*)baseAddress + 0x164860 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x164860 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); // Some other get name func 2 (that seems to be unused too) - change m_bConnected address - ChangeOffset((char*)baseAddress + 0x164834 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); + ChangeOffset(module.Offset(0x164834 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start); - *(DWORD*)((char*)baseAddress + 0xC35068) = 0; - auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x163400); + *module.Offset(0xC35068).As() = 0; + auto DT_PlayerResource_Construct = module.Offset(0x163400).As<__int64(__fastcall*)()>(); DT_PlayerResource_Construct(); constexpr int C_Team_OriginalSize = 3200; @@ -611,15 +610,15 @@ ON_DLL_LOAD("client.dll", MaxPlayersOverride_Client, (HMODULE baseAddress)) constexpr int C_Team_ModifiedSize = C_Team_OriginalSize + C_Team_AddedSize; // C_Team class allocation function - allocate a bigger amount to fit all new team player data - ChangeOffset((char*)baseAddress + 0x182321 + 1, C_Team_ModifiedSize); + ChangeOffset(module.Offset(0x182321 + 1), C_Team_ModifiedSize); // C_Team::C_Team - increase memset length to clean newly allocated data - ChangeOffset((char*)baseAddress + 0x1804A2 + 2, 256 + C_Team_AddedSize); + ChangeOffset(module.Offset(0x1804A2 + 2), 256 + C_Team_AddedSize); // DT_Team size - ChangeOffset((char*)baseAddress + 0xC3AA0C, C_Team_ModifiedSize); + ChangeOffset(module.Offset(0xC3AA0C), C_Team_ModifiedSize); - *(DWORD*)((char*)baseAddress + 0xC3AFF8) = 0; - auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x17F950); + *module.Offset(0xC3AFF8).As() = 0; + auto DT_Team_Construct = module.Offset(0x17F950).As<__int64(__fastcall*)()>(); DT_Team_Construct(); } \ No newline at end of file diff --git a/NorthstarDLL/memory.cpp b/NorthstarDLL/memory.cpp new file mode 100644 index 00000000..e1662fda --- /dev/null +++ b/NorthstarDLL/memory.cpp @@ -0,0 +1,350 @@ +#include "pch.h" +#include "memory.h" + +MemoryAddress::MemoryAddress() : m_nAddress(0) {} +MemoryAddress::MemoryAddress(const uintptr_t nAddress) : m_nAddress(nAddress) {} +MemoryAddress::MemoryAddress(const void* pAddress) : m_nAddress(reinterpret_cast(pAddress)) {} + +// operators +MemoryAddress::operator uintptr_t() const +{ + return m_nAddress; +} + +MemoryAddress::operator void* () const +{ + return reinterpret_cast(m_nAddress); +} + +MemoryAddress::operator bool() const +{ + return m_nAddress != 0; +} + +bool MemoryAddress::operator==(const MemoryAddress& other) const +{ + return m_nAddress == other.m_nAddress; +} + +bool MemoryAddress::operator!=(const MemoryAddress& other) const +{ + return m_nAddress != other.m_nAddress; +} + +bool MemoryAddress::operator==(const uintptr_t& addr) const +{ + return m_nAddress == addr; +} + +bool MemoryAddress::operator!=(const uintptr_t& addr) const +{ + return m_nAddress != addr; +} + +MemoryAddress MemoryAddress::operator+(const MemoryAddress& other) const +{ + return Offset(other.m_nAddress); +} + +MemoryAddress MemoryAddress::operator-(const MemoryAddress& other) const +{ + return MemoryAddress(m_nAddress - other.m_nAddress); +} + +MemoryAddress MemoryAddress::operator+(const uintptr_t& addr) const +{ + return Offset(addr); +} + +MemoryAddress MemoryAddress::operator-(const uintptr_t& addr) const +{ + return MemoryAddress(m_nAddress - addr); +} + +MemoryAddress MemoryAddress::operator*() const +{ + return Deref(); +} + +// traversal +MemoryAddress MemoryAddress::Offset(const uintptr_t nOffset) const +{ + return MemoryAddress(m_nAddress + nOffset); +} + +MemoryAddress MemoryAddress::Deref(const int nNumDerefs) const +{ + uintptr_t ret = m_nAddress; + for (int i = 0; i < nNumDerefs; i++) + ret = *reinterpret_cast(ret); + + return MemoryAddress(ret); +} + +// patching +void MemoryAddress::Patch(const uint8_t* pBytes, const size_t nSize) +{ + if (nSize) + WriteProcessMemory(GetCurrentProcess(), reinterpret_cast(m_nAddress), pBytes, nSize, NULL); +} + +void MemoryAddress::Patch(const std::initializer_list bytes) +{ + uint8_t* pBytes = new uint8_t[bytes.size()]; + + int i = 0; + for (const uint8_t& byte : bytes) + pBytes[i++] = byte; + + Patch(pBytes, bytes.size()); + delete[] pBytes; +} + +inline std::vector HexBytesToString(const char* pHexString) +{ + std::vector ret; + + int size = strlen(pHexString); + for (int i = 0; i < size; i++) + { + // If this is a space character, ignore it + if (isspace(pHexString[i])) + continue; + + if (i < size - 1) + { + BYTE result = 0; + for (int j = 0; j < 2; j++) + { + int val = 0; + char c = *(pHexString + i + j); + if (c >= 'a') + { + val = c - 'a' + 0xA; + } + else if (c >= 'A') + { + val = c - 'A' + 0xA; + } + else if (isdigit(c)) + { + val = c - '0'; + } + else + { + assert(false, "Failed to parse invalid hex string."); + val = -1; + } + + result += (j == 0) ? val * 16 : val; + } + ret.push_back(result); + } + + i++; + } + + return ret; +} + +void MemoryAddress::Patch(const char* pBytes) +{ + std::vector vBytes = HexBytesToString(pBytes); + Patch(vBytes.data(), vBytes.size()); +} + +void MemoryAddress::NOP(const size_t nSize) +{ + uint8_t* pBytes = new uint8_t[nSize]; + + memset(pBytes, 0x90, nSize); + Patch(pBytes, nSize); + + delete[] pBytes; +} + +bool MemoryAddress::IsMemoryReadable(const size_t nSize) +{ + static SYSTEM_INFO sysInfo; + if (!sysInfo.dwPageSize) + GetSystemInfo(&sysInfo); + + MEMORY_BASIC_INFORMATION memInfo; + if (!VirtualQuery(reinterpret_cast(m_nAddress), &memInfo, sizeof(memInfo))) + return false; + + return memInfo.RegionSize >= nSize && memInfo.State & MEM_COMMIT && !(memInfo.Protect & PAGE_NOACCESS); +} + + + +CModule::CModule(const HMODULE pModule) +{ + MODULEINFO mInfo {0}; + + if (pModule && pModule != INVALID_HANDLE_VALUE) + GetModuleInformation(GetCurrentProcess(), pModule, &mInfo, sizeof(MODULEINFO)); + + m_nModuleSize = static_cast(mInfo.SizeOfImage); + m_pModuleBase = reinterpret_cast(mInfo.lpBaseOfDll); + m_nAddress = m_pModuleBase; + + if (!m_nModuleSize || !m_pModuleBase) + return; + + m_pDOSHeader = reinterpret_cast(m_pModuleBase); + m_pNTHeaders = reinterpret_cast(m_pModuleBase + m_pDOSHeader->e_lfanew); + + const IMAGE_SECTION_HEADER* hSection = IMAGE_FIRST_SECTION(m_pNTHeaders); // Get first image section. + + for (WORD i = 0; i < m_pNTHeaders->FileHeader.NumberOfSections; i++) // Loop through the sections. + { + const IMAGE_SECTION_HEADER& hCurrentSection = hSection[i]; // Get current section. + + ModuleSections_t moduleSection = ModuleSections_t( + std::string(reinterpret_cast(hCurrentSection.Name)), + static_cast(m_pModuleBase + hCurrentSection.VirtualAddress), + hCurrentSection.SizeOfRawData); + + if (!strcmp((const char*)hCurrentSection.Name, ".text")) + m_ExecutableCode = moduleSection; + else if (!strcmp((const char*)hCurrentSection.Name, ".pdata")) + m_ExceptionTable = moduleSection; + else if (!strcmp((const char*)hCurrentSection.Name, ".data")) + m_RunTimeData = moduleSection; + else if (!strcmp((const char*)hCurrentSection.Name, ".rdata")) + m_ReadOnlyData = moduleSection; + + m_vModuleSections.push_back(moduleSection); // Push back a struct with the section data. + } +} + +CModule::CModule(const char* pModuleName) : CModule(GetModuleHandleA(pModuleName)) {} + +MemoryAddress CModule::GetExport(const char* pExportName) +{ + return MemoryAddress(reinterpret_cast(GetProcAddress(reinterpret_cast(m_nAddress), pExportName))); +} + +MemoryAddress CModule::FindPattern(const uint8_t* pPattern, const char* pMask) +{ + if (!m_ExecutableCode.IsSectionValid()) + return MemoryAddress(); + + uint64_t nBase = static_cast(m_ExecutableCode.m_pSectionBase); + uint64_t nSize = static_cast(m_ExecutableCode.m_nSectionSize); + + const uint8_t* pData = reinterpret_cast(nBase); + const uint8_t* pEnd = pData + static_cast(nSize) - strlen(pMask); + + int nMasks[64]; // 64*16 = enough masks for 1024 bytes. + int iNumMasks = static_cast(ceil(static_cast(strlen(pMask)) / 16.f)); + + memset(nMasks, '\0', iNumMasks * sizeof(int)); + for (intptr_t i = 0; i < iNumMasks; ++i) + { + for (intptr_t j = strnlen(pMask + i * 16, 16) - 1; j >= 0; --j) + { + if (pMask[i * 16 + j] == 'x') + { + _bittestandset(reinterpret_cast(&nMasks[i]), j); + } + } + } + __m128i xmm1 = _mm_loadu_si128(reinterpret_cast(pPattern)); + __m128i xmm2, xmm3, msks; + for (; pData != pEnd; _mm_prefetch(reinterpret_cast(++pData + 64), _MM_HINT_NTA)) + { + if (pPattern[0] == pData[0]) + { + xmm2 = _mm_loadu_si128(reinterpret_cast(pData)); + msks = _mm_cmpeq_epi8(xmm1, xmm2); + if ((_mm_movemask_epi8(msks) & nMasks[0]) == nMasks[0]) + { + for (uintptr_t i = 1; i < static_cast(iNumMasks); ++i) + { + xmm2 = _mm_loadu_si128(reinterpret_cast((pData + i * 16))); + xmm3 = _mm_loadu_si128(reinterpret_cast((pPattern + i * 16))); + msks = _mm_cmpeq_epi8(xmm2, xmm3); + if ((_mm_movemask_epi8(msks) & nMasks[i]) == nMasks[i]) + { + if ((i + 1) == iNumMasks) + { + return MemoryAddress(const_cast(pData)); + } + } + else + goto CONTINUE; + } + + return MemoryAddress((&*(const_cast(pData)))); + } + } + + CONTINUE:; + } + + return MemoryAddress(); +} + +inline std::pair, std::string> MaskedBytesFromPattern(const char* pPatternString) +{ + std::vector vRet; + std::string sMask; + + int size = strlen(pPatternString); + for (int i = 0; i < size; i++) + { + // If this is a space character, ignore it + if (isspace(pPatternString[i])) + continue; + + if (pPatternString[i] == '?') + { + // Add a wildcard + vRet.push_back(0); + sMask.append("?"); + } + else if (i < size - 1) + { + BYTE result = 0; + for (int j = 0; j < 2; j++) + { + int val = 0; + char c = *(pPatternString + i + j); + if (c >= 'a') + { + val = c - 'a' + 0xA; + } + else if (c >= 'A') + { + val = c - 'A' + 0xA; + } + else if (isdigit(c)) + { + val = c - '0'; + } + else + { + assert(false, "Failed to parse invalid pattern string."); + val = -1; + } + + result += (j == 0) ? val * 16 : val; + } + + vRet.push_back(result); + sMask.append("x"); + } + + i++; + } + + return std::make_pair(vRet, sMask); +} + +MemoryAddress CModule::FindPattern(const char* pPattern) +{ + const auto pattern = MaskedBytesFromPattern(pPattern); + return FindPattern(pattern.first.data(), pattern.second.c_str()); +} \ No newline at end of file diff --git a/NorthstarDLL/memory.h b/NorthstarDLL/memory.h new file mode 100644 index 00000000..7ed4ed59 --- /dev/null +++ b/NorthstarDLL/memory.h @@ -0,0 +1,87 @@ +#pragma once + +class MemoryAddress +{ + public: + uintptr_t m_nAddress; + + public: + MemoryAddress(); + MemoryAddress(const uintptr_t nAddress); + MemoryAddress(const void* pAddress); + + //operators + operator uintptr_t() const; + operator void*() const; + operator bool() const; + + bool operator==(const MemoryAddress& other) const; + bool operator!=(const MemoryAddress& other) const; + bool operator==(const uintptr_t& addr) const; + bool operator!=(const uintptr_t& addr) const; + + MemoryAddress operator+(const MemoryAddress& other) const; + MemoryAddress operator-(const MemoryAddress& other) const; + MemoryAddress operator+(const uintptr_t& other) const; + MemoryAddress operator-(const uintptr_t& other) const; + MemoryAddress operator*() const; + + template T As() { return reinterpret_cast(m_nAddress); } + + // traversal + MemoryAddress Offset(const uintptr_t nOffset) const; + MemoryAddress Deref(const int nNumDerefs = 1) const; + + // patching + void Patch(const uint8_t* pBytes, const size_t nSize); + void Patch(const std::initializer_list bytes); + void Patch(const char* pBytes); + void NOP(const size_t nSize); + + bool IsMemoryReadable(const size_t nSize); +}; + +// based on https://github.com/Mauler125/r5sdk/blob/master/r5dev/public/include/module.h +class CModule : public MemoryAddress +{ + public: + struct ModuleSections_t + { + ModuleSections_t(void) = default; + ModuleSections_t(const std::string& svSectionName, uintptr_t pSectionBase, size_t nSectionSize) + : m_svSectionName(svSectionName), m_pSectionBase(pSectionBase), m_nSectionSize(nSectionSize) + { + } + + bool IsSectionValid(void) const + { + return m_nSectionSize != 0; + } + + std::string m_svSectionName; // Name of section. + uintptr_t m_pSectionBase {}; // Start address of section. + size_t m_nSectionSize {}; // Size of section. + }; + + ModuleSections_t m_ExecutableCode; + ModuleSections_t m_ExceptionTable; + ModuleSections_t m_RunTimeData; + ModuleSections_t m_ReadOnlyData; + + private: + std::string m_svModuleName; + uintptr_t m_pModuleBase {}; + DWORD m_nModuleSize {}; + IMAGE_NT_HEADERS64* m_pNTHeaders = nullptr; + IMAGE_DOS_HEADER* m_pDOSHeader = nullptr; + std::vector m_vModuleSections; + + public: + CModule() = delete; // no default, we need a module name + CModule(const HMODULE pModule); + CModule(const char* pModuleName); + + MemoryAddress GetExport(const char* pExportName); + MemoryAddress FindPattern(const uint8_t* pPattern, const char* pMask); + MemoryAddress FindPattern(const char* pPattern); +}; \ No newline at end of file diff --git a/NorthstarDLL/miscclientfixes.cpp b/NorthstarDLL/miscclientfixes.cpp deleted file mode 100644 index 475b0efa..00000000 --- a/NorthstarDLL/miscclientfixes.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "pch.h" -#include "convar.h" -#include "NSMem.h" - -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", MiscClientFixes, ConVar, (HMODULE baseAddress)) { -} \ No newline at end of file diff --git a/NorthstarDLL/miscserverfixes.cpp b/NorthstarDLL/miscserverfixes.cpp index 926779b7..1f33cc44 100644 --- a/NorthstarDLL/miscserverfixes.cpp +++ b/NorthstarDLL/miscserverfixes.cpp @@ -1,11 +1,7 @@ #include "pch.h" -#include "NSMem.h" - -ON_DLL_LOAD("server.dll", MiscServerFixes, (HMODULE baseAddress)) +ON_DLL_LOAD("server.dll", MiscServerFixes, (CModule module)) { - uintptr_t ba = (uintptr_t)baseAddress; - // nop out call to VGUI shutdown since it crashes the game when quitting from the console - NSMem::NOP(ba + 0x154A96, 5); + module.Offset(0x154A96).NOP(5); } \ No newline at end of file diff --git a/NorthstarDLL/miscserverscript.cpp b/NorthstarDLL/miscserverscript.cpp index 1b075079..d41c4afe 100644 --- a/NorthstarDLL/miscserverscript.cpp +++ b/NorthstarDLL/miscserverscript.cpp @@ -46,7 +46,7 @@ SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm) return SQRESULT_NOTNULL; } -ON_DLL_LOAD_RELIESON("server.dll", MiscServerScriptCommands, ServerSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("server.dll", MiscServerScriptCommands, ServerSquirrel, (CModule module)) { g_pServerSquirrel->AddFuncRegistration( "void", "NSEarlyWritePlayerIndexPersistenceForLeave", "int playerIndex", "", SQ_EarlyWritePlayerIndexPersistenceForLeave); diff --git a/NorthstarDLL/modlocalisation.cpp b/NorthstarDLL/modlocalisation.cpp index e1820e4c..66a8977f 100644 --- a/NorthstarDLL/modlocalisation.cpp +++ b/NorthstarDLL/modlocalisation.cpp @@ -27,7 +27,7 @@ bool,, (void* pVguiLocalize, const char* path, const char* pathId, char unknown) return ret; } -ON_DLL_LOAD_CLIENT("localize.dll", Localize, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("localize.dll", Localize, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/modmanager.cpp b/NorthstarDLL/modmanager.cpp index b0ff609e..61554faf 100644 --- a/NorthstarDLL/modmanager.cpp +++ b/NorthstarDLL/modmanager.cpp @@ -636,7 +636,7 @@ fs::path GetCompiledAssetsPath() return fs::path(GetNorthstarPrefix() + COMPILED_ASSETS_SUFFIX); } -ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (CModule module)) { g_pModManager = new ModManager; diff --git a/NorthstarDLL/pch.h b/NorthstarDLL/pch.h index e76bd75f..f13e936f 100644 --- a/NorthstarDLL/pch.h +++ b/NorthstarDLL/pch.h @@ -23,6 +23,7 @@ #include "spdlog/spdlog.h" #include "libcurl/include/curl/curl.h" #include "hooks.h" +#include "memory.h" template ReturnType CallVFunc(int index, void* thisPtr, Args... args) { diff --git a/NorthstarDLL/playlist.cpp b/NorthstarDLL/playlist.cpp index b8fadc98..a685bedd 100644 --- a/NorthstarDLL/playlist.cpp +++ b/NorthstarDLL/playlist.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "playlist.h" -#include "NSMem.h" #include "concommand.h" #include "convar.h" #include "squirrel.h" @@ -91,14 +90,14 @@ void ConCommand_setplaylistvaroverride(const CCommand& args) R2::SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1)); } -ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (CModule module)) { AUTOHOOK_DISPATCH() - R2::GetCurrentPlaylistName = (const char* (*)())((char*)baseAddress + 0x18C640); - R2::SetCurrentPlaylist = (void (*)(const char*))((char*)baseAddress + 0x18EB20); - R2::SetPlaylistVarOverride = (void (*)(const char*, const char*))((char*)baseAddress + 0x18ED00); - R2::GetCurrentPlaylistVar = (const char* (*)(const char*, bool))((char*)baseAddress + 0x18C680); + R2::GetCurrentPlaylistName = module.Offset(0x18C640).As(); + R2::SetCurrentPlaylist = module.Offset(0x18EB20).As (); + R2::SetPlaylistVarOverride = module.Offset(0x18ED00).As(); + R2::GetCurrentPlaylistVar = module.Offset(0x18C680).As(); // playlist is the name of the command on respawn servers, but we already use setplaylist so can't get rid of it RegisterConCommand("playlist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE); @@ -114,8 +113,8 @@ ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (HMODULE // patch to prevent clc_SetPlaylistVarOverride from being able to crash servers if we reach max overrides due to a call to Error (why is // this possible respawn, wtf) todo: add a warning for this - NSMem::BytePatch((uintptr_t)baseAddress + 0x18ED8D, "C3"); + module.Offset(0x18ED8D).Patch("C3"); // patch to allow setplaylistvaroverride to be called before map init on dedicated and private match launched through the game - NSMem::NOP((uintptr_t)baseAddress + 0x18ED17, 6); + module.Offset(0x18ED17).NOP(6); } \ No newline at end of file diff --git a/NorthstarDLL/plugins.cpp b/NorthstarDLL/plugins.cpp index d34e0392..221981e7 100644 --- a/NorthstarDLL/plugins.cpp +++ b/NorthstarDLL/plugins.cpp @@ -386,7 +386,7 @@ int getPlayerInfoBool(bool* out_ptr, PlayerInfoType var) return n; } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", PluginCommands, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", PluginCommands, ClientSquirrel, (CModule module)) { // i swear there's a way to make this not have be run in 2 contexts but i can't figure it out // some funcs i need are just not available in UI or CLIENT diff --git a/NorthstarDLL/r2client.cpp b/NorthstarDLL/r2client.cpp index e973ff79..6eb3c6c6 100644 --- a/NorthstarDLL/r2client.cpp +++ b/NorthstarDLL/r2client.cpp @@ -11,10 +11,10 @@ namespace R2 GetBaseLocalClientType GetBaseLocalClient; } // namespace R2 -ON_DLL_LOAD("engine.dll", R2EngineClient, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", R2EngineClient, (CModule module)) { - g_pLocalPlayerUserID = (char*)baseAddress + 0x13F8E688; - g_pLocalPlayerOriginToken = (char*)baseAddress + 0x13979C80; + g_pLocalPlayerUserID = module.Offset(0x13F8E688).As(); + g_pLocalPlayerOriginToken = module.Offset(0x13979C80).As(); - GetBaseLocalClient = (GetBaseLocalClientType)((char*)baseAddress + 0x78200); + GetBaseLocalClient = module.Offset(0x78200).As(); } \ No newline at end of file diff --git a/NorthstarDLL/r2engine.cpp b/NorthstarDLL/r2engine.cpp index 883178ee..451928af 100644 --- a/NorthstarDLL/r2engine.cpp +++ b/NorthstarDLL/r2engine.cpp @@ -13,23 +13,21 @@ namespace R2 CEngine* g_pEngine; void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...); - CBaseClient* g_pClientArray; server_state_t* g_pServerState; } // namespace R2 -ON_DLL_LOAD("engine.dll", R2Engine, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", R2Engine, (CModule module)) { - Cbuf_GetCurrentPlayer = (Cbuf_GetCurrentPlayerType)((char*)baseAddress + 0x120630); - Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0); - Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0); - - g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8); + Cbuf_GetCurrentPlayer = module.Offset(0x120630).As(); + Cbuf_AddText = module.Offset(0x1203B0).As(); + Cbuf_Execute = module.Offset(0x1204B0).As(); - CBaseClient__Disconnect = (void (*)(void*, uint32_t, const char*, ...))((char*)baseAddress + 0x1012C0); + g_pEngine = module.Offset(0x7D70C8).Deref().As(); // new - g_pServerState = (server_state_t*)((char*)baseAddress + 0x12A53D48); + CBaseClient__Disconnect = module.Offset(0x1012C0).As(); + g_pClientArray = module.Offset(0x12A53F90).As(); - g_pClientArray = (CBaseClient*)((char*)baseAddress + 0x12A53F90); + g_pServerState = module.Offset(0x12A53D48).As(); } \ No newline at end of file diff --git a/NorthstarDLL/r2server.cpp b/NorthstarDLL/r2server.cpp index 8d04beff..b83ba5f7 100644 --- a/NorthstarDLL/r2server.cpp +++ b/NorthstarDLL/r2server.cpp @@ -10,8 +10,8 @@ namespace R2 CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex); } // namespace R2 -ON_DLL_LOAD("server.dll", R2GameServer, (HMODULE baseAddress)) +ON_DLL_LOAD("server.dll", R2GameServer, (CModule module)) { - Server_GetEntityByIndex = (CBaseEntity*(*)(int))((char*)baseAddress + 0xFB820); - UTIL_PlayerByIndex = (CBasePlayer*(__fastcall*)(int))((char*)baseAddress + 0x26AA10); + Server_GetEntityByIndex = module.Offset(0xFB820).As(); + UTIL_PlayerByIndex = module.Offset(0x26AA10).As(); } \ No newline at end of file diff --git a/NorthstarDLL/rpakfilesystem.cpp b/NorthstarDLL/rpakfilesystem.cpp index 28d8b101..b83c4408 100644 --- a/NorthstarDLL/rpakfilesystem.cpp +++ b/NorthstarDLL/rpakfilesystem.cpp @@ -202,14 +202,14 @@ void*, , (const char* pPath, void* a2)) } -ON_DLL_LOAD("engine.dll", RpakFilesystem, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", RpakFilesystem, (CModule module)) { AUTOHOOK_DISPATCH(); g_pPakLoadManager = new PakLoadManager; - g_pakLoadApi = *(PakLoadFuncs**)((char*)baseAddress + 0x5BED78); - pUnknownPakLoadSingleton = (void**)((char*)baseAddress + 0x7C5E20); + g_pakLoadApi = module.Offset(0x5BED78).Deref().As(); + pUnknownPakLoadSingleton = module.Offset(0x7C5E20).As(); LoadPakAsyncHook.Dispatch(g_pakLoadApi->LoadPakAsync); UnloadPakHook.Dispatch(g_pakLoadApi->UnloadPak); diff --git a/NorthstarDLL/runframe.cpp b/NorthstarDLL/runframe.cpp index ac0f3055..19a0a122 100644 --- a/NorthstarDLL/runframe.cpp +++ b/NorthstarDLL/runframe.cpp @@ -7,12 +7,12 @@ AUTOHOOK_INIT() AUTOHOOK(CEngine__Frame, engine.dll + 0x1C8650, -void, , (R2::CEngine* self)) +void, __fastcall, (R2::CEngine* self)) { CEngine__Frame(self); } -ON_DLL_LOAD("engine.dll", RunFrame, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", RunFrame, (CModule module)) { AUTOHOOK_DISPATCH() } \ No newline at end of file diff --git a/NorthstarDLL/scriptbrowserhooks.cpp b/NorthstarDLL/scriptbrowserhooks.cpp index 63f97bb7..1b6adc6a 100644 --- a/NorthstarDLL/scriptbrowserhooks.cpp +++ b/NorthstarDLL/scriptbrowserhooks.cpp @@ -15,9 +15,9 @@ void,, (char* pUrl, char flags)) *bIsOriginOverlayEnabled = bIsOriginOverlayEnabledOriginal; } -ON_DLL_LOAD_CLIENT("engine.dll", ScriptExternalBrowserHooks, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT("engine.dll", ScriptExternalBrowserHooks, (CModule module)) { AUTOHOOK_DISPATCH() - bIsOriginOverlayEnabled = (bool*)baseAddress + 0x13978255; + bIsOriginOverlayEnabled = module.Offset(0x13978255).As(); } \ No newline at end of file diff --git a/NorthstarDLL/scriptmainmenupromos.cpp b/NorthstarDLL/scriptmainmenupromos.cpp index 5d86c603..becc08ea 100644 --- a/NorthstarDLL/scriptmainmenupromos.cpp +++ b/NorthstarDLL/scriptmainmenupromos.cpp @@ -127,7 +127,7 @@ SQRESULT SQ_GetCustomMainMenuPromoData(void* sqvm) return SQRESULT_NOTNULL; } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptMainMenuPrograms, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptMainMenuPrograms, ClientSquirrel, (CModule module)) { g_pUISquirrel->AddFuncRegistration("void", "NSRequestCustomMainMenuPromos", "", "", SQ_RequestCustomMainMenuPromos); g_pUISquirrel->AddFuncRegistration("bool", "NSHasCustomMainMenuPromoData", "", "", SQ_HasCustomMainMenuPromoData); diff --git a/NorthstarDLL/scriptmodmenu.cpp b/NorthstarDLL/scriptmodmenu.cpp index 77866e84..436d980c 100644 --- a/NorthstarDLL/scriptmodmenu.cpp +++ b/NorthstarDLL/scriptmodmenu.cpp @@ -174,7 +174,7 @@ SQRESULT SQ_ReloadMods(void* sqvm) return SQRESULT_NULL; } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptModMenu, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptModMenu, ClientSquirrel, (CModule module)) { g_pUISquirrel->AddFuncRegistration("array", "NSGetModNames", "", "Returns the names of all loaded mods", SQ_GetModNames); g_pUISquirrel->AddFuncRegistration( diff --git a/NorthstarDLL/scriptserverbrowser.cpp b/NorthstarDLL/scriptserverbrowser.cpp index 13f4b7e6..059eb3e0 100644 --- a/NorthstarDLL/scriptserverbrowser.cpp +++ b/NorthstarDLL/scriptserverbrowser.cpp @@ -409,7 +409,7 @@ SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm) return SQRESULT_NULL; } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerBrowser, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerBrowser, ClientSquirrel, (CModule module)) { g_pUISquirrel->AddFuncRegistration("bool", "NSIsMasterServerAuthenticated", "", "", SQ_IsMasterServerAuthenticated); g_pUISquirrel->AddFuncRegistration("void", "NSRequestServerList", "", "", SQ_RequestServerList); diff --git a/NorthstarDLL/scriptservertoclientstringcommand.cpp b/NorthstarDLL/scriptservertoclientstringcommand.cpp index ecd44175..e1b91ee6 100644 --- a/NorthstarDLL/scriptservertoclientstringcommand.cpp +++ b/NorthstarDLL/scriptservertoclientstringcommand.cpp @@ -13,7 +13,7 @@ void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg) } } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerToClientStringCommand, ClientSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerToClientStringCommand, ClientSquirrel, (CModule module)) { RegisterConCommand( "ns_script_servertoclientstringcommand", diff --git a/NorthstarDLL/serverauthentication.cpp b/NorthstarDLL/serverauthentication.cpp index 3fe6b10b..a8aa678d 100644 --- a/NorthstarDLL/serverauthentication.cpp +++ b/NorthstarDLL/serverauthentication.cpp @@ -10,7 +10,6 @@ #include "concommand.h" #include "dedicated.h" #include "nsprefix.h" -#include "NSMem.h" #include "tier0.h" #include "r2engine.h" #include "r2client.h" @@ -341,7 +340,7 @@ void ConCommand_ns_resetpersistence(const CCommand& args) g_pServerAuthentication->m_bForceResetLocalPlayerPersistence = true; } -ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), (CModule module)) { AUTOHOOK_DISPATCH() @@ -361,23 +360,12 @@ ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), ( RegisterConCommand( "ns_resetpersistence", ConCommand_ns_resetpersistence, "resets your pdata when you next enter the lobby", FCVAR_NONE); - uintptr_t ba = (uintptr_t)baseAddress; - // patch to disable kicking based on incorrect serverfilter in connectclient, since we repurpose it for use as an auth token - NSMem::BytePatch( - ba + 0x114655, - "EB" // jz => jmp - ); + module.Offset(0x114655).Patch("EB"); // patch to disable fairfight marking players as cheaters and kicking them - NSMem::BytePatch( - ba + 0x101012, - "E9 90 00" // jz => jmp - ); + module.Offset(0x101012).Patch("E9 90 00"); // patch to allow same of multiple account - NSMem::BytePatch( - ba + 0x114510, - "EB" // jz => jmp - ); + module.Offset(0x114510).Patch("EB"); } \ No newline at end of file diff --git a/NorthstarDLL/serverchathooks.cpp b/NorthstarDLL/serverchathooks.cpp index da7d34dd..6adb831b 100644 --- a/NorthstarDLL/serverchathooks.cpp +++ b/NorthstarDLL/serverchathooks.cpp @@ -147,27 +147,27 @@ SQRESULT SQ_BroadcastMessage(void* sqvm) return SQRESULT_NULL; } -ON_DLL_LOAD("engine.dll", EngineServerChatHooks, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", EngineServerChatHooks, (CModule module)) { - g_pServerGameDLL = (CServerGameDLL*)((char*)baseAddress + 0x13F0AA98); + g_pServerGameDLL = module.Offset(0x13F0AA98).As(); } -ON_DLL_LOAD_RELIESON("server.dll", ServerChatHooks, ServerSquirrel, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("server.dll", ServerChatHooks, ServerSquirrel, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(server.dll) - CServerGameDLL__OnReceivedSayTextMessage = (void(__fastcall*)(CServerGameDLL*, unsigned int, const char*, int))((char*)baseAddress + 0x1595C0); - CRecipientFilter__Construct = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9440); - CRecipientFilter__Destruct = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9700); - CRecipientFilter__AddAllPlayers = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9940); - CRecipientFilter__AddRecipient = (void(__fastcall*)(CRecipientFilter*, const R2::CBasePlayer*))((char*)baseAddress + 0x1E9b30); - CRecipientFilter__MakeReliable = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1EA4E0); - - UserMessageBegin = (void(__fastcall*)(CRecipientFilter*, const char*))((char*)baseAddress + 0x15C520); - MessageEnd = (void(__fastcall*)())((char*)baseAddress + 0x158880); - MessageWriteByte = (void(__fastcall*)(int))((char*)baseAddress + 0x158A90); - MessageWriteString = (void(__fastcall*)(const char*))((char*)baseAddress + 0x158D00); - MessageWriteBool = (void(__fastcall*)(bool))((char*)baseAddress + 0x158A00); + CServerGameDLL__OnReceivedSayTextMessage = module.Offset(0x1595C0).As(); + CRecipientFilter__Construct = module.Offset(0x1E9440).As(); + CRecipientFilter__Destruct = module.Offset(0x1E9700).As(); + CRecipientFilter__AddAllPlayers = module.Offset(0x1E9940).As(); + CRecipientFilter__AddRecipient = module.Offset(0x1E9B30).As(); + CRecipientFilter__MakeReliable = module.Offset(0x1EA4E0).As(); + + UserMessageBegin = module.Offset(0x15C520).As(); + MessageEnd = module.Offset(0x158880).As(); + MessageWriteByte = module.Offset(0x158A90).As(); + MessageWriteString = module.Offset(0x158D00).As(); + MessageWriteBool = module.Offset(0x158A00).As(); // Chat sending functions g_pServerSquirrel->AddFuncRegistration("void", "NSSendMessage", "int playerIndex, string text, bool isTeam", "", SQ_SendMessage); diff --git a/NorthstarDLL/serverpresence.cpp b/NorthstarDLL/serverpresence.cpp index 3db39c82..287c66da 100644 --- a/NorthstarDLL/serverpresence.cpp +++ b/NorthstarDLL/serverpresence.cpp @@ -199,9 +199,9 @@ void ServerPresenceManager::SetPlayerCount(const int iPlayerCount) m_ServerPresence.m_iPlayerCount = iPlayerCount; } -ON_DLL_LOAD_RELIESON("engine.dll", ServerPresence, ConVar, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("engine.dll", ServerPresence, ConVar, (CModule module)) { g_pServerPresence = new ServerPresenceManager; - Cvar_hostname = *(ConVar**)((char*)baseAddress + 0x1315bae8); + Cvar_hostname = module.Offset(0x1315BAE8).Deref().As(); } \ No newline at end of file diff --git a/NorthstarDLL/sourceconsole.cpp b/NorthstarDLL/sourceconsole.cpp index 02216898..7d96770c 100644 --- a/NorthstarDLL/sourceconsole.cpp +++ b/NorthstarDLL/sourceconsole.cpp @@ -62,7 +62,7 @@ void InitialiseConsoleOnInterfaceCreation() spdlog::default_logger()->sinks().push_back(consoleLogger); } -ON_DLL_LOAD_CLIENT_RELIESON("client.dll", SourceConsole, ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD_CLIENT_RELIESON("client.dll", SourceConsole, ConCommand, (CModule module)) { g_pSourceGameConsole = new SourceInterface("client.dll", "GameConsole004"); diff --git a/NorthstarDLL/sourceinterface.cpp b/NorthstarDLL/sourceinterface.cpp index 08de9628..3e4db390 100644 --- a/NorthstarDLL/sourceinterface.cpp +++ b/NorthstarDLL/sourceinterface.cpp @@ -36,17 +36,17 @@ void*,, (const char* pName, const int* pReturnCode)) return ret; } -ON_DLL_LOAD("client.dll", ClientInterface, (HMODULE baseAddress)) +ON_DLL_LOAD("client.dll", ClientInterface, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(client.dll) } -ON_DLL_LOAD("server.dll", ServerInterface, (HMODULE baseAddress)) +ON_DLL_LOAD("server.dll", ServerInterface, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(server.dll) } -ON_DLL_LOAD("engine.dll", EngineInterface, (HMODULE baseAddress)) +ON_DLL_LOAD("engine.dll", EngineInterface, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(engine.dll) } \ No newline at end of file diff --git a/NorthstarDLL/squirrel.cpp b/NorthstarDLL/squirrel.cpp index e2333dad..15c2b3a5 100644 --- a/NorthstarDLL/squirrel.cpp +++ b/NorthstarDLL/squirrel.cpp @@ -4,7 +4,6 @@ #include "modmanager.h" #include "dedicated.h" #include "r2engine.h" -#include "NSMem.h" AUTOHOOK_INIT() @@ -235,65 +234,65 @@ template void ConCommand_script(const CCommand& args) g_pServerSquirrel->ExecuteCode(args.ArgS()); } -ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(client.dll) g_pClientSquirrel = new SquirrelManager; g_pUISquirrel = new SquirrelManager; - g_pClientSquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0); - g_pUISquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0); - - g_pClientSquirrel->__sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110); - g_pUISquirrel->__sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110); - g_pClientSquirrel->__sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860); - g_pUISquirrel->__sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860); - - g_pClientSquirrel->__sq_call = (sq_callType)((char*)baseAddress + 0x8650); - g_pUISquirrel->__sq_call = (sq_callType)((char*)baseAddress + 0x8650); - - g_pClientSquirrel->__sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0); - g_pUISquirrel->__sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0); - g_pClientSquirrel->__sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70); - g_pUISquirrel->__sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70); - - g_pClientSquirrel->__sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440); - g_pUISquirrel->__sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440); - g_pClientSquirrel->__sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0); - g_pUISquirrel->__sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0); - g_pClientSquirrel->__sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800); - g_pUISquirrel->__sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800); - g_pClientSquirrel->__sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710); - g_pUISquirrel->__sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710); - g_pClientSquirrel->__sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470); - g_pUISquirrel->__sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8470); - - g_pClientSquirrel->__sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0); - g_pUISquirrel->__sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0); - g_pClientSquirrel->__sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0); - g_pUISquirrel->__sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0); - g_pClientSquirrel->__sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100); - g_pUISquirrel->__sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100); - g_pClientSquirrel->__sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130); - g_pUISquirrel->__sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130); - g_pClientSquirrel->__sq_get = (sq_getType)((char*)baseAddress + 0x7C30); - g_pUISquirrel->__sq_get = (sq_getType)((char*)baseAddress + 0x7C30); + g_pClientSquirrel->RegisterSquirrelFunc = module.Offset(0x108E0).As(); + g_pUISquirrel->RegisterSquirrelFunc = module.Offset(0x108E0).As(); + + g_pClientSquirrel->__sq_compilebuffer = module.Offset(0x3110).As(); + g_pUISquirrel->__sq_compilebuffer = module.Offset(0x3110).As(); + g_pClientSquirrel->__sq_pushroottable = module.Offset(0x5860).As(); + g_pUISquirrel->__sq_pushroottable = module.Offset(0x5860).As(); + + g_pClientSquirrel->__sq_call = module.Offset(0x8650).As(); + g_pUISquirrel->__sq_call = module.Offset(0x8650).As(); + + g_pClientSquirrel->__sq_newarray = module.Offset(0x39F0).As(); + g_pUISquirrel->__sq_newarray = module.Offset(0x39F0).As(); + g_pClientSquirrel->__sq_arrayappend = module.Offset(0x3C70).As(); + g_pUISquirrel->__sq_arrayappend = module.Offset(0x3C70).As(); + + g_pClientSquirrel->__sq_pushstring = module.Offset(0x3440).As(); + g_pUISquirrel->__sq_pushstring = module.Offset(0x3440).As(); + g_pClientSquirrel->__sq_pushinteger = module.Offset(0x36A0).As(); + g_pUISquirrel->__sq_pushinteger = module.Offset(0x36A0).As(); + g_pClientSquirrel->__sq_pushfloat = module.Offset(0x3800).As(); + g_pUISquirrel->__sq_pushfloat = module.Offset(0x3800).As(); + g_pClientSquirrel->__sq_pushbool = module.Offset(0x3710).As(); + g_pUISquirrel->__sq_pushbool = module.Offset(0x3710).As(); + g_pClientSquirrel->__sq_raiseerror = module.Offset(0x8470).As(); + g_pUISquirrel->__sq_raiseerror = module.Offset(0x8470).As(); + + g_pClientSquirrel->__sq_getstring = module.Offset(0x60C0).As(); + g_pUISquirrel->__sq_getstring = module.Offset(0x60C0).As(); + g_pClientSquirrel->__sq_getinteger = module.Offset(0x60E0).As(); + g_pUISquirrel->__sq_getinteger = module.Offset(0x60E0).As(); + g_pClientSquirrel->__sq_getfloat = module.Offset(0x6100).As(); + g_pUISquirrel->__sq_getfloat = module.Offset(0x6100).As(); + g_pClientSquirrel->__sq_getbool = module.Offset(0x6130).As(); + g_pUISquirrel->__sq_getbool = module.Offset(0x6130).As(); + g_pClientSquirrel->__sq_get = module.Offset(0x7C30).As(); + g_pUISquirrel->__sq_get = module.Offset(0x7C30).As(); // uiscript_reset concommand: don't loop forever if compilation fails - NSMem::NOP((uintptr_t)baseAddress + 0x3C6E4C, 6); + module.Offset(0x3C6E4C).NOP(6); - MAKEHOOK((char*)baseAddress + 0x12B00, &SQPrintHook, &ClientSQPrint); // client print function - MAKEHOOK((char*)baseAddress + 0x12BA0, &SQPrintHook, &UISQPrint); // ui print function + MAKEHOOK(module.Offset(0x12B00), &SQPrintHook, &ClientSQPrint); // client print function + MAKEHOOK(module.Offset(0x12BA0), &SQPrintHook, &UISQPrint); // ui print function - MAKEHOOK((char*)baseAddress + 0x26130, &CreateNewVMHook, &ClientCreateNewVM); // client createnewvm function - MAKEHOOK((char*)baseAddress + 0x26E70, &DestroyVMHook, &ClientDestroyVM); // client destroyvm function + MAKEHOOK(module.Offset(0x26130), &CreateNewVMHook, &ClientCreateNewVM); // client createnewvm function + MAKEHOOK(module.Offset(0x26E70), &DestroyVMHook, &ClientDestroyVM); // client destroyvm function MAKEHOOK( - (char*)baseAddress + 0x79A50, + module.Offset(0x79A50), &ScriptCompileErrorHook, &ClientSQCompileError); // client compileerror function MAKEHOOK( - (char*)baseAddress + 0x10190, + module.Offset(0x10190), &CallScriptInitCallbackHook, &ClientCallScriptInitCallback); // client callscriptinitcallback function @@ -301,42 +300,42 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (HMODULE baseAddr RegisterConCommand("script_ui", ConCommand_script, "Executes script code on the ui vm", FCVAR_CLIENTDLL); } -ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (HMODULE baseAddress)) +ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(server.dll) g_pServerSquirrel = new SquirrelManager; - g_pServerSquirrel->RegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10); + g_pServerSquirrel->RegisterSquirrelFunc = module.Offset(0x1DD10).As(); - g_pServerSquirrel->__sq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110); - g_pServerSquirrel->__sq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840); - g_pServerSquirrel->__sq_call = (sq_callType)((char*)baseAddress + 0x8620); + g_pServerSquirrel->__sq_compilebuffer = module.Offset(0x3110).As(); + g_pServerSquirrel->__sq_pushroottable = module.Offset(0x5840).As(); + g_pServerSquirrel->__sq_call = module.Offset(0x8620).As(); - g_pServerSquirrel->__sq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0); - g_pServerSquirrel->__sq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70); + g_pServerSquirrel->__sq_newarray = module.Offset(0x39F0).As(); + g_pServerSquirrel->__sq_arrayappend = module.Offset(0x3C70).As(); - g_pServerSquirrel->__sq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440); - g_pServerSquirrel->__sq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0); - g_pServerSquirrel->__sq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800); - g_pServerSquirrel->__sq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710); - g_pServerSquirrel->__sq_raiseerror = (sq_raiseerrorType)((char*)baseAddress + 0x8440); + g_pServerSquirrel->__sq_pushstring = module.Offset(0x3440).As(); + g_pServerSquirrel->__sq_pushinteger = module.Offset(0x36A0).As(); + g_pServerSquirrel->__sq_pushfloat = module.Offset(0x3800).As(); + g_pServerSquirrel->__sq_pushbool = module.Offset(0x3710).As(); + g_pServerSquirrel->__sq_raiseerror = module.Offset(0x8440).As(); - g_pServerSquirrel->__sq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0); - g_pServerSquirrel->__sq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0); - g_pServerSquirrel->__sq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0); - g_pServerSquirrel->__sq_getbool = (sq_getboolType)((char*)baseAddress + 0x6110); - g_pServerSquirrel->__sq_get = (sq_getType)((char*)baseAddress + 0x7C00); + g_pServerSquirrel->__sq_getstring = module.Offset(0x60A0).As(); + g_pServerSquirrel->__sq_getinteger = module.Offset(0x60C0).As(); + g_pServerSquirrel->__sq_getfloat = module.Offset(0x60E0).As(); + g_pServerSquirrel->__sq_getbool = module.Offset(0x6110).As(); + g_pServerSquirrel->__sq_get = module.Offset(0x7C00).As(); - MAKEHOOK((char*)baseAddress + 0x1FE90, &SQPrintHook, &ServerSQPrint); // server print function - MAKEHOOK((char*)baseAddress + 0x260E0, &CreateNewVMHook, &ServerCreateNewVM); // server createnewvm function - MAKEHOOK((char*)baseAddress + 0x26E20, &DestroyVMHook, &ServerDestroyVM); // server destroyvm function + MAKEHOOK(module.Offset(0x1FE90), &SQPrintHook, &ServerSQPrint); // server print function + MAKEHOOK(module.Offset(0x260E0), &CreateNewVMHook, &ServerCreateNewVM); // server createnewvm function + MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook, &ServerDestroyVM); // server destroyvm function MAKEHOOK( - (char*)baseAddress + 0x799E0, + module.Offset(0x799E0), &ScriptCompileErrorHook, &ServerSQCompileError); // server compileerror function MAKEHOOK( - (char*)baseAddress + 0x1D5C0, + module.Offset(0x1D5C0), &CallScriptInitCallbackHook, &ServerCallScriptInitCallback); // server callscriptinitcallback function diff --git a/NorthstarDLL/tier0.cpp b/NorthstarDLL/tier0.cpp index a4ac7752..b2461c7f 100644 --- a/NorthstarDLL/tier0.cpp +++ b/NorthstarDLL/tier0.cpp @@ -19,19 +19,19 @@ CreateGlobalMemAllocType CreateGlobalMemAlloc; void TryCreateGlobalMemAlloc() { // init memalloc stuff - CreateGlobalMemAlloc = reinterpret_cast(GetProcAddress(GetModuleHandleA("tier0.dll"), "CreateGlobalMemAlloc")); + CreateGlobalMemAlloc = + reinterpret_cast(GetProcAddress(GetModuleHandleA("tier0.dll"), "CreateGlobalMemAlloc")); Tier0::g_pMemAllocSingleton = CreateGlobalMemAlloc(); // if it already exists, this returns the preexisting IMemAlloc instance } -ON_DLL_LOAD("tier0.dll", Tier0GameFuncs, (HMODULE baseAddress)) +ON_DLL_LOAD("tier0.dll", Tier0GameFuncs, (CModule module)) { // shouldn't be necessary, but do this just in case TryCreateGlobalMemAlloc(); // setup tier0 funcs - Tier0::Error = reinterpret_cast(GetProcAddress(baseAddress, "Error")); - Tier0::CommandLine = reinterpret_cast(GetProcAddress(baseAddress, "CommandLine")); - Tier0::Plat_FloatTime = reinterpret_cast(GetProcAddress(baseAddress, "Plat_FloatTime")); - Tier0::ThreadInServerFrameThread = - reinterpret_cast(GetProcAddress(baseAddress, "ThreadInServerFrameThread")); + Tier0::Error = module.GetExport("Error").As(); + Tier0::CommandLine = module.GetExport("CommandLine").As(); + Tier0::Plat_FloatTime = module.GetExport("Plat_FloatTime").As(); + Tier0::ThreadInServerFrameThread = module.GetExport("ThreadInServerFrameThread").As(); } \ No newline at end of file -- cgit v1.2.3