Esempio n. 1
0
        public static void RegisterTypeInIl2Cpp <T>() where T : class
        {
            var type = typeof(T);

            if (type.IsGenericType || type.IsGenericTypeDefinition)
            {
                throw new ArgumentException($"Type {type} is generic and can't be used in il2cpp");
            }

            var currentPointer = Il2CppClassPointerStore <T> .NativeClassPtr;

            if (currentPointer != IntPtr.Zero)
            {
                throw new ArgumentException($"Type {type} is already registered in il2cpp");
            }

            var baseType         = type.BaseType;
            var baseClassPointer = UnityVersionHandler.Wrap((Il2CppClass *)ReadClassPointerForType(baseType));

            if (baseClassPointer == null)
            {
                throw new ArgumentException($"Base class {baseType} of class {type} is not registered in il2cpp");
            }

            if ((baseClassPointer.Part2->bitfield_1 & ClassBitfield1.valuetype) != 0 || (baseClassPointer.Part2->bitfield_1 & ClassBitfield1.enumtype) != 0)
            {
                throw new ArgumentException($"Base class {baseType} is value type and can't be inherited from");
            }

            if ((baseClassPointer.Part2->bitfield_1 & ClassBitfield1.is_generic) != 0)
            {
                throw new ArgumentException($"Base class {baseType} is generic and can't be inherited from");
            }

            if ((baseClassPointer.Part2->flags & Il2CppClassAttributes.TYPE_ATTRIBUTE_SEALED) != 0)
            {
                throw new ArgumentException($"Base class {baseType} is sealed and can't be inherited from");
            }

            if ((baseClassPointer.Part2->flags & Il2CppClassAttributes.TYPE_ATTRIBUTE_INTERFACE) != 0)
            {
                throw new ArgumentException($"Base class {baseType} is an interface and can't be inherited from");
            }

            lock (InjectedTypes)
                if (!InjectedTypes.Add(typeof(T).FullName))
                {
                    throw new ArgumentException($"Type with FullName {typeof(T).FullName} is already injected. Don't inject the same type twice, or use a different namespace");
                }

            if (ourOriginalTypeToClassMethod == null)
            {
                HookClassFromType();
            }

            var classPointer = UnityVersionHandler.NewClass(baseClassPointer.Part2->vtable_count);

            classPointer.Part1->image         = FakeImage;
            classPointer.Part1->parent        = baseClassPointer.ClassPointer;
            classPointer.Part1->element_class = classPointer.Part1->klass = classPointer.Part1->castClass = classPointer.ClassPointer;
            classPointer.Part2->native_size   = -1;
            classPointer.Part2->actualSize    = classPointer.Part2->instance_size = baseClassPointer.Part2->instance_size + (uint)IntPtr.Size;
            classPointer.Part2->bitfield_1    = ClassBitfield1.initialized | ClassBitfield1.initialized_and_no_error |
                                                ClassBitfield1.size_inited;
            classPointer.Part2->bitfield_2 = ClassBitfield2.has_finalize | ClassBitfield2.is_vtable_initialized;
            classPointer.Part1->name       = Marshal.StringToHGlobalAnsi(type.Name);
            classPointer.Part1->namespaze  = Marshal.StringToHGlobalAnsi(type.Namespace);

            classPointer.Part1->this_arg.type           = classPointer.Part1->byval_arg.type = Il2CppTypeEnum.IL2CPP_TYPE_CLASS;
            classPointer.Part1->this_arg.mods_byref_pin = 64;

            classPointer.Part2->flags = baseClassPointer.Part2->flags; // todo: adjust flags?

            var eligibleMethods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Where(IsMethodEligible).ToArray();
            var methodCount     = 2 + eligibleMethods.Length; // 1 is the finalizer, 1 is empty ctor

            classPointer.Part2->method_count = (ushort)methodCount;
            var methodPointerArray = (Il2CppMethodInfo **)Marshal.AllocHGlobal(methodCount * IntPtr.Size);

            classPointer.Part1->methods = methodPointerArray;

            methodPointerArray[0] = ConvertStaticMethod(FinalizeDelegate, "Finalize", classPointer);
            methodPointerArray[1] = ConvertStaticMethod(CreateEmptyCtor(type), ".ctor", classPointer);
            for (var i = 0; i < eligibleMethods.Length; i++)
            {
                var methodInfo = eligibleMethods[i];
                methodPointerArray[i + 2] = ConvertMethodInfo(methodInfo, classPointer);
            }

            var vTablePointer     = (VirtualInvokeData *)classPointer.VTable;
            var baseVTablePointer = (VirtualInvokeData *)baseClassPointer.VTable;

            classPointer.Part2->vtable_count = baseClassPointer.Part2->vtable_count;
            for (var i = 0; i < classPointer.Part2->vtable_count; i++)
            {
                vTablePointer[i] = baseVTablePointer[i];
                if (Marshal.PtrToStringAnsi(vTablePointer[i].method->name) == "Finalize") // slot number is not static
                {
                    vTablePointer[i].method    = methodPointerArray[0];
                    vTablePointer[i].methodPtr = methodPointerArray[0]->methodPointer;
                }
            }

            var newCounter = Interlocked.Decrement(ref ourClassOverrideCounter);

            FakeTokenClasses[newCounter]       = classPointer.Pointer;
            classPointer.Part1->byval_arg.data = classPointer.Part1->this_arg.data = (IntPtr)newCounter;

            RuntimeSpecificsStore.SetClassInfo(classPointer.Pointer, true, true);
            Il2CppClassPointerStore <T> .NativeClassPtr = classPointer.Pointer;

            LogSupport.Info($"Registered mono type {typeof(T)} in il2cpp domain");
        }
Esempio n. 2
0
        private static ISupportModule Initialize()
        {
            LogSupport.RemoveAllHandlers();
            if (Console.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler += MelonModLogger.Log;
            }
            LogSupport.WarningHandler += MelonModLogger.LogWarning;
            LogSupport.ErrorHandler   += MelonModLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler += MelonModLogger.Log;
            }

            try
            {
                Assembly il2cppSystem = Assembly.Load("Il2CppSystem");
                if (il2cppSystem != null)
                {
                    Type unitytls = il2cppSystem.GetType("Il2CppMono.Unity.UnityTls");
                    if (unitytls != null)
                    {
                        unsafe
                        {
                            var tlsHookTarget    = typeof(Uri).Assembly.GetType("Mono.Unity.UnityTls").GetMethod("GetUnityTlsInterface", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).MethodHandle.GetFunctionPointer();
                            var unityMethodField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(unitytls.GetMethod("GetUnityTlsInterface", BindingFlags.Public | BindingFlags.Static));
                            var unityMethodPtr   = (IntPtr)unityMethodField.GetValue(null);
                            var unityMethod      = *(IntPtr *)unityMethodPtr;
                            Imports.Hook((IntPtr)(&tlsHookTarget), unityMethod);
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Type Il2CppMono.Unity.UnityTls!");
                    }
                }
                else
                {
                    throw new Exception("Failed to get Assembly Il2CppSystem!");
                }
            }
            catch (Exception ex)
            {
                MelonModLogger.LogWarning("Exception while setting up TLS, mods will not be able to use HTTPS: " + ex);
            }

            if (MelonLoader.Main.IsVRChat)
            {
                try
                {
                    Assembly Transmtn = Assembly.Load("Transmtn");
                    if (Transmtn != null)
                    {
                        Type Transmtn_HttpConnection = Transmtn.GetType("Transmtn.HttpConnection");
                        if (Transmtn_HttpConnection != null)
                        {
                            Il2CppSystem_Console_WriteLine = typeof(Il2CppSystem.Console).GetMethods(BindingFlags.Public | BindingFlags.Static).First(x => (x.Name.Equals("WriteLine") && (x.GetParameters().Count() == 1) && (x.GetParameters()[0].ParameterType == typeof(string))));
                            if (harmonyInstance == null)
                            {
                                harmonyInstance = HarmonyInstance.Create("MelonLoader.Support.Il2Cpp");
                            }
                            harmonyInstance.Patch(Transmtn_HttpConnection.GetMethod("get", BindingFlags.Public | BindingFlags.Instance), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Prefix", BindingFlags.NonPublic | BindingFlags.Static)), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Postfix", BindingFlags.NonPublic | BindingFlags.Static)));
                        }
                        else
                        {
                            throw new Exception("Failed to get Type Transmtn.HttpConnection!");
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Assembly Transmtn!");
                    }
                }
                catch (Exception ex)
                {
                    MelonModLogger.LogWarning("Exception while setting up Auth Token Hider, Auth Tokens may show in Console: " + ex);
                }
            }

            ClassInjector.DoHook += Imports.Hook;
            GetUnityVersionNumbers(out var major, out var minor, out var patch);
            UnityVersionHandler.Initialize(major, minor, patch);

            SetAsLastSiblingDelegateField = IL2CPP.ResolveICall <SetAsLastSiblingDelegate>("UnityEngine.Transform::SetAsLastSibling");

            ClassInjector.RegisterTypeInIl2Cpp <MelonLoaderComponent>();
            MelonLoaderComponent.Create();

            SceneManager.sceneLoaded = (
                (SceneManager.sceneLoaded == null)
                ? new Action <Scene, LoadSceneMode>(OnSceneLoad)
                : Il2CppSystem.Delegate.Combine(SceneManager.sceneLoaded, (UnityAction <Scene, LoadSceneMode>) new Action <Scene, LoadSceneMode>(OnSceneLoad)).Cast <UnityAction <Scene, LoadSceneMode> >()
                );
            Camera.onPostRender = (
                (Camera.onPostRender == null)
                ? new Action <Camera>(OnPostRender)
                : Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) new Action <Camera>(OnPostRender)).Cast <Camera.CameraCallback>()
                );

            return(new Module());
        }
Esempio n. 3
0
    public static void Run()
    {
        try
        {
            HarmonyBackendFix.Initialize();

            ConsoleManager.Initialize(false, false);

            PreloaderLog = new PreloaderConsoleListener();
            Logger.Listeners.Add(PreloaderLog);

            if (ConsoleManager.ConsoleEnabled)
            {
                ConsoleManager.CreateConsole();
                Logger.Listeners.Add(new ConsoleLogListener());
            }

            ChainloaderLogHelper.PrintLogInfo(Log);

            Log.Log(LogLevel.Debug, $"Game executable path: {Paths.ExecutablePath}");
            Log.Log(LogLevel.Debug, $"Unhollowed assembly directory: {IL2CPPUnhollowedPath}");
            Log.Log(LogLevel.Debug, $"BepInEx root path: {Paths.BepInExRootPath}");

            UnhollowerLog              = Logger.CreateLogSource("Unhollower");
            LogSupport.InfoHandler    += UnhollowerLog.LogInfo;
            LogSupport.WarningHandler += UnhollowerLog.LogWarning;
            LogSupport.TraceHandler   += UnhollowerLog.LogDebug;
            LogSupport.ErrorHandler   += UnhollowerLog.LogError;

            InitializeUnityVersion();

            if (ProxyAssemblyGenerator.CheckIfGenerationRequired())
            {
                ProxyAssemblyGenerator.GenerateAssemblies();
            }

            UnityVersionHandler.Initialize(UnityVersion.Major, UnityVersion.Minor, UnityVersion.Build);

            using (var assemblyPatcher = new AssemblyPatcher())
            {
                assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);

                Log.LogInfo($"{assemblyPatcher.PatcherContext.PatcherPlugins.Count} patcher plugin{(assemblyPatcher.PatcherContext.PatcherPlugins.Count == 1 ? "" : "s")} loaded");

                assemblyPatcher.LoadAssemblyDirectories(IL2CPPUnhollowedPath);

                Log.LogInfo($"{assemblyPatcher.PatcherContext.PatcherPlugins.Count} assemblies discovered");

                assemblyPatcher.PatchAndLoad();
            }


            Logger.Listeners.Remove(PreloaderLog);


            Chainloader = new IL2CPPChainloader();

            Chainloader.Initialize();
        }
        catch (Exception ex)
        {
            Log.Log(LogLevel.Fatal, ex);

            throw;
        }
    }
Esempio n. 4
0
        private static ISupportModule Initialize()
        {
            if (Console.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler -= System.Console.WriteLine;
                LogSupport.InfoHandler += MelonModLogger.Log;
            }
            LogSupport.WarningHandler -= System.Console.WriteLine;
            LogSupport.WarningHandler += MelonModLogger.LogWarning;
            LogSupport.ErrorHandler   -= System.Console.WriteLine;
            LogSupport.ErrorHandler   += MelonModLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler -= System.Console.WriteLine;
                LogSupport.TraceHandler += MelonModLogger.Log;
            }

            try
            {
                Assembly il2cppSystem = Assembly.Load("Il2CppSystem");
                if (il2cppSystem != null)
                {
                    Type unitytls = il2cppSystem.GetType("Il2CppMono.Unity.UnityTls");
                    if (unitytls != null)
                    {
                        unsafe
                        {
                            var tlsHookTarget    = typeof(Uri).Assembly.GetType("Mono.Unity.UnityTls").GetMethod("GetUnityTlsInterface", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).MethodHandle.GetFunctionPointer();
                            var unityMethodField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(unitytls.GetMethod("GetUnityTlsInterface", BindingFlags.Public | BindingFlags.Static));
                            var unityMethodPtr   = (IntPtr)unityMethodField.GetValue(null);
                            var unityMethod      = *(IntPtr *)unityMethodPtr;
                            Imports.Hook((IntPtr)(&tlsHookTarget), unityMethod);
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Type Il2CppMono.Unity.UnityTls!");
                    }
                }
                else
                {
                    throw new Exception("Failed to get Assembly Il2CppSystem!");
                }
            } catch (Exception ex) {
                MelonModLogger.LogWarning("Exception while setting up TLS, mods will not be able to use HTTPS: " + ex);
            }

            ClassInjector.DoHook += Imports.Hook;
            GetUnityVersionNumbers(out var major, out var minor, out var patch);
            UnityVersionHandler.Initialize(major, minor, patch);
            ClassInjector.RegisterTypeInIl2Cpp <MelonLoaderComponent>();
            MelonLoaderComponent.Create();
            SceneManager.sceneLoaded = (
                (SceneManager.sceneLoaded == null)
                ? new Action <Scene, LoadSceneMode>(OnSceneLoad)
                : Il2CppSystem.Delegate.Combine(SceneManager.sceneLoaded, (UnityAction <Scene, LoadSceneMode>) new Action <Scene, LoadSceneMode>(OnSceneLoad)).Cast <UnityAction <Scene, LoadSceneMode> >()
                );
            Camera.onPostRender = (
                (Camera.onPostRender == null)
                ? new Action <Camera>(OnPostRender)
                : Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) new Action <Camera>(OnPostRender)).Cast <Camera.CameraCallback>()
                );
            return(new Module());
        }
Esempio n. 5
0
        private static ISupportModule Initialize()
        {
            LogSupport.RemoveAllHandlers();
            if (MelonConsole.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler += MelonLogger.Log;
            }
            LogSupport.WarningHandler += MelonLogger.LogWarning;
            LogSupport.ErrorHandler   += MelonLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler += MelonLogger.Log;
            }

            if (MelonLoaderBase.IsVRChat)
            {
                try
                {
                    Assembly Transmtn = Assembly.Load("Transmtn");
                    if (Transmtn != null)
                    {
                        Type Transmtn_HttpConnection = Transmtn.GetType("Transmtn.HttpConnection");
                        if (Transmtn_HttpConnection != null)
                        {
                            Il2CppSystem_Console_WriteLine = typeof(Il2CppSystem.Console).GetMethods(BindingFlags.Public | BindingFlags.Static).First(x => (x.Name.Equals("WriteLine") && (x.GetParameters().Count() == 1) && (x.GetParameters()[0].ParameterType == typeof(string))));
                            if (harmonyInstance == null)
                            {
                                harmonyInstance = HarmonyInstance.Create("MelonLoader.Support.Il2Cpp");
                            }
                            harmonyInstance.Patch(Transmtn_HttpConnection.GetMethod("get", BindingFlags.Public | BindingFlags.Instance), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Prefix", BindingFlags.NonPublic | BindingFlags.Static)), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Postfix", BindingFlags.NonPublic | BindingFlags.Static)));
                        }
                        else
                        {
                            throw new Exception("Failed to get Type Transmtn.HttpConnection!");
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Assembly Transmtn!");
                    }
                }
                catch (Exception ex)
                {
                    MelonLogger.LogWarning("Exception while setting up Auth Token Hider, Auth Tokens may show in Console: " + ex);
                }
            }

            ClassInjector.DoHook += Imports.Hook;
            GetUnityVersionNumbers(out var major, out var minor, out var patch);
            UnityVersionHandler.Initialize(major, minor, patch);

            SetAsLastSiblingDelegateField = IL2CPP.ResolveICall <SetAsLastSiblingDelegate>("UnityEngine.Transform::SetAsLastSibling");

            ClassInjector.RegisterTypeInIl2Cpp <MelonLoaderComponent>();
            MelonLoaderComponent.Create();

            SceneManager.sceneLoaded = (
                (SceneManager.sceneLoaded == null)
                ? new Action <Scene, LoadSceneMode>(OnSceneLoad)
                : Il2CppSystem.Delegate.Combine(SceneManager.sceneLoaded, (UnityAction <Scene, LoadSceneMode>) new Action <Scene, LoadSceneMode>(OnSceneLoad)).Cast <UnityAction <Scene, LoadSceneMode> >()
                );
            Camera.onPostRender = (
                (Camera.onPostRender == null)
                ? new Action <Camera>(OnPostRender)
                : Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) new Action <Camera>(OnPostRender)).Cast <Camera.CameraCallback>()
                );

            return(new Module());
        }