From 4c4d605d10109e02708984755405bbe0947ef5c4 Mon Sep 17 00:00:00 2001
From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com>
Date: Thu, 8 Jul 2021 15:33:31 +0100
Subject: initial commit
---
.../NorthstarDedicatedTest.vcxproj | 209 +++++++++++++++++++++
.../NorthstarDedicatedTest.vcxproj.filters | 123 ++++++++++++
NorthstarDedicatedTest/context.cpp | 16 ++
NorthstarDedicatedTest/context.h | 11 ++
NorthstarDedicatedTest/dedicated.cpp | 101 ++++++++++
NorthstarDedicatedTest/dedicated.h | 30 +++
NorthstarDedicatedTest/dllmain.cpp | 49 +++++
NorthstarDedicatedTest/hooks.cpp | 90 +++++++++
NorthstarDedicatedTest/hooks.h | 7 +
NorthstarDedicatedTest/hookutils.cpp | 57 ++++++
NorthstarDedicatedTest/hookutils.h | 34 ++++
NorthstarDedicatedTest/include/MinHook.h | 186 ++++++++++++++++++
NorthstarDedicatedTest/include/MinHook.x64.dll | Bin 0 -> 15360 bytes
NorthstarDedicatedTest/include/MinHook.x64.lib | Bin 0 -> 4048 bytes
NorthstarDedicatedTest/include/MinHook.x86.dll | Bin 0 -> 12288 bytes
NorthstarDedicatedTest/include/MinHook.x86.lib | Bin 0 -> 4238 bytes
NorthstarDedicatedTest/include/tier0.def | 10 +
NorthstarDedicatedTest/include/tier0.exp | Bin 0 -> 1636 bytes
NorthstarDedicatedTest/include/tier0.lib | Bin 0 -> 2840 bytes
NorthstarDedicatedTest/logging.cpp | 52 +++++
NorthstarDedicatedTest/logging.h | 11 ++
NorthstarDedicatedTest/main.h | 3 +
NorthstarDedicatedTest/pch.cpp | 5 +
NorthstarDedicatedTest/pch.h | 11 ++
NorthstarDedicatedTest/sigscanning.cpp | 39 ++++
NorthstarDedicatedTest/sigscanning.h | 7 +
NorthstarDedicatedTest/sourceconsole.cpp | 14 ++
NorthstarDedicatedTest/sourceconsole.h | 90 +++++++++
NorthstarDedicatedTest/sourceinterface.cpp | 13 ++
NorthstarDedicatedTest/sourceinterface.h | 24 +++
NorthstarDedicatedTest/squirrel.cpp | 67 +++++++
NorthstarDedicatedTest/squirrel.h | 26 +++
NorthstarDedicatedTest/tier0.cpp | 33 ++++
NorthstarDedicatedTest/tier0.h | 9 +
34 files changed, 1327 insertions(+)
create mode 100644 NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
create mode 100644 NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
create mode 100644 NorthstarDedicatedTest/context.cpp
create mode 100644 NorthstarDedicatedTest/context.h
create mode 100644 NorthstarDedicatedTest/dedicated.cpp
create mode 100644 NorthstarDedicatedTest/dedicated.h
create mode 100644 NorthstarDedicatedTest/dllmain.cpp
create mode 100644 NorthstarDedicatedTest/hooks.cpp
create mode 100644 NorthstarDedicatedTest/hooks.h
create mode 100644 NorthstarDedicatedTest/hookutils.cpp
create mode 100644 NorthstarDedicatedTest/hookutils.h
create mode 100644 NorthstarDedicatedTest/include/MinHook.h
create mode 100644 NorthstarDedicatedTest/include/MinHook.x64.dll
create mode 100644 NorthstarDedicatedTest/include/MinHook.x64.lib
create mode 100644 NorthstarDedicatedTest/include/MinHook.x86.dll
create mode 100644 NorthstarDedicatedTest/include/MinHook.x86.lib
create mode 100644 NorthstarDedicatedTest/include/tier0.def
create mode 100644 NorthstarDedicatedTest/include/tier0.exp
create mode 100644 NorthstarDedicatedTest/include/tier0.lib
create mode 100644 NorthstarDedicatedTest/logging.cpp
create mode 100644 NorthstarDedicatedTest/logging.h
create mode 100644 NorthstarDedicatedTest/main.h
create mode 100644 NorthstarDedicatedTest/pch.cpp
create mode 100644 NorthstarDedicatedTest/pch.h
create mode 100644 NorthstarDedicatedTest/sigscanning.cpp
create mode 100644 NorthstarDedicatedTest/sigscanning.h
create mode 100644 NorthstarDedicatedTest/sourceconsole.cpp
create mode 100644 NorthstarDedicatedTest/sourceconsole.h
create mode 100644 NorthstarDedicatedTest/sourceinterface.cpp
create mode 100644 NorthstarDedicatedTest/sourceinterface.h
create mode 100644 NorthstarDedicatedTest/squirrel.cpp
create mode 100644 NorthstarDedicatedTest/squirrel.h
create mode 100644 NorthstarDedicatedTest/tier0.cpp
create mode 100644 NorthstarDedicatedTest/tier0.h
(limited to 'NorthstarDedicatedTest')
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
new file mode 100644
index 00000000..8af2d3e0
--- /dev/null
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -0,0 +1,209 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {cfad2623-064f-453c-8196-79ee10292e32}
+ NorthstarDedicatedTest
+ 10.0
+ Northstar
+
+
+
+ DynamicLibrary
+ true
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ stdcpp17
+
+
+ Windows
+ true
+ false
+ %(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ stdcpp17
+
+
+ Windows
+ true
+ true
+ true
+ false
+ %(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ stdcpp17
+ $(ProjectDir)include;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ false
+ $(ProjectDir)include\MinHook.x64.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ stdcpp17
+ $(ProjectDir)include;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ true
+ true
+ false
+ $(ProjectDir)include\MinHook.x64.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
new file mode 100644
index 00000000..e9e523e8
--- /dev/null
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -0,0 +1,123 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {d4199e4b-10d2-43ce-af9c-e1fa79e1e64e}
+
+
+ {4d322431-dcaa-4f75-aee0-3b6371cf52a6}
+
+
+ {94259c8c-5411-48bf-af4f-46ca32b7d0bb}
+
+
+ {4f525372-34a8-40b3-8a95-81d77cdfcf7f}
+
+
+ {4db0d1e9-9035-457f-87f1-5dc3f13b6b9e}
+
+
+ {947835db-67d6-42c0-870d-62743f85231f}
+
+
+ {8b8ed12a-9269-4dc3-b932-0daefdf6a388}
+
+
+ {b6f79919-9735-476d-8798-067a75cbeca0}
+
+
+ {ca657be5-c2d8-4322-a689-1154aaafe57b}
+
+
+
+
+ Header Files
+
+
+ Header Files\include
+
+
+ Header Files\Shared\Hooks
+
+
+ Header Files\Shared\Hooks
+
+
+ Header Files\Shared
+
+
+ Header Files
+
+
+ Header Files\Dedicated
+
+
+ Header Files\Client
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared\Hooks
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\Shared\Hooks
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared\Hooks
+
+
+ Source Files\Dedicated
+
+
+ Source Files\Client
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared\Hooks
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared
+
+
+
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/context.cpp b/NorthstarDedicatedTest/context.cpp
new file mode 100644
index 00000000..6cd9d885
--- /dev/null
+++ b/NorthstarDedicatedTest/context.cpp
@@ -0,0 +1,16 @@
+#include "pch.h"
+#include "context.h"
+
+const char* GetContextName(Context context)
+{
+ if (context == NONE)
+ return "";
+ if (context == CLIENT)
+ return "CLIENT";
+ else if (context == SERVER)
+ return "SERVER";
+ else if (context == UI)
+ return "UI";
+
+ return nullptr;
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/context.h b/NorthstarDedicatedTest/context.h
new file mode 100644
index 00000000..05506973
--- /dev/null
+++ b/NorthstarDedicatedTest/context.h
@@ -0,0 +1,11 @@
+#pragma once
+
+enum Context
+{
+ NONE,
+ CLIENT,
+ SERVER,
+ UI // this is used exclusively in scripts
+};
+
+const char* GetContextName(Context context);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
new file mode 100644
index 00000000..ce4723cb
--- /dev/null
+++ b/NorthstarDedicatedTest/dedicated.cpp
@@ -0,0 +1,101 @@
+#include "pch.h"
+#include "dedicated.h"
+#include "hookutils.h"
+
+#include
+
+bool IsDedicated()
+{
+ // temp: should get this from commandline
+ return false;
+}
+
+void InitialiseDedicated(HMODULE engineAddress)
+{
+ std::cout << "InitialiseDedicated()" << std::endl;
+
+ while (!IsDebuggerPresent())
+ Sleep(100);
+
+ // create binary patches
+ {
+ // CEngineAPI::SetStartupInfo
+ // prevents englishclient_frontend from loading
+
+ char* ptr = (char*)engineAddress + 0x1C7CBE;
+ TempReadWrite rw(ptr);
+
+ // je => jmp
+ *ptr = (char)0xEB;
+ }
+
+ {
+ // CModAppSystemGroup::Create
+ // force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment
+ char* ptr = (char*)engineAddress + 0x1C4EBD;
+ TempReadWrite rw(ptr);
+
+ // cmp => mov
+ *(ptr + 1) = (char)0xC6;
+ *(ptr + 2) = (char)0x87;
+
+ // 00 => 01
+ *((char*)ptr + 7) = (char)0x01;
+ }
+
+ {
+ // Some init that i'm not sure of that crashes
+ char* ptr = (char*)engineAddress + 0x156A63;
+ TempReadWrite rw(ptr);
+
+ // nop the call to it
+ *ptr = (char)0x90;
+ *(ptr + 1) = (char)0x90;
+ *(ptr + 2) = (char)0x90;
+ *(ptr + 3) = (char)0x90;
+ *(ptr + 4) = (char)0x90;
+ }
+
+ CDedicatedExports* dedicatedApi = new CDedicatedExports;
+ dedicatedApi->Sys_Printf = Sys_Printf;
+ dedicatedApi->RunServer = RunServer;
+
+ // double ptr to dedicatedApi
+ intptr_t* ptr = (intptr_t*)((char*)engineAddress + 0x13F0B668);
+
+ // ptr to dedicatedApi
+ intptr_t* doublePtr = new intptr_t;
+ *doublePtr = (intptr_t)dedicatedApi;
+
+ // ptr to ptr
+ *ptr = (intptr_t)doublePtr;
+}
+
+void Sys_Printf(CDedicatedExports* dedicated, char* msg)
+{
+ std::cout << msg << std::endl;
+}
+
+void RunServer(CDedicatedExports* dedicated)
+{
+ Sys_Printf(dedicated, (char*)"CDedicatedServerAPI::RunServer(): starting");
+
+ HMODULE engine = GetModuleHandleA("engine.dll");
+ CEngine__Frame engineFrame = (CEngine__Frame)((char*)engine + 0x1C8650);
+ CEngineAPI__ActivateSimulation engineApiStartSimulation = (CEngineAPI__ActivateSimulation)((char*)engine + 0x1C4370);
+
+ void* cEnginePtr = (void*)((char*)engine + 0x7D70C8);
+
+ CEngineAPI__SetMap engineApiSetMap = (CEngineAPI__SetMap)((char*)engine + 0x1C7B30);
+
+ engineApiSetMap(nullptr, "mp_lobby; net_usesocketsforloopback 1");
+ Sys_Printf(dedicated, (char*)"CDedicatedServerAPI::RunServer(): map mp_lobby");
+
+ while (true)
+ {
+ engineFrame(cEnginePtr);
+ //engineApiStartSimulation(nullptr, true);
+ Sys_Printf(dedicated, (char*)"engine->Frame()");
+ Sleep(50);
+ }
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicated.h b/NorthstarDedicatedTest/dedicated.h
new file mode 100644
index 00000000..61d430ac
--- /dev/null
+++ b/NorthstarDedicatedTest/dedicated.h
@@ -0,0 +1,30 @@
+#pragma once
+
+bool IsDedicated();
+
+struct CDedicatedExports; // forward declare
+
+// functions for CDedicatedServerAPI
+typedef void (*DedicatedSys_Printf)(CDedicatedExports* dedicated, char* msg);
+typedef void (*DedicatedRunServer)(CDedicatedExports* dedicated);
+
+void Sys_Printf(CDedicatedExports* dedicated, char* msg);
+void RunServer(CDedicatedExports* dedicated);
+
+// functions for running dedicated server
+typedef bool (*CEngine__Frame)(void* engineSelf);
+typedef void (*CEngineAPI__SetMap)(void* engineApiSelf, const char* pMapName);
+typedef void (*CEngineAPI__ActivateSimulation)(void* engineApiSelf, bool bActive);
+
+// struct used internally
+struct CDedicatedExports
+{
+ char unused[64];
+ DedicatedSys_Printf Sys_Printf; // base + 64
+ DedicatedRunServer RunServer; // base + 72
+};
+
+// hooking stuff
+extern bool bDedicatedHooksInitialised;
+void InitialiseDedicated(HMODULE moduleAddress);
+
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
new file mode 100644
index 00000000..f71a39a8
--- /dev/null
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -0,0 +1,49 @@
+#include "pch.h"
+#include "hooks.h"
+#include "main.h"
+#include "squirrel.h"
+#include "dedicated.h"
+#include "sourceconsole.h"
+#include
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ DisableThreadLibraryCalls(hModule);
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ InitialiseNorthstar();
+
+ return TRUE;
+}
+
+// this is called from the injector and initialises stuff, dllmain is called multiple times while this should only be called once
+void InitialiseNorthstar()
+{
+ AllocConsole();
+ freopen("CONOUT$", "w", stdout);
+ AddLoggingSink(DefaultLoggingSink);
+
+ // apply hooks
+ InstallInitialHooks();
+
+ if (IsDedicated())
+ AddDllLoadCallback("engine.dll", InitialiseDedicated);
+
+ if (!IsDedicated())
+ {
+ AddDllLoadCallback("client.dll", InitialiseClientSquirrel);
+ AddDllLoadCallback("client.dll", InitialiseSourceConsole);
+ }
+
+ AddDllLoadCallback("server.dll", InitialiseServerSquirrel);
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.cpp b/NorthstarDedicatedTest/hooks.cpp
new file mode 100644
index 00000000..a3be154d
--- /dev/null
+++ b/NorthstarDedicatedTest/hooks.cpp
@@ -0,0 +1,90 @@
+#include "pch.h"
+#include "hooks.h"
+#include "hookutils.h"
+#include "dedicated.h"
+#include "tier0.h"
+
+#include
+#include
+#include
+
+typedef HMODULE(*LoadLibraryExAType)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+
+typedef HMODULE(*LoadLibraryExWType)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+
+LoadLibraryExAType LoadLibraryExAOriginal;
+LoadLibraryExWType LoadLibraryExWOriginal;
+
+void InstallInitialHooks()
+{
+ //AllocConsole();
+
+ if (MH_Initialize() != MH_OK)
+ Error("MH_Initialize failed");
+
+ HookEnabler hook;
+ ENABLER_CREATEHOOK(hook, &LoadLibraryExA, &LoadLibraryExAHook, reinterpret_cast(&LoadLibraryExAOriginal));
+ ENABLER_CREATEHOOK(hook, &LoadLibraryExW, &LoadLibraryExWHook, reinterpret_cast(&LoadLibraryExWOriginal));
+}
+
+// dll load callback stuff
+// this allows for code to register callbacks to be run as soon as a dll is loaded, mainly to allow for patches to be made on dll load
+struct DllLoadCallback
+{
+ std::string dll;
+ DllLoadCallbackFuncType callback;
+ bool called;
+};
+
+std::vector dllLoadCallbacks;
+
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback)
+{
+ DllLoadCallback* callbackStruct = new DllLoadCallback;
+ callbackStruct->dll = dll;
+ callbackStruct->callback = callback;
+ callbackStruct->called = false;
+
+ dllLoadCallbacks.push_back(callbackStruct);
+}
+
+HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
+{
+ HMODULE moduleAddress = LoadLibraryExAOriginal(lpLibFileName, hFile, dwFlags);
+
+ if (moduleAddress)
+ {
+ for (auto& callbackStruct : dllLoadCallbacks)
+ {
+ if (!callbackStruct->called && strstr(lpLibFileName + (strlen(lpLibFileName) - strlen(callbackStruct->dll.c_str())), callbackStruct->dll.c_str()) != nullptr)
+ {
+ callbackStruct->callback(moduleAddress);
+ callbackStruct->called = true;
+ }
+ }
+ }
+
+ return moduleAddress;
+}
+
+HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
+{
+ HMODULE moduleAddress = LoadLibraryExWOriginal(lpLibFileName, hFile, dwFlags);
+
+ if (moduleAddress)
+ {
+ for (auto& callbackStruct : dllLoadCallbacks)
+ {
+ const wchar_t* callbackDll = std::wstring(callbackStruct->dll.begin(), callbackStruct->dll.end()).c_str();
+ if (!callbackStruct->called && wcsstr(lpLibFileName + (wcslen(lpLibFileName) - wcslen(callbackDll)), callbackDll) != nullptr)
+ {
+ callbackStruct->callback(moduleAddress);
+ callbackStruct->called = true;
+ }
+ }
+ }
+
+ return moduleAddress;
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.h b/NorthstarDedicatedTest/hooks.h
new file mode 100644
index 00000000..972b38a6
--- /dev/null
+++ b/NorthstarDedicatedTest/hooks.h
@@ -0,0 +1,7 @@
+#pragma once
+#include
+
+void InstallInitialHooks();
+
+typedef void(*DllLoadCallbackFuncType)(HMODULE moduleAddress);
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hookutils.cpp b/NorthstarDedicatedTest/hookutils.cpp
new file mode 100644
index 00000000..c5472b57
--- /dev/null
+++ b/NorthstarDedicatedTest/hookutils.cpp
@@ -0,0 +1,57 @@
+#include "pch.h"
+#include "hookutils.h"
+#include "tier0.h"
+
+#include
+
+TempReadWrite::TempReadWrite(void* ptr)
+{
+ m_ptr = ptr;
+ MEMORY_BASIC_INFORMATION mbi;
+ VirtualQuery(m_ptr, &mbi, sizeof(mbi));
+ VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
+ m_origProtection = mbi.Protect;
+}
+
+TempReadWrite::~TempReadWrite()
+{
+ MEMORY_BASIC_INFORMATION mbi;
+ VirtualQuery(m_ptr, &mbi, sizeof(mbi));
+ VirtualProtect(mbi.BaseAddress, mbi.RegionSize, m_origProtection, &mbi.Protect);
+}
+
+
+void HookEnabler::CreateHook(LPVOID ppTarget, LPVOID ppDetour, LPVOID* ppOriginal, const char* targetName)
+{
+ if (MH_CreateHook(ppTarget, ppDetour, ppOriginal) == MH_OK)
+ {
+ HookTarget *target = new HookTarget;
+ target->targetAddress = ppTarget;
+ target->targetName = (char*)targetName;
+
+ m_hookTargets.push_back(target);
+ }
+ else
+ {
+ if (targetName != nullptr)
+ Error("MH_CreateHook failed for function %s", targetName);
+ else
+ Error("MH_CreateHook failed for unknown function");
+ }
+}
+
+HookEnabler::~HookEnabler()
+{
+ for (auto& hook : m_hookTargets)
+ {
+ if (MH_EnableHook(hook->targetAddress) != MH_OK)
+ {
+ if (hook->targetName != nullptr)
+ Error("MH_EnableHook failed for function %s", hook->targetName);
+ else
+ Error("MH_EnableHook failed for unknown function");
+ }
+ else
+ std::cout << "enabling hook " << hook->targetName << std::endl;
+ }
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hookutils.h b/NorthstarDedicatedTest/hookutils.h
new file mode 100644
index 00000000..dd3b15b1
--- /dev/null
+++ b/NorthstarDedicatedTest/hookutils.h
@@ -0,0 +1,34 @@
+#pragma once
+#include
+
+// Sets an area of memory as writeable until the TempReadWrite object goes out of scope
+class TempReadWrite
+{
+private:
+ DWORD m_origProtection;
+ void* m_ptr;
+
+public:
+ TempReadWrite(void* ptr);
+ ~TempReadWrite();
+};
+
+// Enables all hooks created with the HookEnabler object when it goes out of scope and handles hook errors
+class HookEnabler
+{
+private:
+ struct HookTarget
+ {
+ char* targetName;
+ LPVOID targetAddress;
+ };
+
+ std::vector m_hookTargets;
+
+public:
+ void CreateHook(LPVOID ppTarget, LPVOID ppDetour, LPVOID* ppOriginal, const char* targetName = nullptr);
+ ~HookEnabler();
+};
+
+// macro to call HookEnabler::CreateHook with the hook's name
+#define ENABLER_CREATEHOOK(enabler, ppTarget, ppDetour, ppOriginal) enabler.CreateHook(ppTarget, ppDetour, ppOriginal, #ppDetour)
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/include/MinHook.h b/NorthstarDedicatedTest/include/MinHook.h
new file mode 100644
index 00000000..15c0a875
--- /dev/null
+++ b/NorthstarDedicatedTest/include/MinHook.h
@@ -0,0 +1,186 @@
+/*
+ * MinHook - The Minimalistic API Hooking Library for x64/x86
+ * Copyright (C) 2009-2017 Tsuda Kageyu.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
+ #error MinHook supports only x86 and x64 systems.
+#endif
+
+#include
+
+// MinHook Error Codes.
+typedef enum MH_STATUS
+{
+ // Unknown error. Should not be returned.
+ MH_UNKNOWN = -1,
+
+ // Successful.
+ MH_OK = 0,
+
+ // MinHook is already initialized.
+ MH_ERROR_ALREADY_INITIALIZED,
+
+ // MinHook is not initialized yet, or already uninitialized.
+ MH_ERROR_NOT_INITIALIZED,
+
+ // The hook for the specified target function is already created.
+ MH_ERROR_ALREADY_CREATED,
+
+ // The hook for the specified target function is not created yet.
+ MH_ERROR_NOT_CREATED,
+
+ // The hook for the specified target function is already enabled.
+ MH_ERROR_ENABLED,
+
+ // The hook for the specified target function is not enabled yet, or already
+ // disabled.
+ MH_ERROR_DISABLED,
+
+ // The specified pointer is invalid. It points the address of non-allocated
+ // and/or non-executable region.
+ MH_ERROR_NOT_EXECUTABLE,
+
+ // The specified target function cannot be hooked.
+ MH_ERROR_UNSUPPORTED_FUNCTION,
+
+ // Failed to allocate memory.
+ MH_ERROR_MEMORY_ALLOC,
+
+ // Failed to change the memory protection.
+ MH_ERROR_MEMORY_PROTECT,
+
+ // The specified module is not loaded.
+ MH_ERROR_MODULE_NOT_FOUND,
+
+ // The specified function is not found.
+ MH_ERROR_FUNCTION_NOT_FOUND
+}
+MH_STATUS;
+
+// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
+// MH_QueueEnableHook or MH_QueueDisableHook.
+#define MH_ALL_HOOKS NULL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Initialize the MinHook library. You must call this function EXACTLY ONCE
+ // at the beginning of your program.
+ MH_STATUS WINAPI MH_Initialize(VOID);
+
+ // Uninitialize the MinHook library. You must call this function EXACTLY
+ // ONCE at the end of your program.
+ MH_STATUS WINAPI MH_Uninitialize(VOID);
+
+ // Creates a Hook for the specified target function, in disabled state.
+ // Parameters:
+ // pTarget [in] A pointer to the target function, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a Hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszTarget [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApi(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a Hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszTarget [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ // ppTarget [out] A pointer to the target function, which will be used
+ // with other functions.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApiEx(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
+
+ // Removes an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
+
+ // Enables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // enabled in one go.
+ MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
+
+ // Disables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // disabled in one go.
+ MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
+
+ // Queues to enable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be enabled.
+ MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
+
+ // Queues to disable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be disabled.
+ MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
+
+ // Applies all queued changes in one go.
+ MH_STATUS WINAPI MH_ApplyQueued(VOID);
+
+ // Translates the MH_STATUS to its name as a string.
+ const char * WINAPI MH_StatusToString(MH_STATUS status);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/NorthstarDedicatedTest/include/MinHook.x64.dll b/NorthstarDedicatedTest/include/MinHook.x64.dll
new file mode 100644
index 00000000..b4f51c2e
Binary files /dev/null and b/NorthstarDedicatedTest/include/MinHook.x64.dll differ
diff --git a/NorthstarDedicatedTest/include/MinHook.x64.lib b/NorthstarDedicatedTest/include/MinHook.x64.lib
new file mode 100644
index 00000000..909fe682
Binary files /dev/null and b/NorthstarDedicatedTest/include/MinHook.x64.lib differ
diff --git a/NorthstarDedicatedTest/include/MinHook.x86.dll b/NorthstarDedicatedTest/include/MinHook.x86.dll
new file mode 100644
index 00000000..d6167c83
Binary files /dev/null and b/NorthstarDedicatedTest/include/MinHook.x86.dll differ
diff --git a/NorthstarDedicatedTest/include/MinHook.x86.lib b/NorthstarDedicatedTest/include/MinHook.x86.lib
new file mode 100644
index 00000000..02f351c2
Binary files /dev/null and b/NorthstarDedicatedTest/include/MinHook.x86.lib differ
diff --git a/NorthstarDedicatedTest/include/tier0.def b/NorthstarDedicatedTest/include/tier0.def
new file mode 100644
index 00000000..6834b009
--- /dev/null
+++ b/NorthstarDedicatedTest/include/tier0.def
@@ -0,0 +1,10 @@
+LIBRARY tier0.dll
+EXPORTS
+CreateGlobalMemAlloc
+g_pMemAllocSingleton
+ThreadInMainThread
+
+Error
+
+LoggingSystem_RegisterLoggingListener
+LoggingSystem_Log
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/include/tier0.exp b/NorthstarDedicatedTest/include/tier0.exp
new file mode 100644
index 00000000..706b6de8
Binary files /dev/null and b/NorthstarDedicatedTest/include/tier0.exp differ
diff --git a/NorthstarDedicatedTest/include/tier0.lib b/NorthstarDedicatedTest/include/tier0.lib
new file mode 100644
index 00000000..6b0ffa5c
Binary files /dev/null and b/NorthstarDedicatedTest/include/tier0.lib differ
diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp
new file mode 100644
index 00000000..021613d9
--- /dev/null
+++ b/NorthstarDedicatedTest/logging.cpp
@@ -0,0 +1,52 @@
+#include "pch.h"
+#include "logging.h"
+#include "context.h"
+#include "dedicated.h"
+#include
+#include
+#include
+
+std::vector loggingSinks;
+
+void Log(Context context, char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ Log(context, fmt, args);
+ va_end(args);
+}
+
+void Log(Context context, char* fmt, va_list args)
+{
+ char buf[1024];
+ vsnprintf_s(buf, _TRUNCATE, fmt, args);
+
+ for (LoggingSink& sink : loggingSinks)
+ sink(context, fmt);
+}
+
+void AddLoggingSink(LoggingSink sink)
+{
+ loggingSinks.push_back(sink);
+}
+
+// default logging sink
+void DefaultLoggingSink(Context context, char* message)
+{
+ time_t now = time(0);
+ tm* localTime = localtime(&now);
+ char timeBuf[10];
+ strftime(timeBuf, sizeof(timeBuf), "%X", localTime);
+
+ std::cout << "[" << timeBuf << "] ";
+ if (context != NONE)
+ std::cout << "[" << GetContextName(context) << "] ";
+
+ std::cout << message;
+
+ if (!IsDedicated())
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/logging.h b/NorthstarDedicatedTest/logging.h
new file mode 100644
index 00000000..aa19b8f1
--- /dev/null
+++ b/NorthstarDedicatedTest/logging.h
@@ -0,0 +1,11 @@
+#pragma once
+#include "context.h"
+
+typedef void(*LoggingSink)(Context context, char* fmt);
+
+void Log(Context context, char* fmt, ...);
+void Log(Context context, char* fmt, va_list args);
+void AddLoggingSink(LoggingSink sink);
+
+// default logging sink
+void DefaultLoggingSink(Context context, char* message);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/main.h b/NorthstarDedicatedTest/main.h
new file mode 100644
index 00000000..ef5d86dc
--- /dev/null
+++ b/NorthstarDedicatedTest/main.h
@@ -0,0 +1,3 @@
+#pragma once
+
+extern "C" __declspec(dllexport) void InitialiseNorthstar();
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/pch.cpp b/NorthstarDedicatedTest/pch.cpp
new file mode 100644
index 00000000..64b7eef6
--- /dev/null
+++ b/NorthstarDedicatedTest/pch.cpp
@@ -0,0 +1,5 @@
+// pch.cpp: source file corresponding to the pre-compiled header
+
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
diff --git a/NorthstarDedicatedTest/pch.h b/NorthstarDedicatedTest/pch.h
new file mode 100644
index 00000000..1ad845c9
--- /dev/null
+++ b/NorthstarDedicatedTest/pch.h
@@ -0,0 +1,11 @@
+#ifndef PCH_H
+#define PCH_H
+
+#define _CRT_SECURE_NO_WARNINGS
+
+// add headers that you want to pre-compile here
+#include
+#include "logging.h"
+#include "include/MinHook.h"
+
+#endif
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/sigscanning.cpp b/NorthstarDedicatedTest/sigscanning.cpp
new file mode 100644
index 00000000..c75c80f0
--- /dev/null
+++ b/NorthstarDedicatedTest/sigscanning.cpp
@@ -0,0 +1,39 @@
+#include "pch.h"
+#include "sigscanning.h"
+#include