private bool CheckPlatformAttribute() { MelonPlatformAttribute platformAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformAttribute>(Assembly); if ((platformAttribute == null) || (platformAttribute.Platforms == null) || (platformAttribute.Platforms.Length <= 0)) { return(true); } bool is_compatible = false; for (int i = 0; i < platformAttribute.Platforms.Length; i++) { MelonPlatformAttribute.CompatiblePlatforms platform = platformAttribute.Platforms[i]; if ((platform == MelonPlatformAttribute.CompatiblePlatforms.UNIVERSAL) || (MelonUtils.IsGame32Bit() && (platform == MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X86)) || (!MelonUtils.IsGame32Bit() && (platform == MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64))) { is_compatible = true; break; } } if (!is_compatible) { MelonLogger.Error($"Incompatible Platform for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}"); return(false); } return(true); }
public static unsafe IntPtr GetExportedFunctionPointerForModule(long moduleBaseAddress, string importName) { ImageNtHeaders * imageNtHeaders = AnalyseModuleWin((IntPtr)moduleBaseAddress); ImageSectionHeader *pSech = ImageFirstSection(imageNtHeaders); ImageDataDirectory *imageDirectoryEntryExport = MelonUtils.IsGame32Bit() ? &imageNtHeaders->optionalHeader32.exportTable : &imageNtHeaders->optionalHeader64.exportTable; ImageExportDirectory *pExportDirectory = (ImageExportDirectory *)((long)moduleBaseAddress + imageDirectoryEntryExport->virtualAddress); //MelonLoader.MelonLogger.Msg("pExportDirectory at " + string.Format("{0:X}", (ulong)pExportDirectory - (ulong)moduleBaseAddress)); for (uint i = 0; i < imageDirectoryEntryExport->size / sizeof(ImageExportDirectory); ++i) { ImageExportDirectory *pExportDirectoryI = pExportDirectory + i; //MelonLoader.MelonLogger.Msg("pExportDirectoryI->name: " + string.Format("{0:X}", pExportDirectoryI->name)); if (pExportDirectoryI->name != 0) { string imagename = Marshal.PtrToStringAnsi((IntPtr)((long)moduleBaseAddress + pExportDirectoryI->name)); //string imagename = CppUtils.CharArrayPtrToString((IntPtr)pExportDirectoryI->name); //MelonLoader.MelonLogger.Msg("imagename: " + imagename); /* * if (imagename != "UnityPlayer.dll") * continue; */ long baseNameOrdinalOffset = moduleBaseAddress + (int)pExportDirectoryI->addressOfNameOrdinals; long baseFunctionOffset = moduleBaseAddress + (int)pExportDirectoryI->addressOfFunctions; long baseNameOffset = moduleBaseAddress + (int)pExportDirectoryI->addressOfNames; for (int j = 0; j < pExportDirectoryI->numberOfNames; ++j) { ushort ordinal = *(ushort *)((long)baseNameOrdinalOffset + j * 2); long functionnameAddress = moduleBaseAddress + *(int *)(baseNameOffset + j * 4); long functionaddress = moduleBaseAddress + *(int *)(baseFunctionOffset + ordinal * 4); string importname = Marshal.PtrToStringAnsi((IntPtr)functionnameAddress); //MelonLoader.MelonLogger.Msg($"{imagename}::{importname} @ 0x{((ulong)functionaddress - (ulong)moduleBaseAddress):X} (0x{functionaddress:X} - 0x{moduleBaseAddress:X})"); if (importname == importName) { return((IntPtr)functionaddress); } } } } return(IntPtr.Zero); }
private unsafe static void RunInstallFunction() { IntPtr unityplayer = GetUnityPlayerModule(out int unityplayer_size); if (unityplayer == IntPtr.Zero) { return; } IntPtr[] ptrs = null; if (MelonUtils.IsGame32Bit()) { ptrs = GetPointers(unityplayer, unityplayer_size, Signatures_x86); } else { ptrs = GetPointers(unityplayer, unityplayer_size, Signatures_x64); } if ((ptrs == null) || (ptrs.Length <= 0)) { Logger.Warning("Unable to find Il2CppInstallUnityTlsInterface!"); return; } foreach (IntPtr ptr in ptrs) { byte *i = (byte *)ptr.ToPointer(); if (*i == 0 || (*i & 0xF) == 0xF) { continue; } Logger.Msg("Calling Il2CppInstallUnityTlsInterface..."); VoidDelegate installUnityTlsInterface = (VoidDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(VoidDelegate)); installUnityTlsInterface(); break; } }
static GfxDevice() { if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" })) { // `FrameTimingManager_CUSTOM_CaptureFrameTimings()` calls `GetRealGfxDevice()` after 4 bytes. m_GetRealGfxDevice = (GetRealGfxDeviceDelegate)Marshal.GetDelegateForFunctionPointer( CppUtils.ResolveRelativeInstruction( (IntPtr)((long)UnityInternals.ResolveICall("UnityEngine.FrameTimingManager::CaptureFrameTimings") + (MelonUtils.IsGame32Bit() ? 0 : 4))), typeof(GetRealGfxDeviceDelegate)); } }
internal static bool Apply() { NativeSignatureFlags currentFlags = default; currentFlags |= MelonUtils.IsGame32Bit() ? NativeSignatureFlags.X86 : NativeSignatureFlags.X64; currentFlags |= MelonUtils.IsGameIl2Cpp() ? NativeSignatureFlags.Il2Cpp : NativeSignatureFlags.Mono; MelonDebug.Msg("Current Unity flags: " + (uint)currentFlags); string currentUnityVersion = MelonUtils.GetUnityVersion(); int splitIndex = currentUnityVersion.IndexOf('f'); if (splitIndex == -1) { splitIndex = currentUnityVersion.IndexOf('p'); } if (splitIndex > 0) { currentUnityVersion = currentUnityVersion.Substring(0, splitIndex); } MelonDebug.Msg("Unity version: " + currentUnityVersion); string moduleName = "UnityPlayer.dll"; #if LINUX // TODO #elif OSX // TODO #elif ANDROID // TODO #else if (!currentUnityVersion.StartsWith("20") || currentUnityVersion.StartsWith("2017.1")) { moduleName = "player_win.exe"; } #endif IntPtr moduleAddress = IntPtr.Zero; int moduleSize = 0; foreach (ProcessModule module in Process.GetCurrentProcess().Modules) { if (module.ModuleName == moduleName) { moduleAddress = module.BaseAddress; moduleSize = module.ModuleMemorySize; break; } } if (moduleAddress == IntPtr.Zero) { MelonLogger.Error($"Failed to find module \"{moduleName}\""); return(false); } bool success = true; foreach (Type type in typeof(NativeSignatureResolver).Assembly.GetTypes()) { foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) { bool hasAttribute = false; bool signaturefound = false; bool optionalOnEarlyVersion = false; IOrderedEnumerable <NativeSignatureAttribute> nativeSignatureAttributes = fi.GetCustomAttributes(false) .Where(attr => attr is NativeSignatureAttribute) .Select(attr => (NativeSignatureAttribute)attr) .OrderByDescending(attr => attr.LookupIndex); foreach (NativeSignatureAttribute attribute in nativeSignatureAttributes) { hasAttribute = true; if ((attribute.Flags & currentFlags) != attribute.Flags) { continue; } if (!IsUnityVersionOverOrEqual(currentUnityVersion, attribute.MinimalUnityVersions)) { continue; } signaturefound = true; if (attribute.Signature == null) { optionalOnEarlyVersion = true; break; } IntPtr ptr = CppUtils.Sigscan(moduleAddress, moduleSize, attribute.Signature); if (ptr == IntPtr.Zero) { success = false; MelonLogger.Error("Failed to find the signature for field " + fi.Name + " in module. Signature: " + attribute.Signature); break; } if (typeof(Delegate).IsAssignableFrom(fi.FieldType)) { fi.SetValue(null, Marshal.GetDelegateForFunctionPointer(ptr, fi.FieldType)); } else if (typeof(IntPtr).IsAssignableFrom(fi.FieldType)) { fi.SetValue(null, ptr); } else { MelonLogger.Error($"Invalid target type for field \"{fi.FieldType} {fi.Name}\""); } MelonDebug.Msg("Signature for " + fi.Name + ": " + attribute.Signature); break; } if (hasAttribute && !signaturefound && !optionalOnEarlyVersion) { MelonLogger.Error("Failed to find a signature for field " + fi.Name + " for this version of Unity"); success = false; } hasAttribute = false; signaturefound = false; IOrderedEnumerable <NativeFieldValueAttribute> nativeFieldValueAttributes = fi.GetCustomAttributes(false) .Where(attr => attr is NativeFieldValueAttribute) .Select(attr => (NativeFieldValueAttribute)attr) .OrderByDescending(attr => attr.LookupIndex); foreach (NativeFieldValueAttribute attribute in nativeFieldValueAttributes) { hasAttribute = true; if ((attribute.Flags & currentFlags) != attribute.Flags) { continue; } if (!IsUnityVersionOverOrEqual(currentUnityVersion, attribute.MinimalUnityVersions)) { continue; } signaturefound = true; fi.SetValue(null, attribute.Value); MelonDebug.Msg("Value for " + fi.Name + ": " + attribute.Value); break; } if (hasAttribute && !signaturefound) { MelonLogger.Error("Failed to find a value for field " + fi.Name + " for this version of Unity"); success = false; } } } return(success); }
public unsafe override void Setup() { if (!PatchMonoExport()) { Logger.Error("Web Connection based C# Methods may not work as intended."); return; } if (!PatchIl2CppExport()) { Logger.Error("Web Connection based C# Methods may not work as intended."); return; } IntPtr unityplayer = GetUnityPlayerModule(out int unityplayer_size); if (unityplayer == IntPtr.Zero) { return; } IntPtr[] ptrs = null; if (MelonUtils.IsGame32Bit()) { ptrs = CppUtils.SigscanAll(unityplayer, unityplayer_size, "A1 ?? ?? ?? ?? 85 C0 0F 85 68 01 00 00 A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? B8 ?? ?? ?? ?? C7 05"); } else { ptrs = CppUtils.SigscanAll(unityplayer, unityplayer_size, "48 8B 0D ?? ?? ?? ?? 48 85 C9 0F 85 DC 01 00 00 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 89 05"); } if (ptrs.Length <= 0) { if (MelonUtils.IsGame32Bit()) { ptrs = CppUtils.SigscanAll(unityplayer, unityplayer_size, "A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 85 C0 0F 85 68 01 00 00 A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? B8 ?? ?? ?? ?? C7 05"); } else { ptrs = CppUtils.SigscanAll(unityplayer, unityplayer_size, "48 8B 0D ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 85 C9 0F 85 DC 01 00 00 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 89 05"); } } if (ptrs.Length <= 0) { Logger.Error("InstallUnityTlsInterface was not found!"); Logger.Error("Web Connection based C# Methods may not work as intended."); return; } foreach (IntPtr ptr in ptrs) { byte *i = (byte *)ptr.ToPointer(); if (*i == 0 || (*i & 0xF) == 0xF) { continue; } Logger.Msg("Calling InstallUnityTlsInterface..."); dInstallUnityTlsInterface installUnityTlsInterface = (dInstallUnityTlsInterface)Marshal.GetDelegateForFunctionPointer(ptr, typeof(dInstallUnityTlsInterface)); installUnityTlsInterface(); break; } }