From 7529092ab1cf935be3c9bcff5e240ee1ce7fb02d Mon Sep 17 00:00:00 2001 From: p1xel8ted <10510767+p1xel8ted@users.noreply.github.com> Date: Sun, 21 Jan 2024 10:54:04 +1100 Subject: [PATCH 1/5] Ubisoft+ --- .../XrefScans/XrefScanMethodDb.cs | 2 +- .../Injection/InjectorHelpers.cs | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs b/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs index 3958f4a7..6acd3bb6 100644 --- a/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs +++ b/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs @@ -21,7 +21,7 @@ static XrefScanMethodDb() XrefScanCache = new MethodXrefScanCache(GeneratedDatabasesUtil.GetDatabasePath(MethodXrefScanCache.FileName)); foreach (ProcessModule module in Process.GetCurrentProcess().Modules) - if (module.ModuleName == "GameAssembly.dll") + if (module.ModuleName is "GameAssembly.dll" or "GameAssembly_plus.dll") { GameAssemblyBase = (long)module.BaseAddress; break; diff --git a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs index b1729e42..aff9cb32 100644 --- a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs +++ b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs @@ -8,30 +8,34 @@ using System.Runtime.InteropServices; using System.Threading; using Il2CppInterop.Common; -using Il2CppInterop.Common.Extensions; -using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Runtime.Injection.Hooks; using Il2CppInterop.Runtime.Runtime; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Assembly; -using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class; -using Il2CppInterop.Runtime.Runtime.VersionSpecific.FieldInfo; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Image; using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo; -using Il2CppInterop.Runtime.Startup; using Microsoft.Extensions.Logging; namespace Il2CppInterop.Runtime.Injection { internal static unsafe class InjectorHelpers { + private static readonly string[] s_assemblies = ["GameAssembly.dll", "GameAssembly_plus.dll", "GameAssembly.so", "GameAssembly_plus.so", "UserAssembly.dll", "UserAssembly_plus.dll"]; + internal static Assembly Il2CppMscorlib = typeof(Il2CppSystem.Type).Assembly; internal static INativeAssemblyStruct InjectedAssembly; internal static INativeImageStruct InjectedImage; internal static ProcessModule Il2CppModule = Process.GetCurrentProcess() .Modules.OfType() - .Single((x) => x.ModuleName is "GameAssembly.dll" or "GameAssembly.so" or "UserAssembly.dll"); + .Single(x => s_assemblies.Contains(x.ModuleName, StringComparer.OrdinalIgnoreCase)); - internal static IntPtr Il2CppHandle = NativeLibrary.Load("GameAssembly", typeof(InjectorHelpers).Assembly, null); + internal static IntPtr Il2CppHandle + { + get + { + var assembly = Il2CppModule.ModuleName != null && Il2CppModule.ModuleName.Contains("_plus") ? "GameAssembly_plus" : "GameAssembly"; + return NativeLibrary.Load(assembly, typeof(InjectorHelpers).Assembly, null); + } + } internal static readonly Dictionary StIndOpcodes = new() { From ca2c37721e5a5bca245f21ff93b99e0b59b5ba15 Mon Sep 17 00:00:00 2001 From: p1xel8ted <10510767+p1xel8ted@users.noreply.github.com> Date: Sun, 21 Jan 2024 10:54:04 +1100 Subject: [PATCH 2/5] Ubisoft+ --- .../XrefScans/XrefScanMethodDb.cs | 2 +- .../Injection/InjectorHelpers.cs | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs b/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs index 3958f4a7..6acd3bb6 100644 --- a/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs +++ b/Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs @@ -21,7 +21,7 @@ static XrefScanMethodDb() XrefScanCache = new MethodXrefScanCache(GeneratedDatabasesUtil.GetDatabasePath(MethodXrefScanCache.FileName)); foreach (ProcessModule module in Process.GetCurrentProcess().Modules) - if (module.ModuleName == "GameAssembly.dll") + if (module.ModuleName is "GameAssembly.dll" or "GameAssembly_plus.dll") { GameAssemblyBase = (long)module.BaseAddress; break; diff --git a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs index b1729e42..2966a4ff 100644 --- a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs +++ b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs @@ -8,30 +8,34 @@ using System.Runtime.InteropServices; using System.Threading; using Il2CppInterop.Common; -using Il2CppInterop.Common.Extensions; -using Il2CppInterop.Common.XrefScans; using Il2CppInterop.Runtime.Injection.Hooks; using Il2CppInterop.Runtime.Runtime; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Assembly; -using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class; -using Il2CppInterop.Runtime.Runtime.VersionSpecific.FieldInfo; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Image; using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo; -using Il2CppInterop.Runtime.Startup; using Microsoft.Extensions.Logging; namespace Il2CppInterop.Runtime.Injection { internal static unsafe class InjectorHelpers { + private static readonly string[] s_assemblies = {"GameAssembly.dll", "GameAssembly_plus.dll", "GameAssembly.so", "GameAssembly_plus.so", "UserAssembly.dll", "UserAssembly_plus.dll"}; + internal static Assembly Il2CppMscorlib = typeof(Il2CppSystem.Type).Assembly; internal static INativeAssemblyStruct InjectedAssembly; internal static INativeImageStruct InjectedImage; internal static ProcessModule Il2CppModule = Process.GetCurrentProcess() .Modules.OfType() - .Single((x) => x.ModuleName is "GameAssembly.dll" or "GameAssembly.so" or "UserAssembly.dll"); + .Single(x => s_assemblies.Contains(x.ModuleName, StringComparer.OrdinalIgnoreCase)); - internal static IntPtr Il2CppHandle = NativeLibrary.Load("GameAssembly", typeof(InjectorHelpers).Assembly, null); + internal static IntPtr Il2CppHandle + { + get + { + var assembly = Il2CppModule.ModuleName != null && Il2CppModule.ModuleName.Contains("_plus") ? "GameAssembly_plus" : "GameAssembly"; + return NativeLibrary.Load(assembly, typeof(InjectorHelpers).Assembly, null); + } + } internal static readonly Dictionary StIndOpcodes = new() { From 452a748fa03dbabcdd5e2066641ed5a427d16db9 Mon Sep 17 00:00:00 2001 From: p1xel8ted <10510767+p1xel8ted@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:36:15 +1100 Subject: [PATCH 3/5] Whitespace Fix? --- .../Injection/InjectorHelpers.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs index 2966a4ff..3994c840 100644 --- a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs +++ b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs @@ -24,6 +24,7 @@ internal static unsafe class InjectorHelpers internal static Assembly Il2CppMscorlib = typeof(Il2CppSystem.Type).Assembly; internal static INativeAssemblyStruct InjectedAssembly; internal static INativeImageStruct InjectedImage; + internal static ProcessModule Il2CppModule = Process.GetCurrentProcess() .Modules.OfType() .Single(x => s_assemblies.Contains(x.ModuleName, StringComparer.OrdinalIgnoreCase)); @@ -55,6 +56,7 @@ internal static IntPtr Il2CppHandle private static void CreateInjectedAssembly() { InjectedAssembly = UnityVersionHandler.NewAssembly(); + InjectedImage = UnityVersionHandler.NewImage(); InjectedAssembly.Name.Name = Marshal.StringToHGlobalAnsi("InjectedMonoTypes"); @@ -141,29 +143,18 @@ internal static IntPtr GetIl2CppMethodPointer(MethodBase proxyMethod) private static long s_LastInjectedToken = -2; internal static readonly ConcurrentDictionary s_InjectedClasses = new(); + /// (namespace, class, image) : class internal static readonly Dictionary<(string _namespace, string _class, IntPtr imagePtr), IntPtr> s_ClassNameLookup = new(); #region Class::Init + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void d_ClassInit(Il2CppClass* klass); + internal static d_ClassInit ClassInit; - private static readonly MemoryUtils.SignatureDefinition[] s_ClassInitSignatures = - { - new MemoryUtils.SignatureDefinition - { - pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x28\x83", - mask = "x????xxxxx", - xref = true - }, - new MemoryUtils.SignatureDefinition - { - pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x48\x48", - mask = "x????xxxxx", - xref = true - } - }; + private static readonly MemoryUtils.SignatureDefinition[] s_ClassInitSignatures = {new MemoryUtils.SignatureDefinition {pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x28\x83", mask = "x????xxxxx", xref = true}, new MemoryUtils.SignatureDefinition {pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x48\x48", mask = "x????xxxxx", xref = true}}; private static d_ClassInit FindClassInit() { @@ -188,6 +179,7 @@ static nint GetClassInitSubstitute() Logger.Instance.LogTrace("GameAssembly.dll: 0x{Il2CppModuleAddress}", Il2CppModule.BaseAddress.ToInt64().ToString("X2")); throw new NotSupportedException("Failed to use signature for Class::Init and a substitute cannot be found, please create an issue and report your unity version & game"); } + nint pClassInit = s_ClassInitSignatures .Select(s => MemoryUtils.FindSignatureInModule(Il2CppModule, s)) .FirstOrDefault(p => p != 0); @@ -202,6 +194,8 @@ static nint GetClassInitSubstitute() return Marshal.GetDelegateForFunctionPointer(pClassInit); } + #endregion + } } From e441b8baea8330397e16d8154a803c069718f114 Mon Sep 17 00:00:00 2001 From: p1xel8ted <10510767+p1xel8ted@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:36:15 +1100 Subject: [PATCH 4/5] Whitespace Fix? --- .../Injection/InjectorHelpers.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs index 2966a4ff..3994c840 100644 --- a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs +++ b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs @@ -24,6 +24,7 @@ internal static unsafe class InjectorHelpers internal static Assembly Il2CppMscorlib = typeof(Il2CppSystem.Type).Assembly; internal static INativeAssemblyStruct InjectedAssembly; internal static INativeImageStruct InjectedImage; + internal static ProcessModule Il2CppModule = Process.GetCurrentProcess() .Modules.OfType() .Single(x => s_assemblies.Contains(x.ModuleName, StringComparer.OrdinalIgnoreCase)); @@ -55,6 +56,7 @@ internal static IntPtr Il2CppHandle private static void CreateInjectedAssembly() { InjectedAssembly = UnityVersionHandler.NewAssembly(); + InjectedImage = UnityVersionHandler.NewImage(); InjectedAssembly.Name.Name = Marshal.StringToHGlobalAnsi("InjectedMonoTypes"); @@ -141,29 +143,18 @@ internal static IntPtr GetIl2CppMethodPointer(MethodBase proxyMethod) private static long s_LastInjectedToken = -2; internal static readonly ConcurrentDictionary s_InjectedClasses = new(); + /// (namespace, class, image) : class internal static readonly Dictionary<(string _namespace, string _class, IntPtr imagePtr), IntPtr> s_ClassNameLookup = new(); #region Class::Init + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void d_ClassInit(Il2CppClass* klass); + internal static d_ClassInit ClassInit; - private static readonly MemoryUtils.SignatureDefinition[] s_ClassInitSignatures = - { - new MemoryUtils.SignatureDefinition - { - pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x28\x83", - mask = "x????xxxxx", - xref = true - }, - new MemoryUtils.SignatureDefinition - { - pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x48\x48", - mask = "x????xxxxx", - xref = true - } - }; + private static readonly MemoryUtils.SignatureDefinition[] s_ClassInitSignatures = {new MemoryUtils.SignatureDefinition {pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x28\x83", mask = "x????xxxxx", xref = true}, new MemoryUtils.SignatureDefinition {pattern = "\xE8\x00\x00\x00\x00\x0F\xB7\x47\x48\x48", mask = "x????xxxxx", xref = true}}; private static d_ClassInit FindClassInit() { @@ -188,6 +179,7 @@ static nint GetClassInitSubstitute() Logger.Instance.LogTrace("GameAssembly.dll: 0x{Il2CppModuleAddress}", Il2CppModule.BaseAddress.ToInt64().ToString("X2")); throw new NotSupportedException("Failed to use signature for Class::Init and a substitute cannot be found, please create an issue and report your unity version & game"); } + nint pClassInit = s_ClassInitSignatures .Select(s => MemoryUtils.FindSignatureInModule(Il2CppModule, s)) .FirstOrDefault(p => p != 0); @@ -202,6 +194,8 @@ static nint GetClassInitSubstitute() return Marshal.GetDelegateForFunctionPointer(pClassInit); } + #endregion + } } From 18893cf4a29ab83037e02a9a839258547b5fc3fe Mon Sep 17 00:00:00 2001 From: p1xel8ted <10510767+p1xel8ted@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:51:16 +1100 Subject: [PATCH 5/5] Whitespace Fix --- Il2CppInterop.Runtime/Injection/InjectorHelpers.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs index 5e1aad95..d23d053e 100644 --- a/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs +++ b/Il2CppInterop.Runtime/Injection/InjectorHelpers.cs @@ -19,7 +19,15 @@ namespace Il2CppInterop.Runtime.Injection { internal static unsafe class InjectorHelpers { - private static readonly string[] s_assemblies = {"GameAssembly.dll", "GameAssembly_plus.dll", "GameAssembly.so", "GameAssembly_plus.so", "UserAssembly.dll", "UserAssembly_plus.dll"}; + private static readonly string[] s_assemblies = + { + "GameAssembly.dll", + "GameAssembly_plus.dll", + "GameAssembly.so", + "GameAssembly_plus.so", + "UserAssembly.dll", + "UserAssembly_plus.dll" + }; internal static Assembly Il2CppMscorlib = typeof(Il2CppSystem.Type).Assembly; internal static INativeAssemblyStruct InjectedAssembly;