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);