public override DynamicMethodDefinition CopyOriginal()
        {
            DynamicMethodDefinition method = Original.ToNewDynamicMethodDefinition();

            method.Definition.Name += "_wrapper";
            ILContext      ilcontext          = new ILContext(method.Definition);
            ILCursor       ilcursor           = new ILCursor(ilcontext);
            FieldReference tempfieldreference = null;

            if (ilcursor.TryGotoNext(x => x.MatchLdsfld(out tempfieldreference), x => x.MatchCall(UnhollowerSupport.IL2CPPType, "il2cpp_object_get_virtual_method")))
            {
                // Virtual method: Replace the sequence
                // - ldarg.0
                // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase)
                // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc
                // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int)

                ilcursor.Index -= 2;
                ilcursor.RemoveRange(4);
            }
            else if (ilcursor.TryGotoNext(x => x.MatchLdsfld(UnhollowerSupport.MethodBaseToIl2CppFieldInfo(Original))))
            {
                ilcursor.Remove();
            }
            else
            {
                MelonLogger.Error("Harmony Patcher could not rewrite Il2Cpp Unhollowed Method. Expect a stack overflow.");
                return(method);
            }
            ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I8, copiedMethodInfoPointer.ToInt64());
            ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Conv_I);
            return(method);
        }
Exemplo n.º 2
0
		private static void ConvertReturnValue(ILGenerator il, Type returnType) {
			if (returnType == typeof(string)) {
				Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.ManagedStringToIl2CppMethod);
			} else if (!returnType.IsValueType && UnhollowerSupport.IsGeneratedAssemblyType(returnType)) {
				Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppObjectBaseToPtrMethod);
			}
		}
Exemplo n.º 3
0
        public static object Il2CppObjectPtrToIl2CppObjectByType(IntPtr ptr, Type type)
        {
            if (ptr == IntPtr.Zero)
            {
                throw new ArgumentException("The ptr cannot be IntPtr.Zero.");
            }
            if (!UnhollowerSupport.IsGeneratedAssemblyType(type))
            {
                throw new ArgumentException("The type must be a Generated Assembly Type.");
            }

            var ctor = type?.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new[]
            {
                typeof(IntPtr)
            }, new ParameterModifier[0]) ?? throw new MissingMethodException($"{type?.FullName}.ctor(IntPtr) not found");

            try
            {
                var obj = ctor.Invoke(new object[] { ptr });
                return(obj);
            }
            catch (Exception e)
            {
                Logger.Warn($"Exception while constructing {type.FullName}: {e}");
                return(null);
            }
        }
 internal static void TryResolve(object sender, PatchManager.PatcherResolverEventArgs args)
 {
     if (UnhollowerSupport.IsGeneratedAssemblyType(args.Original.DeclaringType))
     {
         args.MethodPatcher = new HarmonyIl2CppMethodPatcher(args.Original);
     }
 }
Exemplo n.º 5
0
        private static unsafe TDelegate Patch <TDelegate>(MethodBase originalMethod, IntPtr patchDetour)
        {
            IntPtr original = *(IntPtr *)UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(originalMethod);

            MelonUtils.NativeHookAttach((IntPtr)(&original), patchDetour);
            return(Marshal.GetDelegateForFunctionPointer <TDelegate>(original));
        }
        public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

            var replacement = MethodPatcher.CreatePatchedMethod(original, instanceID, sortedPrefixes, sortedPostfixes, sortedTranspilers);

            if (replacement == null)
            {
                throw new MissingMethodException("Cannot create dynamic replacement for " + original.FullDescription());
            }

            var errorString = Memory.DetourMethod(original, replacement);

            if (errorString != null)
            {
                throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
            }

            if (UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType))
            {
                var il2CppShim = CreateIl2CppShim(replacement, original.DeclaringType);
                Imports.Hook(UnhollowerSupport.MethodBaseToIntPtr(original), il2CppShim.MethodHandle.GetFunctionPointer());
                PatchTools.RememberObject(original, new PotatoTuple {
                    First = replacement, Second = il2CppShim
                });
            }
            else
            {
                PatchTools.RememberObject(original, replacement);                 // no gc for new value + release old value to gc
            }
            return(replacement);
        }
Exemplo n.º 7
0
        private static void Bridge(IntPtr @this, IntPtr handle)
        {
            var record = BRIDGE_INDEX[handle];

            Logger.Debug(() => $"{record}");

            try
            {
                var conf = UnhollowerSupport.Il2CppObjectPtrToIl2CppObject <ConfBase>(@this)
                           ?? throw new Exception("Unable to convert ptr to object");

                if (Env.IsGameUpdated)
                {
                    BridgeHelper.DumpConf(conf, record);
                }
                else
                {
                    BridgeHelper.UpdateConf(conf, record);
                }
            }
            catch (Exception e)
            {
                var info = Trampoline.GetInfo(handle);
                MelonLogger.Warning($"Exception occurs in bridge\n{e}\n" +
                                    $"this: 0x{@this.ToInt64():X}\n" +
                                    $"trampoline info: {info}\n" +
                                    $"record: {record}");
            }
        }
Exemplo n.º 8
0
 public T LoadAsset <T>(string name) where T : Object
 {
     if (!UnhollowerSupport.IsGeneratedAssemblyType(typeof(T)))
     {
         throw new System.NullReferenceException("The type must be a Generated Assembly Type.");
     }
     System.IntPtr intptr = LoadAsset(name, Il2CppType.Of <T>().Pointer);
     return((intptr != System.IntPtr.Zero) ? UnhollowerSupport.Il2CppObjectPtrToIl2CppObject <T>(intptr) : null);
 }
Exemplo n.º 9
0
 public Il2CppReferenceArray <T> LoadAllAssets <T>() where T : Object
 {
     if (!UnhollowerSupport.IsGeneratedAssemblyType(typeof(T)))
     {
         throw new System.NullReferenceException("The type must be a Generated Assembly Type.");
     }
     System.IntPtr intptr = LoadAllAssets(Il2CppType.Of <T>().Pointer);
     return((intptr != System.IntPtr.Zero) ? new Il2CppReferenceArray <T>(intptr) : null);
 }
Exemplo n.º 10
0
 public AssetBundleCreateRequest LoadAssetWithSubAssetsAsync <T>(string name) where T : Object
 {
     if (!UnhollowerSupport.IsGeneratedAssemblyType(typeof(T)))
     {
         throw new System.NullReferenceException("The type must be a Generated Assembly Type.");
     }
     System.IntPtr intptr = LoadAssetWithSubAssetsAsync(name, Il2CppType.Of <T>().Pointer);
     return((intptr != System.IntPtr.Zero) ? new AssetBundleCreateRequest(intptr) : null);
 }
        public void Patcher3()
        {
            var realPtr = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(
                typeof(ObjectPublicAbstractSealedDi2StTyHaDi2St1TyUnique)
                .GetMethod("Method_Public_Static_Void_Component_0"));
            var myrealFunct = typeof(MonoBehaviour1).GetMethod("FakeMethod").MethodHandle.GetFunctionPointer();

            //MelonLogger.Log(realPtr);
            //MelonLogger.Log(myrealFunct);
            Imports.Hook(realPtr, myrealFunct);
        }
        public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var  sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var  sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var  sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);
            bool isIl2Cpp          = UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType);

            if (isIl2Cpp)
            {
                if (sortedTranspilers.Count > 0)
                {
                    throw new NotSupportedException("IL2CPP patches cannot use transpilers (got " + sortedTranspilers.Count + ")");
                }

                if (patchInfo.copiedMethodInfoPointer == IntPtr.Zero)
                {
                    IntPtr origMethodPtr = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(original);
                    patchInfo.copiedMethodInfoPointer = CopyMethodInfoStruct(origMethodPtr);
                    HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                }

                sortedTranspilers.Add(AccessTools.DeclaredMethod(typeof(PatchFunctions), "UnhollowerTranspiler"));
            }

            var replacement = MethodPatcher.CreatePatchedMethod(original, instanceID, sortedPrefixes, sortedPostfixes, sortedTranspilers);

            if (replacement == null)
            {
                throw new MissingMethodException("Cannot create dynamic replacement for " + original.FullDescription());
            }

            if (isIl2Cpp)
            {
                DynamicMethod il2CppShim = CreateIl2CppShim(replacement, original);
                InstallIl2CppPatch(patchInfo, il2CppShim);
                PatchTools.RememberObject(original, new PotatoTuple {
                    First = replacement, Second = il2CppShim
                });
            }
            else
            {
                var errorString = Memory.DetourMethod(original, replacement);
                if (errorString != null)
                {
                    throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
                }

                PatchTools.RememberObject(original, replacement);                 // no gc for new value + release old value to gc
            }

            return(replacement);
        }
Exemplo n.º 13
0
		private static void ConvertArgument(ILGenerator il, Type paramType, ref LocalBuilder byRefLocal) {
			if (paramType.IsValueType)
				return;

			if (paramType.IsByRef) {
				Type elementType = paramType.GetElementType();

				if (paramType.GetElementType() == typeof(string)) {
					// byRefLocal = Il2CppStringToManaged(*ptr);
					// return ref byRefLocal;

					byRefLocal = il.DeclareLocal(elementType);
					Emitter.Emit(il, OpCodes.Ldind_I);
					Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppStringToManagedMethod);
					Emitter.Emit(il, OpCodes.Stloc, byRefLocal);
					Emitter.Emit(il, OpCodes.Ldloca, byRefLocal);
				} else if (UnhollowerSupport.IsGeneratedAssemblyType(elementType)) {
					// byRefLocal = *ptr == 0 ? null : new SomeType(*ptr);
					// return ref byRefLocal;
					Label ptrNonZero = il.DefineLabel();
					Label done = il.DefineLabel();

					byRefLocal = il.DeclareLocal(elementType);
					Emitter.Emit(il, OpCodes.Ldind_I);
					Emitter.Emit(il, OpCodes.Dup);
					Emitter.Emit(il, OpCodes.Brtrue_S, ptrNonZero);
					Emitter.Emit(il, OpCodes.Pop);
					Emitter.Emit(il, OpCodes.Br_S, done);
					Emitter.MarkLabel(il, ptrNonZero);
					Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(elementType));
					Emitter.Emit(il, OpCodes.Stloc, byRefLocal);
					Emitter.MarkLabel(il, done);
					Emitter.Emit(il, OpCodes.Ldloca, byRefLocal);
				}
			} else if (paramType == typeof(string)) {
				// return Il2CppStringToManaged(ptr);
				Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppStringToManagedMethod);
			} else if (UnhollowerSupport.IsGeneratedAssemblyType(paramType)) {
				// return ptr == 0 ? null : new SomeType(ptr);
				Label ptrNonZero = il.DefineLabel();
				Label done = il.DefineLabel();

				Emitter.Emit(il, OpCodes.Dup);
				Emitter.Emit(il, OpCodes.Brtrue_S, ptrNonZero);
				Emitter.Emit(il, OpCodes.Pop);
				Emitter.Emit(il, OpCodes.Ldnull);
				Emitter.Emit(il, OpCodes.Br_S, done);
				Emitter.MarkLabel(il, ptrNonZero);
				Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(paramType));
				Emitter.MarkLabel(il, done);
			}
		}
Exemplo n.º 14
0
		private static Type Il2CppTypeForPatchType(Type type) {
			if (type.IsByRef) {
				Type element = type.GetElementType();
				if (element == typeof(string) || UnhollowerSupport.IsGeneratedAssemblyType(element)) {
					return typeof(IntPtr*);
				} else {
					return type;
				}
			} else if (type == typeof(string) || UnhollowerSupport.IsGeneratedAssemblyType(type)) {
				return typeof(IntPtr);
			} else {
				return type;
			}
		}
Exemplo n.º 15
0
        public List <DynamicMethod> Patch()
        {
            lock (locker)
            {
                var dynamicMethods = new List <DynamicMethod>();
                foreach (var original in originals)
                {
                    if (original == null)
                    {
                        throw new NullReferenceException("original");
                    }

                    if ((original.DeclaringType.Assembly.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0) ||
                        (original.DeclaringType.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0) ||
                        (original.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0))
                    {
                        continue;
                    }

                    if (MelonDebug.IsEnabled() && UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType))
                    {
                        WarnIfTargetMethodInlined(original);
                    }

                    var individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, original);
                    if (individualPrepareResult)
                    {
                        var patchInfo = HarmonySharedState.GetPatchInfo(original);
                        if (patchInfo == null)
                        {
                            patchInfo = new PatchInfo();
                        }

                        PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix);
                        PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix);
                        PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler);
                        dynamicMethods.Add(PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id));

                        HarmonySharedState.UpdatePatchInfo(original, patchInfo);

                        RunMethod <HarmonyCleanup>(original);
                    }
                }
                return(dynamicMethods);
            }
        }
Exemplo n.º 16
0
        private void WarnIfTargetMethodInlined(MethodBase target)
        {
            int callerCount = UnhollowerSupport.GetIl2CppMethodCallerCount(target) ?? -1;

            if (callerCount == 0 && !UnityMagicMethods.IsUnityMagicMethod(target))
            {
                string melonName = FindMelon(melon => melon.Harmony == instance);
                if (melonName == null)
                {
                    // Patching using a custom Harmony instance; try to infer the melon assembly from the container type, prefix, postfix, or transpiler.
                    Assembly melonAssembly = container?.Assembly ?? prefix?.declaringType?.Assembly ?? postfix?.declaringType?.Assembly ?? transpiler?.declaringType?.Assembly;
                    if (melonAssembly != null)
                    {
                        melonName = FindMelon(melon => melon.Assembly == melonAssembly);
                    }
                }
                MelonLogger.ManualWarning(melonName, $"Harmony: Method {target.FullDescription()} does not appear to get called directly from anywhere, " +
                                          "suggesting it may have been inlined and your patch may not be called.");
            }
        }
        private void WarnIfOriginalMethodIsInlined(MelonLogger.Instance loggerInstance)
        {
            int callerCount = UnhollowerSupport.GetIl2CppMethodCallerCount(Original) ?? -1;

            if (callerCount > 0 ||
                UnityMagicMethods.IsUnityMagicMethod(Original))
            {
                return;
            }
            string txt = $"Harmony: Method {Original.FullDescription()} does not appear to get called directly from anywhere, " +
                         "suggesting it may have been inlined and your patch may not be called.";

            if (loggerInstance != null)
            {
                loggerInstance.Warning(txt);
            }
            else
            {
                MelonLogger.Warning(txt);
            }
        }
        public static unsafe void FakeMethod(IntPtr aaaa)
        {
            var objectPtr = UnhollowerSupport.Il2CppObjectPtrToIl2CppObject <Component>(aaaa);

            //var testIng = Il2CppType.TypeFromPointer(aaaa, nameof(UnityEngine.Component));
            if (objectPtr == null)
            {
                return;
            }
            // MelonLogger.Log(objectPtr.name);
            var TheTypes = GetTypes();

            if (TheTypes == null)
            {
                return;
            }
            if (!TheTypes.Any())
            {
                return;
            }
            //var myobj = Marshal.PtrToStructure<Component>(aaaa);
            //MelonLogger.Log(&aaaa->name);
            foreach (var type in TheTypes)
            {
                if (!objectPtr.GetType().IsAssignableFrom(type))
                {
                    continue;
                }
                //MelonLogger.Log(objectPtr.name);
                Object.Destroy(objectPtr);
            }
            //Object.Destroy(aaaa);

            //MelonLogger.Log(test);
            return;
        }
Exemplo n.º 19
0
 private HarmonyMethodPatcher(MethodBase original) : base(original)
 {
     originalMethodInfoPointer = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(Original);
     copiedMethodInfoPointer   = Main.unhollower.CopyMethodInfoStruct(originalMethodInfoPointer);
 }
Exemplo n.º 20
0
        private static DynamicMethod CreateIl2CppShim(DynamicMethod original, Type owner)
        {
            var patchName = original.Name + "_il2cpp";

            var parameters     = original.GetParameters();
            var result         = parameters.Types().ToList();
            var origParamTypes = result.ToArray();
            var paramTypes     = new Type[origParamTypes.Length];

            for (int i = 0; i < paramTypes.Length; ++i)
            {
                paramTypes[i] = UnhollowerSupport.IsGeneratedAssemblyType(origParamTypes[i]) ? typeof(IntPtr) : origParamTypes[i];
            }

            var origReturnType = AccessTools.GetReturnedType(original);
            var returnType     = UnhollowerSupport.IsGeneratedAssemblyType(origReturnType) ? typeof(IntPtr) : origReturnType;

            DynamicMethod method;

            method = new DynamicMethod(
                patchName,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                paramTypes,
                owner,
                true
                );

            for (var i = 0; i < parameters.Length; i++)
            {
                method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
            }

            var il = method.GetILGenerator();

            // Load arguments, invoking the IntPrt -> Il2CppObject constructor for IL2CPP types
            for (int i = 0; i < origParamTypes.Length; ++i)
            {
                Emitter.Emit(il, OpCodes.Ldarg, i);
                if (UnhollowerSupport.IsGeneratedAssemblyType(origParamTypes[i]))
                {
                    Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(origParamTypes[i]));
                }
            }

            // Call the original patch with the now-correct types
            Emitter.Emit(il, OpCodes.Call, original);

            // If needed, unwrap the return value; then return
            if (UnhollowerSupport.IsGeneratedAssemblyType(origReturnType))
            {
                var pointerGetter = AccessTools.DeclaredProperty(UnhollowerSupport.Il2CppObjectBaseType, "Pointer").GetGetMethod();
                Emitter.Emit(il, OpCodes.Call, pointerGetter);
            }

            Emitter.Emit(il, OpCodes.Ret);

            DynamicTools.PrepareDynamicMethod(method);
            return(method);
        }
 private HarmonyIl2CppMethodPatcher(MethodBase original) : base(original)
 {
     originalMethodInfoPointer = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(Original);
     copiedMethodInfoPointer   = (IntPtr)UnhollowerSupport.CopyMethodInfoStructMethod.Invoke(null, new object[] { originalMethodInfoPointer });
 }