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"); }
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); } } } } }
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]); } }