public static IntPtr GetIl2CppClass(string assemblyName, string namespaze, string className)
        {
            if (!ourImagesMap.TryGetValue(assemblyName, out var image))
            {
                LogSupport.Error($"Assembly {assemblyName} is not registered in il2cpp");
                return(IntPtr.Zero);
            }

            var clazz = il2cpp_class_from_name(image, namespaze, className);

            return(clazz);
        }
        public static IntPtr GetIl2CppField(IntPtr clazz, string fieldName)
        {
            if (clazz == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            var field = il2cpp_class_get_field_from_name(clazz, fieldName);

            if (field == IntPtr.Zero)
            {
                LogSupport.Error($"Field {fieldName} was not found on class {Marshal.PtrToStringAnsi(il2cpp_class_get_name(clazz))}");
            }
            return(field);
        }
        static IL2CPP()
        {
            var domain = il2cpp_domain_get();

            if (domain == IntPtr.Zero)
            {
                LogSupport.Error("No il2cpp domain found; sad!");
                return;
            }
            uint assembliesCount = 0;
            var  assemblies      = il2cpp_domain_get_assemblies(domain, ref assembliesCount);

            for (var i = 0; i < assembliesCount; i++)
            {
                var image = il2cpp_assembly_get_image(assemblies[i]);
                var name  = Marshal.PtrToStringAnsi(il2cpp_image_get_name(image));
                ourImagesMap[name] = image;
            }
        }
        public static IntPtr GetIl2CppNestedType(IntPtr enclosingType, string nestedTypeName)
        {
            if (enclosingType == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            IntPtr iter = IntPtr.Zero;
            IntPtr nestedTypePtr;

            if (il2cpp_class_is_inflated(enclosingType))
            {
                LogSupport.Trace("Original class was inflated, falling back to reflection");
                if (GetNestedTypeViaReflection == null)
                {
                    // todo: clean up this ugly reflection hack
                    GetNestedTypeViaReflection = AppDomain.CurrentDomain.GetAssemblies()
                                                 .FirstOrDefault(it => it.GetName().Name == "UnhollowerRuntimeLib")
                                                 ?.GetType("UnhollowerRuntimeLib.RuntimeReflectionHelper")
                                                 ?.GetMethod("GetNestedTypeViaReflection", BindingFlags.Static | BindingFlags.Public)?.CreateDelegate(typeof(Func <IntPtr, string, IntPtr>)) as Func <IntPtr, string, IntPtr>;
                }

                var result = GetNestedTypeViaReflection?.Invoke(enclosingType, nestedTypeName);
                if (result != null)
                {
                    return(result.Value);
                }
            }
            while ((nestedTypePtr = il2cpp_class_get_nested_types(enclosingType, ref iter)) != IntPtr.Zero)
            {
                if (Marshal.PtrToStringAnsi(il2cpp_class_get_name(nestedTypePtr)) == nestedTypeName)
                {
                    return(nestedTypePtr);
                }
            }

            LogSupport.Error($"Nested type {nestedTypeName} on {Marshal.PtrToStringAnsi(il2cpp_class_get_name(enclosingType))} not found!");

            return(IntPtr.Zero);
        }
        public static IntPtr GetIl2CppMethod(IntPtr clazz, string methodName, params string[] argTypes)
        {
            if (clazz == IntPtr.Zero)
            {
                return(NativeStructUtils.GetMethodInfoForMissingMethod(methodName + "(" + string.Join(", ", argTypes) + ")"));
            }

            for (var index = 0; index < argTypes.Length; index++)
            {
                var argType = argTypes[index];
                argTypes[index] = Regex.Replace(argType, "\\`\\d+", "").Replace('/', '.');
            }

            var    methodsSeen = 0;
            var    lastMethod  = IntPtr.Zero;
            IntPtr iter        = IntPtr.Zero;
            IntPtr method;

            while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero)
            {
                if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName)
                {
                    continue;
                }

                if (il2cpp_method_get_param_count(method) != argTypes.Length)
                {
                    continue;
                }

                methodsSeen++;
                lastMethod = method;

                var badType = false;
                for (var i = 0; i < argTypes.Length; i++)
                {
                    var paramType = il2cpp_method_get_param(method, (uint)i);
                    var typeName  = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType));
                    if (typeName != argTypes[i])
                    {
                        badType = true;
                        break;
                    }
                }

                if (badType)
                {
                    continue;
                }

                return(method);
            }

            var className = Marshal.PtrToStringAnsi(il2cpp_class_get_name(clazz));

            LogSupport.Trace($"Method {className}::{methodName} was stubbed with a random matching method of the same name");

            if (methodsSeen == 1)
            {
                return(lastMethod);
            }

            LogSupport.Trace($"Unable to find method {className}::{methodName}; signature follows");
            foreach (var argType in argTypes)
            {
                LogSupport.Trace($"    {argType}");
            }
            LogSupport.Trace("Available methods of this name follow:");
            iter = IntPtr.Zero;
            while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero)
            {
                if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName)
                {
                    continue;
                }

                var nParams = il2cpp_method_get_param_count(method);
                LogSupport.Trace("Method starts");
                for (var i = 0; i < nParams; i++)
                {
                    var paramType = il2cpp_method_get_param(method, (uint)i);
                    var typeName  = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType));
                    LogSupport.Trace($"    {typeName}");
                }

                return(method);
            }

            return(NativeStructUtils.GetMethodInfoForMissingMethod(className + "::" + methodName + "(" + string.Join(", ", argTypes) + ")"));
        }
Ejemplo n.º 6
0
        public static IntPtr GetIl2CppMethod(IntPtr clazz, string methodName, params string[] argTypes)
        {
            if (clazz == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            for (var index = 0; index < argTypes.Length; index++)
            {
                var argType = argTypes[index];
                argTypes[index] = Regex.Replace(argType, "\\`\\d+", "").Replace('/', '.');
            }

            var    methodsSeen = 0;
            var    lastMethod  = IntPtr.Zero;
            IntPtr iter        = IntPtr.Zero;
            IntPtr method;

            while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero)
            {
                if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName)
                {
                    continue;
                }

                if (il2cpp_method_get_param_count(method) != argTypes.Length)
                {
                    continue;
                }

                methodsSeen++;
                lastMethod = method;

                var badType = false;
                for (var i = 0; i < argTypes.Length; i++)
                {
                    var paramType = il2cpp_method_get_param(method, (uint)i);
                    var typeName  = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType));
                    if (typeName != argTypes[i])
                    {
                        badType = true;
                        break;
                    }
                }

                if (badType)
                {
                    continue;
                }

                return(method);
            }

            if (methodsSeen == 1)
            {
                return(lastMethod);
            }

            LogSupport.Log($"Unable to find method {Marshal.PtrToStringAnsi(il2cpp_class_get_name(clazz))}::{methodName}; signature follows");
            foreach (var argType in argTypes)
            {
                LogSupport.Log($"    {argType}");
            }
            LogSupport.Log("Available methods of this name follow:");
            iter = IntPtr.Zero;
            while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero)
            {
                if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName)
                {
                    continue;
                }

                // if(il2cpp_method_get_param_count(method) != argTypes.Length)
                // continue;

                var nParams = il2cpp_method_get_param_count(method);
                LogSupport.Log("Method starts");
                for (var i = 0; i < nParams; i++)
                {
                    var paramType = il2cpp_method_get_param(method, (uint)i);
                    var typeName  = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType));
                    LogSupport.Log($"    {typeName}");
                }

                return(method);
            }

            return(IntPtr.Zero);
        }