From 582e52981b3ab206becde6b3dad18a676ded4634 Mon Sep 17 00:00:00 2001 From: Kaede Date: Thu, 30 Nov 2023 03:34:51 +0200 Subject: [PATCH] Pre-empt AssemblyLoad callbacks --- Marsey/FileHandler.cs | 6 +++ Marsey/GameAssemblyManager.cs | 1 + Marsey/Handbrake/Manual.cs | 39 +++++++++++++++++ Marsey/Handbreak/Manual.cs | 28 ------------ Marsey/MarseyPatcher.cs | 7 ++- Marsey/Preloader/PreloadManager.cs | 4 +- Marsey/Stealthsey/Hidesey.cs | 10 ++--- Marsey/Stealthsey/HideseyPatches.cs | 5 +++ Marsey/Stealthsey/Redial.cs | 67 +++++++++++++++++++++++++++++ SS14.Loader/Program.cs | 2 +- 10 files changed, 129 insertions(+), 40 deletions(-) create mode 100644 Marsey/Handbrake/Manual.cs delete mode 100644 Marsey/Handbreak/Manual.cs create mode 100644 Marsey/Stealthsey/Redial.cs diff --git a/Marsey/FileHandler.cs b/Marsey/FileHandler.cs index 35989e4..333226e 100644 --- a/Marsey/FileHandler.cs +++ b/Marsey/FileHandler.cs @@ -8,6 +8,7 @@ using Marsey.Preloader; using Marsey.Subversion; using Marsey.Serializer; +using Marsey.Stealthsey; namespace Marsey; @@ -79,6 +80,7 @@ public static void LoadAssemblies(string[]? path = null, bool marserializer = fa if (files == null) return; + foreach (string file in files) { LoadExactAssembly(file); @@ -91,6 +93,8 @@ public static void LoadAssemblies(string[]? path = null, bool marserializer = fa /// path to dll file public static void LoadExactAssembly(string file) { + Redial.Disable(); // Disable any AssemblyLoad callbacks found + try { Assembly assembly = Assembly.LoadFrom(file); @@ -105,6 +109,8 @@ public static void LoadExactAssembly(string file) { MarseyLogger.Log(MarseyLogger.LogType.FATL, ex.Message); } + + Redial.Enable(); // Enable callbacks in case the game needs them } /// diff --git a/Marsey/GameAssemblyManager.cs b/Marsey/GameAssemblyManager.cs index 61c910c..46bf90a 100644 --- a/Marsey/GameAssemblyManager.cs +++ b/Marsey/GameAssemblyManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using HarmonyLib; +using Marsey.Stealthsey; namespace Marsey; diff --git a/Marsey/Handbrake/Manual.cs b/Marsey/Handbrake/Manual.cs new file mode 100644 index 0000000..f764ea5 --- /dev/null +++ b/Marsey/Handbrake/Manual.cs @@ -0,0 +1,39 @@ +using System.Reflection; +using HarmonyLib; + +namespace Marsey.Handbrake; + +/// +/// In some cases we are required to patch functions publicly +/// +public static class Manual +{ + public static void Prefix(MethodInfo method, MethodInfo prefix) + { + Harmony? harm = HarmonyManager.GetHarmony(); + harm?.Patch(method, prefix: prefix); + } + + public static void Postfix(MethodInfo method, MethodInfo postfix) + { + Harmony? harm = HarmonyManager.GetHarmony(); + harm?.Patch(method, postfix: postfix); + } + + public static void Transpiler(MethodInfo method, MethodInfo transpiler) + { + Harmony? harm = HarmonyManager.GetHarmony(); + harm?.Patch(method, transpiler: transpiler); + } + + /// + /// Removes **all** patches of type from a method + /// + /// target method that has patches applies + /// type of patches + public static void Unpatch(MethodInfo method, HarmonyPatchType patchType) + { + Harmony? harm = HarmonyManager.GetHarmony(); + harm?.Unpatch(method, patchType); + } +} \ No newline at end of file diff --git a/Marsey/Handbreak/Manual.cs b/Marsey/Handbreak/Manual.cs deleted file mode 100644 index c348dd0..0000000 --- a/Marsey/Handbreak/Manual.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Reflection; -using HarmonyLib; - -namespace Marsey.Handbreak; - -/// -/// In some cases we are required to patch functions publicly -/// -public static class Manual -{ - public static void ManualPrefix(MethodInfo method, MethodInfo prefix) - { - Harmony? harm = HarmonyManager.GetHarmony(); - harm?.Patch(method, prefix: prefix); - } - - public static void ManualPostfix(MethodInfo method, MethodInfo postfix) - { - Harmony? harm = HarmonyManager.GetHarmony(); - harm?.Patch(method, postfix: postfix); - } - - public static void ManualTranspiler(MethodInfo method, MethodInfo transpiler) - { - Harmony? harm = HarmonyManager.GetHarmony(); - harm?.Patch(method, transpiler: transpiler); - } -} \ No newline at end of file diff --git a/Marsey/MarseyPatcher.cs b/Marsey/MarseyPatcher.cs index d4a7717..114227d 100644 --- a/Marsey/MarseyPatcher.cs +++ b/Marsey/MarseyPatcher.cs @@ -41,21 +41,20 @@ public void Boot() { // Preload marseypatches, if available PreloadManager.Preload(); - MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Passed preload"); - + // Initialize subverter if enabled and present if (MarseyVars.Subverter && Subverse.InitSubverter()) { // Side-load custom code Subverse.PatchSubverter(); } - MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Passed subverter"); + // Manage game assemblies GameAssemblyManager.GetGameAssemblies(out Assembly? clientAss, out Assembly? robustSharedAss, out Assembly? clientSharedAss); AssemblyFieldHandler.SetAssemblies(clientAss, robustSharedAss, clientSharedAss); // Prepare marseypatches - FileHandler.LoadAssemblies(marserializer: true, filename: "patches.marsey"); + FileHandler.LoadAssemblies(marserializer: true, filename: PatchListManager.MarserializerFile); List? patches = PatchListManager.GetPatchList(); if (patches == null) return; diff --git a/Marsey/Preloader/PreloadManager.cs b/Marsey/Preloader/PreloadManager.cs index 099ca91..c538e55 100644 --- a/Marsey/Preloader/PreloadManager.cs +++ b/Marsey/Preloader/PreloadManager.cs @@ -13,10 +13,10 @@ public static class PreloadManager public static void Preload(string[]? path = null) { path ??= new[] { MarseyVars.MarseyPatchFolder }; - + List? preloads = Marserializer.Deserialize(path, filename: MarserializerFile); - if (preloads == null) return; + if (preloads == null || preloads.Count == 0) return; MarseyLogger.Log(MarseyLogger.LogType.INFO, $"Preloading {preloads.Count} patches"); diff --git a/Marsey/Stealthsey/Hidesey.cs b/Marsey/Stealthsey/Hidesey.cs index 36072db..e0d6860 100644 --- a/Marsey/Stealthsey/Hidesey.cs +++ b/Marsey/Stealthsey/Hidesey.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Reflection; using System.Runtime.Loader; -using Marsey.Handbreak; +using Marsey.Handbrake; using Marsey.Subversion; namespace Marsey.Stealthsey; @@ -28,11 +28,11 @@ public static void Initialize() .GetMethod("GetAssemblies", BindingFlags.Public | BindingFlags.Instance); MethodInfo? postfix = typeof(HideseyPatches) - .GetMethod("LieLoader", BindingFlags.Public | BindingFlags.Static); + .GetMethod("LieLoader", BindingFlags.Public | BindingFlags.Static)!; - if (target == null || postfix == null) return; - - Manual.ManualPostfix(target, postfix); + if (target == null) return; + + Manual.Postfix(target, postfix); MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Hidesey started."); } diff --git a/Marsey/Stealthsey/HideseyPatches.cs b/Marsey/Stealthsey/HideseyPatches.cs index e3b682c..b7786e7 100644 --- a/Marsey/Stealthsey/HideseyPatches.cs +++ b/Marsey/Stealthsey/HideseyPatches.cs @@ -12,4 +12,9 @@ public static void LieLoader(ref Assembly[] __result) { __result = Hidesey.LyingDomain(__result); } + + /// + /// This patch skips function execution + /// + public static bool Skip() => false; } \ No newline at end of file diff --git a/Marsey/Stealthsey/Redial.cs b/Marsey/Stealthsey/Redial.cs new file mode 100644 index 0000000..c6c8897 --- /dev/null +++ b/Marsey/Stealthsey/Redial.cs @@ -0,0 +1,67 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.Loader; +using HarmonyLib; +using Marsey.Handbrake; +using MonoMod.Utils; + +namespace Marsey.Stealthsey; + +/// +/// Manages AssemblyLoad event delegates +/// +public static class Redial +{ + private static Delegate[]? _phonebook; + + /// + /// Disables AssemblyLoad Callbacks in CurrentDomain + /// + public static void Disable() + { + MethodInfo? prefix = + typeof(HideseyPatches) + .GetMethod("Skip", BindingFlags.Public | BindingFlags.Static)!; + + _phonebook = FillPhonebook(); + + if (_phonebook == null) return; + + foreach (Delegate dial in _phonebook) + { + Manual.Prefix(dial.Method, prefix); + } + } + + /// + /// Unpatches AssemblyLoad callbacks + /// + public static void Enable() + { + if (_phonebook == null) return; + + foreach (Delegate dial in _phonebook) + { + Manual.Unpatch(dial.Method, HarmonyPatchType.Prefix); + } + } + + /// + /// Returns a list of AssemblyLoad delegates + /// + private static Delegate[]? FillPhonebook() + { + FieldInfo? fInfo = typeof(AssemblyLoadContext).GetField("AssemblyLoad", BindingFlags.Static | BindingFlags.NonPublic); + + MulticastDelegate? eventDelegate = (MulticastDelegate?)fInfo?.GetValue(AppDomain.CurrentDomain); + + if (eventDelegate == null) return null; + + Delegate[] delegates = eventDelegate.GetInvocationList(); + + if (delegates != _phonebook) MarseyLogger.Log(MarseyLogger.LogType.DEBG, $"Redialing {delegates.Length} delegates."); + + return delegates; + } +} \ No newline at end of file diff --git a/SS14.Loader/Program.cs b/SS14.Loader/Program.cs index 6e06fe9..d3a0228 100644 --- a/SS14.Loader/Program.cs +++ b/SS14.Loader/Program.cs @@ -195,4 +195,4 @@ internal static int Main(string[] args) return 0; } -} +} \ No newline at end of file