public static unsafe nint FindSignatureInModule(ProcessModule module, SignatureDefinition sigDef)
        {
            nint ptr = FindSignatureInBlock(
                module.BaseAddress,
                module.ModuleMemorySize,
                sigDef.pattern,
                sigDef.mask,
                sigDef.offset
                );

            if (ptr != 0 && sigDef.xref)
            {
                ptr = XrefScannerLowLevel.JumpTargets(ptr).FirstOrDefault();
            }
            return(ptr);
        }
        private static void HookClassFromType()
        {
            var lib = LoadLibrary("GameAssembly.dll");
            var classFromTypeEntryPoint = GetProcAddress(lib, nameof(IL2CPP.il2cpp_class_from_il2cpp_type));

            LogSupport.Trace($"il2cpp_class_from_il2cpp_type entry address: {classFromTypeEntryPoint}");

            var targetMethod = XrefScannerLowLevel.JumpTargets(classFromTypeEntryPoint).Single();

            LogSupport.Trace($"Xref scan target: {targetMethod}");

            if (targetMethod == IntPtr.Zero)
            {
                return;
            }

            ourOriginalTypeToClassMethod = Detour.Detour(targetMethod, new TypeToClassDelegate(ClassFromTypePatch));
            LogSupport.Trace("il2cpp_class_from_il2cpp_type patched");
        }
        private static void HookClassFromType()
        {
            var lib = LoadLibrary("UserAssembly.dll");
            var classFromTypeEntryPoint = GetProcAddress(lib, nameof(IL2CPP.il2cpp_class_from_il2cpp_type));

            LogSupport.Trace($"il2cpp_class_from_il2cpp_type entry address: {classFromTypeEntryPoint}");

            var targetMethod = XrefScannerLowLevel.JumpTargets(classFromTypeEntryPoint).Single();

            LogSupport.Trace($"Xref scan target: {targetMethod}");

            if (targetMethod == IntPtr.Zero)
            {
                return;
            }

            IntPtr *targetVarPointer = &targetMethod;

            DoHook((IntPtr)targetVarPointer,
                   Marshal.GetFunctionPointerForDelegate(new TypeToClassDelegate(ClassFromTypePatch)));
            ourOriginalTypeToClassMethod = Marshal.GetDelegateForFunctionPointer <TypeToClassDelegate>(targetMethod);

            LogSupport.Trace("il2cpp_class_from_il2cpp_type patched");
        }
Example #4
0
        public static void DoPass(RewriteGlobalContext context, UnhollowerOptions options)
        {
            if (string.IsNullOrEmpty(options.GameAssemblyPath))
            {
                Pass15GenerateMemberContexts.HasObfuscatedMethods = false;
                return;
            }
            if (!Pass15GenerateMemberContexts.HasObfuscatedMethods)
            {
                return;
            }

            var methodToCallersMap = new Dictionary <long, List <long> >();
            var methodToCalleesMap = new Dictionary <long, List <long> >();

            using var mappedFile = MemoryMappedFile.CreateFromFile(options.GameAssemblyPath, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
            using var accessor   = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);

            IntPtr gameAssemblyPtr;

            unsafe
            {
                byte *fileStartPtr = null;
                accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref fileStartPtr);
                gameAssemblyPtr = (IntPtr)fileStartPtr;
            }

            // Scan xrefs
            foreach (var assemblyRewriteContext in context.Assemblies)
            {
                foreach (var typeRewriteContext in assemblyRewriteContext.Types)
                {
                    foreach (var originalTypeMethod in typeRewriteContext.Methods)
                    {
                        var address = originalTypeMethod.FileOffset;
                        if (address == 0)
                        {
                            continue;
                        }

                        foreach (var callTarget in XrefScannerLowLevel.CallAndIndirectTargets(IntPtr.Add(gameAssemblyPtr, (int)address)))
                        {
                            var targetRelative = (long)callTarget - (long)gameAssemblyPtr;
                            methodToCallersMap.GetOrCreate(targetRelative, _ => new List <long>()).Add(address);
                            methodToCalleesMap.GetOrCreate(address, _ => new List <long>()).Add(targetRelative);
                        }
                    }
                }
            }

            MapOfCallers = methodToCallersMap;

            void MarkMethodAlive(long address)
            {
                if (!NonDeadMethods.Add(address))
                {
                    return;
                }
                if (!methodToCalleesMap.TryGetValue(address, out var calleeList))
                {
                    return;
                }

                foreach (var callee in calleeList)
                {
                    MarkMethodAlive(callee);
                }
            }

            // Now decided which of them are possible dead code
            foreach (var assemblyRewriteContext in context.Assemblies)
            {
                foreach (var typeRewriteContext in assemblyRewriteContext.Types)
                {
                    foreach (var methodRewriteContext in typeRewriteContext.Methods)
                    {
                        if (methodRewriteContext.FileOffset == 0)
                        {
                            continue;
                        }

                        var originalMethod = methodRewriteContext.OriginalMethod;
                        if (!originalMethod.Name.IsObfuscated() || originalMethod.IsVirtual)
                        {
                            MarkMethodAlive(methodRewriteContext.FileOffset);
                        }
                    }
                }
            }
        }
Example #5
0
        public override void OnApplicationStart()
        {
            if (!CheckWasSuccessful || !MustStayTrue || MustStayFalse)
            {
                return;
            }

            AdvancedSafetySettings.RegisterSettings();
            ClassInjector.RegisterTypeInIl2Cpp <SortingOrderHammerer>();

            try
            {
                BundleVerifierMod.OnApplicationStart(HarmonyInstance);
            }
            catch (Exception ex)
            {
                MelonLogger.Error($"Error initializing Bundle Verifier: {ex}");
            }

            var matchingMethods = typeof(AssetManagement)
                                  .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(it =>
                                                                                                                           it.Name.StartsWith("Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_") && it.GetParameters().Length == 6).ToList();

            foreach (var matchingMethod in matchingMethods)
            {
                ObjectInstantiateDelegate originalInstantiateDelegate = null;

                ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer) =>
                                                        ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate);

                NativePatchUtils.NativePatch(matchingMethod, out originalInstantiateDelegate, replacement);
            }

            foreach (var nestedType in typeof(VRCAvatarManager).GetNestedTypes())
            {
                var moveNext = nestedType.GetMethod("MoveNext");
                if (moveNext == null)
                {
                    continue;
                }
                var avatarManagerField = nestedType.GetProperties().SingleOrDefault(it => it.PropertyType == typeof(VRCAvatarManager));
                if (avatarManagerField == null)
                {
                    continue;
                }

                MelonDebug.Msg($"Patching UniTask type {nestedType.FullName}");

                var fieldOffset = (int)IL2CPP.il2cpp_field_get_offset((IntPtr)UnhollowerUtils
                                                                      .GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(avatarManagerField.GetMethod)
                                                                      .GetValue(null));

                unsafe
                {
                    var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(moveNext).GetValue(null);

                    originalMethodPointer = XrefScannerLowLevel.JumpTargets(originalMethodPointer).First();

                    VoidDelegate originalDelegate = null;

                    void TaskMoveNextPatch(IntPtr taskPtr, IntPtr nativeMethodInfo)
                    {
                        var avatarManager = *(IntPtr *)(taskPtr + fieldOffset - 16);

                        using (new AvatarManagerCookie(new VRCAvatarManager(avatarManager)))
                            originalDelegate(taskPtr, nativeMethodInfo);
                    }

                    var patchDelegate = new VoidDelegate(TaskMoveNextPatch);

                    NativePatchUtils.NativePatch(originalMethodPointer, out originalDelegate, patchDelegate);
                }
            }

            ReaderPatches.ApplyPatches();

            SceneManager.add_sceneLoaded(new Action <Scene, LoadSceneMode>((s, _) =>
            {
                if (s.buildIndex == -1)
                {
                    CanReadAudioMixers = false;
                    CanReadBadFloats   = false;
                    MelonDebug.Msg("No reading audio mixers anymore");
                }
            }));

            SceneManager.add_sceneUnloaded(new Action <Scene>(s =>
            {
                if (s.buildIndex == -1)
                {
                    // allow loading mixers from world assetbundles
                    CanReadAudioMixers = true;
                    CanReadBadFloats   = true;
                    MelonDebug.Msg("Can read audio mixers now");
                }
            }));

            PortalHiding.OnApplicationStart();
            AvatarHiding.OnApplicationStart(HarmonyInstance);
            FinalIkPatches.ApplyPatches(HarmonyInstance);

            if (MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit"))
            {
                typeof(UiExpansionKitSupport).GetMethod(nameof(UiExpansionKitSupport.OnApplicationStart), BindingFlags.Static | BindingFlags.Public) !.Invoke(null, new object[0]);
            }
        }