diff --git a/src/Core/ReflectionUtility.cs b/src/Core/ReflectionUtility.cs index 1cd09ef..70266cc 100644 --- a/src/Core/ReflectionUtility.cs +++ b/src/Core/ReflectionUtility.cs @@ -164,7 +164,7 @@ namespace UnityExplorer /// /// The base type, which can optionally be abstract / interface. /// All implementations of the type in the current AppDomain. - public static HashSet GetImplementationsOf(this Type baseType, bool allowAbstract) + public static HashSet GetImplementationsOf(this Type baseType, bool allowAbstract, bool allowGeneric) { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); @@ -183,10 +183,15 @@ namespace UnityExplorer foreach (var asm in assemblies) { - foreach (var t in asm.TryGetTypes().Where(t => allowAbstract || (!t.IsAbstract && !t.IsInterface))) + foreach (var t in asm.TryGetTypes().Where(t => (allowAbstract || (!t.IsAbstract && !t.IsInterface)) + && (allowGeneric || !t.IsGenericType))) { - if (baseType.IsAssignableFrom(t) && !set.Contains(t)) - set.Add(t); + try + { + if (baseType.IsAssignableFrom(t) && !set.Contains(t)) + set.Add(t); + } + catch { } } } diff --git a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs index a253b30..8eb479c 100644 --- a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs +++ b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs @@ -69,8 +69,29 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp return s; } - public override string ProcessTypeNameInString(Type type, string theString, ref string typeName) + public override Type GetDeobfuscatedType(Type type) { + if (!builtDeobCache) + BuildDeobfuscationCache(); + + Type ret = type; + try + { + var cppType = Il2CppType.From(type); + var monoType = GetMonoType(cppType); + if (monoType != null) + return monoType; + } + catch { } + + return ret; + } + + public override string ProcessTypeFullNameInString(Type type, string theString, ref string typeName) + { + if (!builtDeobCache) + BuildDeobfuscationCache(); + if (!Il2CppTypeNotNull(type)) return theString; @@ -84,6 +105,27 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp return theString; } + //public override string ProcessTypeFullNameInString(Type type, string theString, ref string typeName) + //{ + // if (!builtDeobCache) + // BuildDeobfuscationCache(); + + // try + // { + // var cppType = Il2CppType.From(type); + // if (s_deobfuscatedTypeNames.ContainsKey(cppType.FullName)) + // { + // typeName = s_deobfuscatedTypeNames[cppType.FullName]; + // theString = theString.Replace(cppType.FullName, typeName); + // } + // } + // catch + // { + // } + + // return theString; + //} + public override Type GetActualType(object obj) { if (obj == null) @@ -131,6 +173,37 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp // keep deobfuscated type name cache, used to display proper name. internal static Dictionary s_deobfuscatedTypeNames = new Dictionary(); + private static bool builtDeobCache = false; + + private static void BuildDeobfuscationCache() + { + foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (var type in asm.TryGetTypes()) + { + try + { + if (type.CustomAttributes.Any(it => it.AttributeType.Name == "ObfuscatedNameAttribute")) + { + var cppType = Il2CppType.From(type); + + if (!Il2CppToMonoType.ContainsKey(cppType.FullName)) + { + Il2CppToMonoType.Add(cppType.AssemblyQualifiedName, type); + s_deobfuscatedTypeNames.Add(cppType.FullName, type.FullName); + } + } + } + catch { } + } + } + + builtDeobCache = true; + + if (s_deobfuscatedTypeNames.Count > 0) + ExplorerCore.Log($"Built deobfuscation cache, count: {s_deobfuscatedTypeNames.Count}"); + } + /// /// Try to get the Mono (Unhollowed) Type representation of the provided . /// @@ -138,36 +211,15 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp /// The Mono Type if found, otherwise null. public static Type GetMonoType(CppType cppType) { + if (!builtDeobCache) + BuildDeobfuscationCache(); + string name = cppType.AssemblyQualifiedName; if (Il2CppToMonoType.ContainsKey(name)) return Il2CppToMonoType[name]; Type ret = Type.GetType(name); - - // Thanks to Slaynash for this deobfuscation snippet! - if (ret == null) - { - string baseName = cppType.FullName; - string baseAssembly = cppType.Assembly.GetName().name; - - ret = AppDomain.CurrentDomain - .GetAssemblies() - .FirstOrDefault(a - => a.GetName().Name == baseAssembly)? - .TryGetTypes() - .FirstOrDefault(t - => t.CustomAttributes.Any(ca - => ca.AttributeType.Name == "ObfuscatedNameAttribute" - && (string)ca.ConstructorArguments[0].Value == baseName)); - - if (ret != null) - { - // deobfuscated type was found, add to cache. - s_deobfuscatedTypeNames.Add(cppType.FullName, ret.FullName); - } - } - Il2CppToMonoType.Add(name, ret); return ret; diff --git a/src/Core/Runtime/Mono/MonoReflection.cs b/src/Core/Runtime/Mono/MonoReflection.cs index 9b96854..5620e1b 100644 --- a/src/Core/Runtime/Mono/MonoReflection.cs +++ b/src/Core/Runtime/Mono/MonoReflection.cs @@ -37,9 +37,11 @@ namespace UnityExplorer.Core.Runtime.Mono public override bool LoadModule(string module) => true; - public override string ProcessTypeNameInString(Type type, string theString, ref string typeName) + public override string ProcessTypeFullNameInString(Type type, string theString, ref string typeName) => theString; + public override Type GetDeobfuscatedType(Type type) => type; + // not necessary public override void BoxStringToType(ref object _string, Type castTo) { } } diff --git a/src/Core/Runtime/ReflectionProvider.cs b/src/Core/Runtime/ReflectionProvider.cs index 80c9b84..068752d 100644 --- a/src/Core/Runtime/ReflectionProvider.cs +++ b/src/Core/Runtime/ReflectionProvider.cs @@ -18,6 +18,8 @@ namespace UnityExplorer.Core.Runtime public abstract Type GetActualType(object obj); + public abstract Type GetDeobfuscatedType(Type type); + public abstract object Cast(object obj, Type castTo); public abstract T TryCast(object obj); @@ -26,7 +28,7 @@ namespace UnityExplorer.Core.Runtime public abstract bool IsReflectionSupported(Type type); - public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName); + public abstract string ProcessTypeFullNameInString(Type type, string theString, ref string typeName); public abstract bool LoadModule(string module);