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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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;
            }
        }
Exemple #4
0
 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));
     }
 }
Exemple #5
0
        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);
        }
Exemple #6
0
        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;
            }
        }