Ejemplo n.º 1
0
        public void Unpatch()
        {
            try
            {
                if (prefix != null)
                {
                    patchProcessor.Unpatch(prefix);
                }
                if (postfix != null)
                {
                    patchProcessor.Unpatch(postfix);
                }
                if (finalizer != null)
                {
                    patchProcessor.Unpatch(finalizer);
                }
                if (transpiler != null)
                {
                    patchProcessor.Unpatch(transpiler);
                }

                Enabled = false;
            }
            catch (Exception ex)
            {
                ExplorerCore.LogWarning($"Exception unpatching method: {ex}");
            }
        }
Ejemplo n.º 2
0
 public void UnPatch()
 {
     foreach (var patch in patches)
     {
         processor.Unpatch(patch);
     }
 }
Ejemplo n.º 3
0
        public void AttemptRemoveHarmonyModPatch(Harmony h)
        {
            /* Needs to run after Harmony is OnEnabled() */

            testName = "TEST/" +
                       "API/ACL3/" +
                       typeof(HarmonyHelper).Assembly.GetName().Name + " " +
                       typeof(HarmonyHelper).Assembly.GetName().Version;

            PatchProcessor processor       = null;
            MethodInfo     prohibitedPatch = null;

            try
            {
                var        targetName = "SetEntry";
                MethodInfo target     = typeof(PackageEntry).GetMethod(targetName,
                                                                       BindingFlags.Instance |
                                                                       BindingFlags.Static |
                                                                       BindingFlags.Public |
                                                                       BindingFlags.NonPublic);
                if (target == null)
                {
                    throw new TestFailed($"Target fn ({targetName}) was not found.");
                }
                processor = h.CreateProcessor(target);
                if (processor == null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - Processor=null. BAD");
                    throw new TestFailed($"Failed to create processor.");
                }

                var patches = Harmony.GetPatchInfo(target);

                if (patches == null)
                {
                    throw new TestFailed($"Failed to get '{target}' patches.");
                }

                if (patches.Prefixes != null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Prefixes.Count} prefix patches to {targetName}");
                }
                if (patches.Postfixes != null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Postfixes.Count} postfix patches to {targetName}");
                }
                if (patches.Transpilers != null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Transpilers.Count} transpiler patches to {targetName}");
                }
                if (patches.Finalizers != null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Finalizers.Count} finalizer patches to {targetName}");
                }

                patches.Postfixes.Do((p) => UnityEngine.Debug.Log($"[{testName}] INFO - found patch to {targetName} = {p.PatchMethod.Name} by {p.owner}"));

                bool found = false;
                patches.Postfixes.DoIf((p) => p.owner.Contains("org.ohmi.harmony"),
                                       (p) => {
                    found = true;
                    processor.Unpatch(p.PatchMethod);
                });

                if (!found)
                {
                    throw new TestFailed($"Mod's patch to {targetName} not found.");
                }

                throw new TestFailed("Removing a Mod's patch did not throw HarmonyModACLException");
            }
            catch (TestFailed ex)
            {
                UnityEngine.Debug.Log($"[{testName}] ERROR : {ex.Message}. BAD");
                throw ex;
            }
            catch (Exception ex)
            {
                if (ex.GetType().Name != "HarmonyModACLException")
                {
                    throw new TestFailed($"Unpatching the mod failed but not because of ACL: {ex.Message}", ex);
                }
                UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to unpatch the mod was blocked ({ex.Message}). OK.");
            }
        }
Ejemplo n.º 4
0
        public void AttemptProhibitedPatch(Harmony h)
        {
            testName = "TEST/" +
                       "API/ACL2/" +
                       typeof(HarmonyHelper).Assembly.GetName().Name + " " +
                       typeof(HarmonyHelper).Assembly.GetName().Version;

            PatchProcessor processor       = null;
            MethodInfo     prohibitedPatch = null;

            try
            {
                var        targetName = "CompareTo";
                MethodInfo target     = typeof(Patch).GetMethod(targetName,
                                                                BindingFlags.Instance |
                                                                BindingFlags.Static |
                                                                BindingFlags.Public |
                                                                BindingFlags.NonPublic);
                if (target == null)
                {
                    throw new TestFailed($"Target fn ({targetName}) was not found.");
                }
                processor = h.CreateProcessor(target);
                if (processor == null)
                {
                    UnityEngine.Debug.Log($"[{testName}] INFO - Processor=null. BAD");
                    throw new TestFailed($"Failed to create processor.");
                }

                prohibitedPatch = typeof(ACLPatchDefinitions).GetMethod("ProhibitedPatch",
                                                                        BindingFlags.Instance |
                                                                        BindingFlags.Static |
                                                                        BindingFlags.Public |
                                                                        BindingFlags.NonPublic);
                if (prohibitedPatch == null)
                {
                    throw new TestFailed("Patch fn (ProhibitedPatch) was not found.");
                }

                processor.AddPostfix(prohibitedPatch);
                processor.Patch();
                throw new TestFailed("Installing a prohibited patch did not throw HarmonyModACLException");
            }
            catch (TestFailed ex)
            {
                UnityEngine.Debug.Log($"[{testName}] ERROR : {ex.Message}. BAD");
                throw ex;
            }
            catch (Exception ex)
            {
                if (ex.GetType().Name != "HarmonyModACLException")
                {
                    throw new TestFailed($"Installing a prohibited patch failed but not because of ACL: {ex.Message}");
                }
                UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to install a prohibited patch was blocked ({ex.Message}). OK.");
            }
            finally
            {
                if (processor != null && prohibitedPatch != null)
                {
                    try
                    {
                        processor.Unpatch(prohibitedPatch);
                    }
                    catch (Exception ex)
                    {
                        if (ex.GetType().Name != "HarmonyModACLException")
                        {
                            throw new TestFailed($"Uninstalling a prohibited patch failed but not because of ACL: {ex.Message}");
                        }
                        UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to remove a prohibited patch was blocked ({ex.Message}). OK.");
                    }
                }
                else
                {
                    throw new TestFailed($"Prohibited patch test is broken. processor={processor != null} patch={prohibitedPatch != null}");
                }
            }
        }
Ejemplo n.º 5
0
        public void MethodRestorationTest()
        {
            var originalMethod = typeof(RestoreableClass).GetMethod("Method2");

            Assert.IsNotNull(originalMethod);

            MethodInfo prefixMethod;
            MethodInfo postfixMethod;
            MethodInfo transpilerMethod;

            PatchTools.GetPatches(typeof(Class2Patch), out prefixMethod, out postfixMethod, out transpilerMethod);

            var instance = HarmonyInstance.Create("test");
            var patcher  = new PatchProcessor(instance, new List <MethodBase>()
            {
                originalMethod
            }, new HarmonyMethod(prefixMethod), new HarmonyMethod(postfixMethod), null);

            // Check if the class is clean before using it for patching
            Assert.AreEqual(null, instance.IsPatched(originalMethod), "Class already patched!");

            Exception ex;
            var       start    = Memory.GetMethodStart(originalMethod, out ex);
            var       oldBytes = new byte[12];

            if (IntPtr.Size == sizeof(long))
            {
                Marshal.Copy((IntPtr)start, oldBytes, 0, 12);
            }
            else
            {
                Marshal.Copy((IntPtr)start, oldBytes, 0, 6);
            }

            patcher.Patch();

            patcher.Unpatch(originalMethod);

            var newBytes = new byte[12];

            if (IntPtr.Size == sizeof(long))
            {
                Marshal.Copy((IntPtr)start, newBytes, 0, 12);
            }
            else
            {
                Marshal.Copy((IntPtr)start, newBytes, 0, 6);
            }
            for (int i = 0; i < oldBytes.Length; i++)
            {
                Assert.AreEqual(oldBytes[i], newBytes[i], string.Format("Byte {0} differs after restoration", i));
            }

            Class2Patch._reset();
            new RestoreableClass().Method2();

            Assert.IsFalse(Class2Patch.prefixed);
            Assert.IsTrue(Class2Patch.originalExecuted);
            Assert.IsFalse(Class2Patch.postfixed);

            Assert.AreEqual(0, instance.IsPatched(originalMethod).Postfixes.Count);
            Assert.AreEqual(0, instance.IsPatched(originalMethod).Prefixes.Count);
            Assert.AreEqual(0, instance.IsPatched(originalMethod).Transpilers.Count);
        }