首页
社区
课程
招聘
[原创]Unity逆向获取组件通杀方案
发表于: 2022-7-11 02:30 29325

[原创]Unity逆向获取组件通杀方案

2022-7-11 02:30
29325

由于需要对Adnroid手游游合规检测,即需要识别游戏是否展示“游戏协议声明”,因此需要提取游戏组件内相关原生组件文本。
由于目前Android手游主要以Unity引擎为主,因此首先尝试切入Unity引擎,获取原生组件通杀方案。

首先Unity开发语言是C#,
但是由于起初C#生态并没有跨平台支持(真的瓜这决策...),然而Unity又需要跨平台,因此早年间,为了兼容C#和跨平台需求,Unity自己重写了一套C#解释引擎,并且完全支持原生C#语法。
C#作为虚拟机语言,原生是提供了“反射”功能,所以Unity引擎作为C#解释器,也必然支持反射功能,无论是使用mono编译还是il2cpp编译,他都会支持“反射”。

因此我们的突破点,便是这个“反射”。
使用反射,即可获取C#中任何类、字段、属性、方法等所有信息,因此也可以获取Unity组件信息,获取到组件实例信息,就可以对其做任何读写操作

同时反射机制,相对于使用其他的hook机制,反射可以为我们带来更强的通用性和版本兼容性。

由于目前很多游戏考虑到安全性问题,一般都使用相对安全点的“il2cpp”编译模式,因此接下来的案例,也是在il2cpp基础上做分析。

il2cpp是将C# IL(.net平台一种中间语言)转为C++并编译为native,因此这种模式下,反射接口和直接使用C#的反射接口使用方式不太一样,但是大致流程还是差不多。

所以接下来,主要是要找到和整理native模式下,函数的定位以及组合规则。

注意:以下有些备注可能不准确,可以作为意会和参考,因为确实有点词穷(理解不够深........),
另外以是伪代码,着重描述核心的底层接口脉络,详细代码,会放在最后。

以上就是读取一个组件,所涉及的核心接口,以及组合方式。
当然不同组件,还会有一些其他接口涉及,但是也是依葫芦画瓢,根据函数名字大概就能推断出什么含义。

既然能获取所有实例对象和信息,并且具备读写能力,那么理论上,可以基于这套思路完成无源码修改游戏,以及基于组件级的脚本点击...............
另外需要提取游戏内资源,此方案也可以绕过大部分加固......

这个方案是完全依赖多个关键函数的symbol,目前听说(没实际了解)一些加固厂商,会将这些symbol抹除,如果抹除就通过函数特诊码搜索函数位置,但是这样兼容性有个问题,准确性也是个问题.......

更多il2cpp反射api定义,在il2cpp-api-functions.h

il2cpp的结构体定义在il2cpp-class.h

完整源码项目文件是_agent.js
_agent.js中的UnityApi类,封装了一部分反射api。

_agent.js中的Example类是案例:
图片描述

Zygisk-Il2CppDumper

通过Zygisk-Il2CppDumper源码,偶然间看到相关代码,才获得灵感进一步深挖“反射”这条思路

百度网盘:

 
 
 
 
// 假定一个TextMeshProGUI实例对象
let text_mesh_pro_gui_instance;
 
// 获取进程域
// **核心函数:il2cpp_domain_get**
let domain = il2cpp_domain_get()
 
// 获取所有程序集。类似C#获取所有动态链接库(.dll)反射信息
// **核心函数:il2cpp_domain_get_assemblies**
let assmblies = il2cpp_domain_get_assemblies(domain)
let assembly_images=[];
for(let i=0;i<assmblies.size;i++){
    assm = assmblies[i];
    // **核心函数:il2cpp_assembly_get_image**
    images.add(il2cpp_assembly_get_image(assm))
}
 
// 获取指定程序集反射image对象
// **核心函数:il2cpp_image_get_name**
let target_assembly_image = assembly_images
    .filter(assembly_img=>il2cpp_image_get_name(assembly_img)=="Unity.TextMeshPro.dll")
    .pop()
 
// 通过C#内限定名,获取对象class反射信息
// TextMeshProGUI类型组件限定名是"TMPro.TextMeshProGUI",并属于"Unity.TextMeshPro.dll"程序集
// **核心函数:il2cpp_class_from_name**
let TextMeshPro_class = il2cpp_class_from_name(target_assembly_image,"TMPro","TextMeshProGUI")
 
// 获取文本字段反射信息
// TextMeshProGUI存储文本的字段是“m_text”
// **核心函数:il2cpp_class_get_field_from_name**
m_text_field = il2cpp_class_get_field_from_name(TextMeshPro_class,"m_text")
 
// 读取字段内容实例,实例是个结构体
// **核心函数:il2cpp_field_get_value_object**
let str_content_struct = il2cpp_field_get_value_object(m_text_field,text_mesh_pro_gui_instance);
 
// 读取结构体内字符串内容,这里就是获取最终C版本的字符串
// **核心函数:func_il2cpp_string_chars**
content_chars = func_il2cpp_string_chars(str_content_struct)
// 假定一个TextMeshProGUI实例对象
let text_mesh_pro_gui_instance;
 
// 获取进程域
// **核心函数:il2cpp_domain_get**
let domain = il2cpp_domain_get()
 
// 获取所有程序集。类似C#获取所有动态链接库(.dll)反射信息
// **核心函数:il2cpp_domain_get_assemblies**
let assmblies = il2cpp_domain_get_assemblies(domain)
let assembly_images=[];
for(let i=0;i<assmblies.size;i++){
    assm = assmblies[i];
    // **核心函数:il2cpp_assembly_get_image**
    images.add(il2cpp_assembly_get_image(assm))
}
 
// 获取指定程序集反射image对象
// **核心函数:il2cpp_image_get_name**
let target_assembly_image = assembly_images
    .filter(assembly_img=>il2cpp_image_get_name(assembly_img)=="Unity.TextMeshPro.dll")
    .pop()
 
// 通过C#内限定名,获取对象class反射信息
// TextMeshProGUI类型组件限定名是"TMPro.TextMeshProGUI",并属于"Unity.TextMeshPro.dll"程序集
// **核心函数:il2cpp_class_from_name**
let TextMeshPro_class = il2cpp_class_from_name(target_assembly_image,"TMPro","TextMeshProGUI")
 
// 获取文本字段反射信息
// TextMeshProGUI存储文本的字段是“m_text”
// **核心函数:il2cpp_class_get_field_from_name**
m_text_field = il2cpp_class_get_field_from_name(TextMeshPro_class,"m_text")
 
// 读取字段内容实例,实例是个结构体
// **核心函数:il2cpp_field_get_value_object**
let str_content_struct = il2cpp_field_get_value_object(m_text_field,text_mesh_pro_gui_instance);
 
// 读取结构体内字符串内容,这里就是获取最终C版本的字符串
// **核心函数:func_il2cpp_string_chars**
content_chars = func_il2cpp_string_chars(str_content_struct)
 
 
 
/**
 * android框架的so接口
 */
class AndroidApi {
    static #_self;
 
    /**
     * @returns {AndroidApi}
     */
    static get Api() {
        if (!this.#_self) {
            this.#_self = new AndroidApi();
        }
 
        return this.#_self;
    }
 
    /**
     * @param {InvocationListenerCallbacks} callback
     * @constructor
     */
    AttachDlopen(callback) {
        let android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
        if (android_dlopen_ext != null) {
            Interceptor.attach(android_dlopen_ext, callback);
            console.log("找到了 android_dlopen_ext");
        } else {
            console.error("未找到 android_dlopen_ext");
        }
 
        let dlopen = Module.findExportByName(null, "dlopen");
        if (dlopen != null) {
            Interceptor.attach(dlopen, callback);
            console.log("找到了 dlopen");
        } else {
            console.error("未找到 dlopen");
        }
    }
 
 
 
}
 
class UCommonUtil {
    static #_self;
 
    /**
     * @return {UCommonUtil}
     */
    static get Api() {
        if (this.#_self == null) {
            this.#_self = new UCommonUtil();
        }
        return this.#_self;
    }
 
    /**
     * 获取il2cpp里的迭代器
     * @return {NativePointer}
     */
    GetEmptyIter() {
        let iter = Memory.alloc(Process.pointerSize);
        iter.writePointer(NULL);
 
        return iter;
    }
}
 
class CommonUtil {
    static #_self;
 
    /**
     * @return {CommonUtil}
     */
    static get Api() {
        if (this.#_self == null) {
            this.#_self = new CommonUtil();
        }
        return this.#_self;
    }
 
    /**
     * 创建NativeFunction封装,用于少写两行代码,方便使用
     * @returns {NativeFunction}
     */
    NewNativeFunction(module, exportName, retType, argTypes) {
        let ptr = module.findExportByName(exportName);
        if (ptr == null) {
            console.error(`没有找到【${exportName}】`);
            return null;
        }
 
        console.log(`成功找到【${exportName}】`);
 
        return new NativeFunction(ptr, retType, argTypes);
    }
}
 
/**
 * unity il2cpp中的so接口
 */
 
class UnityApi {
    static #_il2cppName = "libil2cpp.so";
 
    static #_self;
 
    /**
     * @type {Module}
     */
    #_il2cppMoudle;
 
    #func_il2cpp_get_corlib = null;
 
    // class
    #func_il2cpp_class_from_name = null;
    #func_il2cpp_class_get_method_from_name = null;
    #func_il2cpp_class_get_namespace = null;
    #func_il2cpp_class_get_name = null;
    #func_il2cpp_class_get_type = null;
    #func_il2cpp_class_from_type = null;
    #func_il2cpp_class_get_field_from_name = null;
    #func_il2cpp_class_get_fields = null;
    #func_il2cpp_class_get_properties = null;
    #func_il2cpp_class_get_property_from_name = null;
    #func_il2cpp_class_get_image = null;
 
    // domain
    #func_il2cpp_domain_get = null;
    #func_il2cpp_domain_get_assemblies = null;
 
    // assembly
    #func_il2cpp_assembly_get_image = null;
 
    // image
    #func_il2cpp_image_get_name = null;
    #func_il2cpp_image_get_class_count = null;
    #func_il2cpp_image_get_class = null;
 
    // runtime
    #func_il2cpp_runtime_invoke = null;
 
    // type
    #func_il2cpp_type_get_type = null;
    #func_il2cpp_type_get_object = null;
    #func_il2cpp_type_get_class_or_element_class = null;
 
    // field
    #func_il2cpp_field_get_value_object = null;
    #func_il2cpp_field_get_name = null;
    #func_il2cpp_field_get_type = null;
 
    // property
    #func_il2cpp_property_get_get_method = null;
    #func_il2cpp_property_get_name = null;
 
    // object
    #func_il2cpp_object_get_size = null;
    #func_il2cpp_object_get_class = null;
 
    // string
    #func_il2cpp_string_chars = null;
 
    constructor() {
        this.#init();
    }
 
    /**
     * 由于Unity Il2cpp相关接口,需要在il2cpp处加载后,
     * 才能正常发现,所以需要先在合适的地方初始化,再后续使用
     * @constructor
     */
    static Init() {
        if (!this.#_self) {
            this.#_self = new UnityApi();
        }
    }
 
    /**
     * 静态暴露接口
     * @returns {UnityApi}
     */
    static get Api() {
        if (!this.#_self) {
            throw "UnityApi还未初始化"
        }
        return this.#_self;
    }
 
    //-----------------------------------------------------【API】-------------------------------------------------------------//
 
    /**
     * @return {NativePointer}
     */
    il2cpp_get_corlib() {
        return this.#func_il2cpp_get_corlib();
    }
 
    /**
     * 根据类的限定名,获取Type信息
     * @param image_p .dll基址
     * @param namespace 命名空间
     * @param name 类名
     * @returns {NativePointer}
     */
    il2cpp_class_from_name(image_p, namespace, name) {
        let ns = Memory.allocUtf8String(namespace);
        let className = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_from_name(image_p, ns, className);
    }
 
    /**
     * 通过class获取type
     * @param {NativePointer} klass
     * @return {NativePointer}
     */
    il2cpp_class_get_type(klass) {
        return this.#func_il2cpp_class_get_type(klass);
    }
 
    /**
     * 反射获取指定方法
     * @param {NativePointer} klass class句柄
     * @param {string} methodName 指定方法名
     * @param {number} argCount 参数个数
     * @return {NativePointer}
     */
    il2cpp_class_get_method_from_name(klass, methodName, argCount) {
        let methodNameP = Memory.allocUtf8String(methodName);
        return this.#func_il2cpp_class_get_method_from_name(klass, methodNameP, argCount);
    }
 
    /**
     * 获取class下所有字段
     * @param {NativePointer} klass
     * @return {Generator<*, void, *>}
     */
    * il2cpp_class_get_fields(klass) {
        let iter = UCommonUtil.Api.GetEmptyIter();
        while (true) {
            let result = this.#func_il2cpp_class_get_fields(klass, iter);
 
            if (result.valueOf() == 0) {
                break;
            }
 
            yield  result;
        }
    }
 
    /**
     * 获取进程域
     * @returns {NativePointer}
     */
    il2cpp_domain_get() {
        return this.#func_il2cpp_domain_get();
    }
 
    /**
     * 获取所有程序集的基址
     * @param domain
     * @return {{size:number,assemblies:any}} .dll数组(const Il2CppAssembly**)
     */
    il2cpp_domain_get_assemblies(domain) {
        let size = Memory.alloc(4);
        size.writeInt(0);
        let assemblies = this.#func_il2cpp_domain_get_assemblies(domain, size);
        return {
            size: size.readInt(),
            assemblies: assemblies
        }
    }
 
    /**
     * 获取.dll的句柄
     * @param assembly .dll信息指针
     * @return {NativePointer} .dll句柄
     */
    il2cpp_assembly_get_image(assembly) {
        return this.#func_il2cpp_assembly_get_image(assembly);
    }
 
    /**
     * 获取image的name
     * @param {NativePointer} image
     * @return {string} image的名字
     */
    il2cpp_image_get_name(image) {
        let result = this.#func_il2cpp_image_get_name(image);
        return result.readPointer().readCString();
    }
 
    /**
     * 获取.dll下有多少个class
     * @param {NativePointer} image .dll句柄
     * @return {number} class个数
     */
    il2cpp_image_get_class_count(image) {
        let result = this.#func_il2cpp_image_get_class_count(image);
        return result;
    }
 
    /**
     * 获取class
     * @param {NativePointer} image
     * @param {number} index
     * @return {NativePointer}
     */
    il2cpp_image_get_class(image, index) {
        return this.#func_il2cpp_image_get_class(image, index);
    }
 
    /**
     * 通过class获取作用域名
     * @param {NativePointer} klass
     * @return {string};
     */
    il2cpp_class_get_namespace(klass) {
        let result = this.#func_il2cpp_class_get_namespace(klass);
        let ns = ptr(result).readCString();
        return ns;
    }
 
    /**
     * 通过class获取名字
     * @param {NativePointer} klass
     * @return {string}
     */
    il2cpp_class_get_name(klass) {
        let result = this.#func_il2cpp_class_get_name(klass);
        return ptr(result).readCString();
    }
 
    /**
     * @param {NativePointer} klass
     * @return {NativePointer}
     */
    il2cpp_class_get_image(klass) {
        return this.#func_il2cpp_class_get_image(klass);
    }
 
    /**
     * 反射调用方法
     * @param {NativePointer} methodInfo 反射方法对象
     * @param {NativePointer} obj 方法所属实例,static为NULL
     * @param {NativePointer} params 参数数组
     * @param {NativePointer} exception 报错
     * @return {NativePointer}
     */
    il2cpp_runtime_invoke(methodInfo, obj, params, exception) {
        return this.#func_il2cpp_runtime_invoke(methodInfo, obj, params, exception);
    }
 
    /**
     * 获取class的TypeInfo信息
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_class_from_type(type) {
        return this.#func_il2cpp_class_from_type(type);
    }
 
    /**
     * @param {NativePointer} klass
     * @param {string} name
     * @return {NativePointer}
     */
    il2cpp_class_get_field_from_name(klass, name) {
        let nameP = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_get_field_from_name(klass, nameP);
    }
 
    /**
     * 读取字段的名字
     * @param {NativePointer} field
     * @return {string}
     */
    il2cpp_field_get_name(field) {
        let result = this.#func_il2cpp_field_get_name(field);
        return ptr(result).readCString();
    }
 
    /**
     * @param {NativePointer} field
     * @return {NativePointer}
     */
    il2cpp_field_get_type(field) {
        return this.#func_il2cpp_field_get_type(field);
    }
 
    /**
     * 获取class所有属性
     * @param {NativePointer} klass
     * @return {*}
     */
    * il2cpp_class_get_properties(klass) {
        let iter = UCommonUtil.Api.GetEmptyIter();
        while (true) {
            let result = this.#func_il2cpp_class_get_properties(klass, iter);
 
            if (result.valueOf() == 0) {
                break;
            }
 
            yield  result;
        }
    }
 
 
    /**
     * 通过名字,获取class指定属性
     * @param {NativePointer} klass
     * @param {string} name
     * @return {NativePointer}
     */
    il2cpp_class_get_property_from_name(klass, name) {
        let nameP = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_get_property_from_name(klass, nameP);
    }
 
    /**
     * @param {NativePointer} type
     * @return {number}
     */
    il2cpp_type_get_type(type) {
        return this.#func_il2cpp_type_get_type(type);
    }
 
    /**
     * 根据反射信息,创建Type对象(即C#中反射的核心对象类)
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_type_get_object(type) {
        return this.#func_il2cpp_type_get_object(type);
    }
 
    /**
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_type_get_class_or_element_class(type) {
        return this.#func_il2cpp_type_get_class_or_element_class(type);
    }
 
    /**
     * 反射读取字段值
     * @param {NativePointer} field
     * @param {NativePointer} obj
     * @return {NativePointer}
     */
    il2cpp_field_get_value_object(field, obj) {
        return this.#func_il2cpp_field_get_value_object(field, obj);
    }
 
    /**
     * 获取属性的get方法(及读取属性值行为)
     * @param {NativePointer} prop
     * @return {NativePointer}
     */
    il2cpp_property_get_get_method(prop) {
        return this.#func_il2cpp_property_get_get_method(prop);
    }
 
    /**
     * 获取属性名字
     * @param {NativePointer} prop
     * @return {NativePointer}
     */
    il2cpp_property_get_name(prop) {
        let result = this.#func_il2cpp_property_get_name(prop);
        return ptr(result).readCString();
    }
 
    /**
     * 获取对象大小
     * @param {NativePointer} obj
     * @return {number}
     */
    il2cpp_object_get_size(obj) {
        return this.#func_il2cpp_object_get_size(obj);
    }
 
    /**
     * @param {NativePointer} obj
     * @return {NativePointer}
     */
    il2cpp_object_get_class(obj) {
        return this.#func_il2cpp_object_get_class(obj);
    }
 
    /**
     * @param {NativePointer} str
     * @return {string}
     */
    func_il2cpp_string_chars(str) {
        let result = this.#func_il2cpp_string_chars(str);
        return ptr(result).readUtf16String();
    }
 
    //-----------------------------------------------------【Attach】-------------------------------------------------------------//
 
    /**
     * @param {InvocationListenerCallbacks} callback
     */
    Attach_il2cpp_get_corlib(callback) {
        let func = this.#_il2cppMoudle.findExportByName("il2cpp_get_corlib");
        Interceptor.attach(func, callback);
    }
 
    /**
     * @param {InvocationListenerCallbacks} callback
     */
    Attach_il2cpp_class_from_name(callback) {
        let func = this.#_il2cppMoudle.findExportByName("il2cpp_class_from_name");
        Interceptor.attach(func, callback);
    }
 
 
    /**
     * 初始化so函数
     */
    #init() {
        this.#_il2cppMoudle = Process.findModuleByName(UnityApi.#_il2cppName);
 
        if (!this.#_il2cppMoudle) {
            console.error("未发现il2cppModule");
            return;
        }
        // ---------------------------------------------------------------------------------//
 
        this.#func_il2cpp_get_corlib = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_get_corlib",
            "pointer",
            []);
 
        // class
        this.#func_il2cpp_class_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_from_name",
            "pointer",
            ["pointer", "pointer", "pointer"]);
        this.#func_il2cpp_class_get_method_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_method_from_name",
            "pointer",
            ["pointer", "pointer", "int"]);
        this.#func_il2cpp_class_get_namespace = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_namespace",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_name",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_from_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_from_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_field_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_field_from_name",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_fields = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_fields",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_properties = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_properties",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_property_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_property_from_name",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_object_get_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_object_get_class",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_image = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_image",
            "pointer",
            ["pointer"]);
 
        // domain
        this.#func_il2cpp_domain_get = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_domain_get",
            "pointer",
            []);
        this.#func_il2cpp_domain_get_assemblies = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_domain_get_assemblies",
            "pointer",
            ["pointer", "pointer"]);
 
        // assembly
        this.#func_il2cpp_assembly_get_image = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_assembly_get_image",
            "pointer",
            ["pointer"]);
 
        // image
        this.#func_il2cpp_image_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_name",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_image_get_class_count = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_class_count",
            "uint32",
            ["pointer"]);
        this.#func_il2cpp_image_get_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_class",
            "pointer",
            ["pointer", "uint32"]);
 
        // runtime
        this.#func_il2cpp_runtime_invoke = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_runtime_invoke",
            "pointer",
            ["pointer", "pointer", "pointer", "pointer"]);
 
        // type
        this.#func_il2cpp_type_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_type",
            "int",
            ["pointer"]);
        this.#func_il2cpp_type_get_object = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_object",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_field_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_type_get_class_or_element_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_class_or_element_class",
            "pointer",
            ["pointer"]);
 
        // field
        this.#func_il2cpp_field_get_value_object = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_value_object",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_field_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_name",
            "pointer",
            ["pointer"]);
 
        // property
        this.#func_il2cpp_property_get_get_method = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_property_get_get_method",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_property_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_property_get_name",
            "pointer",
            ["pointer"]);
 
        // object
        this.#func_il2cpp_object_get_size = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_object_get_size",
            "uint32",
            ["pointer"]);
 
        // string
        this.#func_il2cpp_string_chars = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_string_chars",
            "pointer",
            ["pointer"]);
        // ---------------------------------------------------------------------------------//
    }
 
 
}
 
/**
 * 懒加载包装类
 */
class Lazy {
    #_value = null;
 
    /**
     * @type {function ():*} value
     */
    #_lazyValue = null;
 
    /**
     * @param {*} this上下文
     * @param {function ():*} value 实例化对象的方法回调
     * @return {Lazy}
     */
    static New(context,value) {
        let lazy = new Lazy();
        lazy.Value = value.bind(context);
        return lazy;
    }
 
    /**
     * @param {function ():*} value
     */
    set Value(value) {
        this.#_lazyValue = value;
    }
 
    /**
     * @return {*}
     */
    get Value() {
        if (this.#_value == null) {
            this.#_value = this.#_lazyValue();
        }
 
        return this.#_value;
    }
}
 
class UMethodInfo {
    /**
     * @type {Lazy}
     */
    #_methodInfo = null;
 
    /**
     * @type {UnityApi}
     */
    #_unityApi = UnityApi.Api;
 
    /**
     * @param {
     *     {
     *         kalss:NativePointer,
     *         methodName:string
     *         argCount:number
     *     }
     * } input
     */
    constructor(input) {
        this.#_methodInfo = Lazy.New(this,() => {
            return this.#_unityApi.il2cpp_class_get_method_from_name(input.kalss,
                input.methodName,
                input.argCount);
        });
    }
 
    /**
     *
     * @param {NativePointer} args 参数数组
     * @param {NativePointer} obj 实例对象
     * @return {(NativePointer | *)}
     * @constructor
     */
    Invoke(obj, args) {
        let result = this.#_unityApi.il2cpp_runtime_invoke(this.#_methodInfo.Value,
            obj, args, NULL);
 
        return result;
    }
}
 
class UDomain {
    static #_self;
 
    /**
     * @type {NativePointer}
     */
    #_domain = null;
    /**
     * @type {{size:number,assemblies:any}}
     */
    #_assmblies = null;
    /**
     * @type {NativePointer[]}
     */
    #_assemblyImages = null;
 
    /**
     * @type {UnityApi}
     */
    #_unityApi = null;
 
    constructor() {
        this.#_unityApi = UnityApi.Api;
 
        this.#LoadDomain();
        this.#LoadAssemblies();
        this.#LoadAssemblyImages();
    }
 
    /**
     * @return {UDomain}
     */
    static get Api() {
        if (UDomain.#_self == null) {
            UDomain.#_self = new UDomain();
        }
 
        return UDomain.#_self;
    }
 
    /**
     * @return {NativePointer[]}
     */
    get AllAssemblyImages() {
        return this.#_assemblyImages;
    }
 
    /**
     * @param {string} name
     * @return {NativePointer}
     */
    GetAssemblyImageByName(name) {
        return this.#_assemblyImages
            .filter(image => this.#_unityApi.il2cpp_image_get_name(image) == name)
            .pop()
            .readPointer();
    }
 
    #LoadDomain() {
        this.#_domain = this.#_unityApi.il2cpp_domain_get();
    }
 
    #LoadAssemblies() {
        this.#_assmblies = this.#_unityApi.il2cpp_domain_get_assemblies(this.#_domain);
    }
 
    #LoadAssemblyImages() {
        let images = [...Array(this.#_assmblies.size).keys()]
            .map(value => ptr(this.#_assmblies.assemblies).add(Process.pointerSize * value))
            .map(assm => this.#_unityApi.il2cpp_assembly_get_image(assm));
 
        this.#_assemblyImages = images;
    }
}
 
/**
 * @readonly
 * @enum {string}
 */
const AssemblyName={
    UnityEngine:"UnityEngine.dll",
    UnityEngineUI:"UnityEngine.UI.dll",
    UnityTextMeshPro:"Unity.TextMeshPro.dll",
    UnityEngineCoreModule:"UnityEngine.CoreModule.dll"
};
 
class UnityUtil {
    static #_self = null;
 
    /**
     * @return {UnityUtil}
     */
    static get Api() {
        if (UnityUtil.#_self == null) {
            UnityUtil.#_self = new UnityUtil();
        }
 
        return UnityUtil.#_self;
    }
 
    /**
     * 获取Class
     * @param {
     *     {
     *         domain:UDomain,
     *         assemblyName:string,
     *         namespace:string,
     *         klassName:string,
     *     }
     * } input
     * @return {NativePointer}
     */
    GetClass(input) {
        let assemblyImage = input.domain.GetAssemblyImageByName(input.assemblyName);
        let klass = UnityApi.Api.il2cpp_class_from_name(assemblyImage, input.namespace, input.klassName);
        return klass;
    }
 
    /**
     * 获取指定类的Type实例
     * @param {
     *     {
     *         klass:NativePointer
     *     }
     * } input
     * @return {NativePointer}
     */
    GetTypeObj(input) {
        let type = UnityApi.Api.il2cpp_class_get_type(input.klass);
        let typeObj = UnityApi.Api.il2cpp_type_get_object(type);
        return typeObj;
    }
 
    /**
     * 反射读取字符串类型字段的值
     * @param {NativePointer} field
     * @param {NativePointer} obj
     * @return {string}
     */
    ReadFieldWithString(field, obj) {
        let valueObj = UnityApi.Api.il2cpp_field_get_value_object(field, obj);
        let valueReal = UnityApi.Api.func_il2cpp_string_chars(valueObj);
        return valueReal;
    }
 
    /**
     * 反射读取字符串类型属性值
     * @param {NativePointer} property
     * @param {NativePointer} obj
     */
    ReadPropertyWithString(property, obj) {
        let getFunc = UnityApi.Api.il2cpp_property_get_get_method(property);
        let valueObj = UnityApi.Api.il2cpp_runtime_invoke(getFunc, obj, NULL, NULL);
        let valueReal = UnityApi.Api.func_il2cpp_string_chars(valueObj);
        return valueReal;
    }
 
}
 
class ReflectionInfoInput {
    dllName;
    namespace;
    className;
    constructor(dllName,namespace,className) {
        this.dllName = dllName;
        this.namespace = namespace;
        this.className = className;
    }
}
 
class ReflectionBase {
    get UApi(){
        return UnityApi.Api;
    }
 
    /**
     *
     * @return {function(): UDomain}
     * @constructor
     */
    get Domain(){
        return UDomain.Api;
    }
}
 
class UReflectionInfo extends ReflectionBase {
    /**
     * @type {ReflectionInfoInput}
     */
    #_input = null;
 
    /**
     * 实例对象
     * @type {NativePointer}
     */
    #_instanceObj = null;
 
    /**
     * @type {Lazy}
     */
    #_assemblyImage = null;
 
    /**
     * @type {Lazy}
     */
    #_class = null;
 
    /**
     * @type {Lazy}
     */
    #_type = null;
 
    /**
     * @type {Lazy}
     */
    #_fields = null;
 
    /**
     * @type {Lazy}
     */
    #_properties = null;
 
    /**
     * @param {ReflectionInfoInput | NativePointer} input
     */
    constructor(input) {
        super();
 
        if (input instanceof ReflectionInfoInput) {
            this.#_input = input;
        }
 
        if (input instanceof NativePointer) {
            this.#_instanceObj = input;
        }
 
        this.#LoadInit();
    }
 
    /**
     * @return {NativePointer}
     */
    get Class() {
        return this.#_class.Value;
    }
 
    get Type() {
        return this.#_type.Value;
    }
 
    get Fields() {
        return this.#_fields.Value;
    }
 
    get Properties() {
        return this.#_properties.Value;
    }
 
    PropertyByName(name) {
        return this.UApi.il2cpp_class_get_property_from_name(this.Class, name);
    }
 
    /**
     * @param {string} name
     * @return {NativePointer}
     */
    FieldByName(name) {
        return this.UApi.il2cpp_class_get_field_from_name(this.Class, name);
    }
 
    /**
     * @param name 方法名字
     * @param argCount 方法个数
     * @return {UMethodInfo}
     */
    MethodByName(name, argCount) {
        return new UMethodInfo({
            kalss: this.#_class.Value,
            methodName: name,
            argCount: argCount
        })
    }
 
 
    #LoadInit() {
        this.#Switch({
            objNotNull: this.#LoadClassByObj,
            inputNotNull: this.#LoadClassByName
        });
 
        this.#LoadAssemblyImage();
        this.#LoadType();
        this.#LoadFields();
        this.#LoadProperties();
    }
 
    /**
     * @param {
     *     {
     *         objNotNull:function ():*,
     *         inputNotNull:function ():*
     *     }
     * } input
     * @return {*}
     */
    #Switch(input) {
        if (this.#_instanceObj != null) {
            return input.objNotNull.call(this);
        }
 
        if (this.#_input != null) {
            return input.inputNotNull.call(this);
        }
    }
 
    #LoadAssemblyImage() {
        this.#_assemblyImage = this.#Switch({
            objNotNull: () => Lazy.New(this, () => this.UApi.il2cpp_class_get_image(this.Class)),
            inputNotNull: () => Lazy.New(this, () => this.Domain.GetAssemblyImageByName(this.#_input.dllName)),
        });
    }
 
    #LoadClassByObj() {
        this.#_class = Lazy.New(this, () => this.UApi.il2cpp_object_get_class(this.#_instanceObj));
    }
 
    #LoadClassByName() {
        this.#_class = Lazy.New(this, () => this.UApi.il2cpp_class_from_name(this.#_assemblyImage.Value,
            this.#_input.namespace,
            this.#_input.className)
        );
    }
 
    #LoadType() {
        this.#_type = Lazy.New(this, () => {
            let type = this.UApi.il2cpp_class_get_type(this.Class);
            return this.UApi.il2cpp_type_get_object(type);
        });
    }
 
    #LoadFields() {
        this.#_fields = Lazy.New(this, () => [...this.UApi.il2cpp_class_get_fields(this.Class)]);
    }
 
    #LoadProperties() {
        this.#_properties = Lazy.New(this, () => [...this.UApi.il2cpp_class_get_properties(this.Class)]);
    }
}
 
/*
    类型反射信息定义
    (在此处定义好类型的反射信息,需要某类型反射信息可方便使用)
 */
class UTypeDefinition {
    static #_self;
 
    #_u_object = new UReflectionInfo(new ReflectionInfoInput(
        AssemblyName.UnityEngine,
        "UnityEngine",
        "Object"));
 
    #_u_Behaviour = new UReflectionInfo(new ReflectionInfoInput(
        AssemblyName.UnityEngine,
        "UnityEngine",
        "Behaviour"
    ));
 
    #_u_UI_Text = new UReflectionInfo(new ReflectionInfoInput(
        AssemblyName.UnityEngineUI,
        "UnityEngine.UI",
        "Text"
    ));
 
    #_u_TextMeshProUGUI = new UReflectionInfo(new ReflectionInfoInput(
        AssemblyName.UnityTextMeshPro,
        "TMPro",
        "TextMeshProUGUI"
    ));
 
    #_u_Resources = new UReflectionInfo(new ReflectionInfoInput(
        AssemblyName.UnityEngineCoreModule,
        "UnityEngine",
        "Resources"
    ));
 
    /**
     * @return {UTypeDefinition}
     */
    static get Api() {
        if (UTypeDefinition.#_self == null) {
            UTypeDefinition.#_self = new UTypeDefinition();
        }
        return UTypeDefinition.#_self;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get U_Object() {
        return this.#_u_object;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get U_Behaviour() {
        return this.#_u_Behaviour;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get U_UI_Text() {
        return this.#_u_UI_Text;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get U_TextMeshProUGUI() {
        return this.#_u_TextMeshProUGUI;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get U_Resources() {
        return this.#_u_Resources;
    }
}
 
class UObject {
    /**
     * @type {Domain}
     */
     #_domain = UDomain.Api;
 
    /**
     * @type {UnityApi}
     */
    #_unityApi = UnityApi.Api;
 
    /**
     * @type {NativePointer}
     */
    #_obj = null;
 
    /**
     * 实例对象的class
     * @type {UReflectionInfo}
     */
    #_instanceReflection = null;
 
    /**
     * @param {
     *     {
     *         obj:NativePointer,
     *     }
     * } input
     */
    constructor(input) {
        this.#_obj = input.obj;
        this.#LoadInstanceKlass(input.obj);
    }
 
    /**
     * 获取组件自定义ID名字
     * @return {string}
     */
    get IDName() {
        let property = this.#_unityApi.il2cpp_class_get_property_from_name(UTypeDefinition.Api.U_Object.Class, "name");
        let name = UnityUtil.Api.ReadPropertyWithString(property, this.#_obj);
        return name;
    }
 
    /**
     * 获取类型限定名字
     * @return {string}
     */
    get TypeName() {
        let namespace = this.#_unityApi.il2cpp_class_get_namespace(this.#_instanceReflection.Class);
        let className = this.#_unityApi.il2cpp_class_get_name(this.#_instanceReflection.Class);
        return `${namespace}.${className}`;
    }
 
    /**
     * @return {UReflectionInfo}
     */
    get InstanceReflection() {
        return this.#_instanceReflection;
    }
 
    /**
     * @return {UnityApi}
     */
    get UApi() {
        return this.#_unityApi;
    }
 
    /**
     * @return {Domain}
     */
    get Domain() {
        return this.#_domain;
    }
 
    /**
     * @return {NativePointer}
     */
    get ObjInstance() {
        return this.#_obj;
    }
 
    #LoadInstanceKlass() {
        this.#_instanceReflection = new UReflectionInfo(this.#_obj);
    }
}
 
class UBehavior extends UObject {
    /**
     *
     * @param {
     *     {
     *         obj:NativePointer
     *     }
     * } input
     */
    constructor(input) {
        super(input);
    }
}
 
class UTextMeshProUGUI extends UObject {
    /**
     * @param {
     *     {
     *         obj:NativePointer
     *     }
     * } input
     */
    constructor(input) {
        super(input);
    }
 
    /**
     * @return {string}
     */
    get TextContent() {
        let field = UTypeDefinition.Api.U_TextMeshProUGUI.FieldByName("m_text");
        let content = UnityUtil.Api.ReadFieldWithString(field, this.ObjInstance);
        return content;
    }
}
 
class UServiceBase {
    /**
     * @type {UDomain}
     */
    #_domain = UDomain.Api;
 
    /**
     * @type {UnityApi}
     */
    #_UApi = UnityApi.Api;
 
    get UApi() {
        return this.#_UApi;
    }
 
    get Domain() {
        return this.#_domain;
    }
}
 
class UIText extends UObject {
    /**
     * @param {
     *     {
     *         obj:NativePointer,
     *     }
     * } input
     */
    constructor(input) {
        super(input);
    }
 
    /**
     * @return {string}
     */
    get TextContent(){
        let property = UTypeDefinition.Api.U_UI_Text.PropertyByName("text");
        let content = UnityUtil.Api.ReadPropertyWithString(property, this.ObjInstance);
        return content;
    }
}
 
/**
 * 搜索功能封装
 */
class UFind extends UServiceBase {
    /**
     * @type {UMethodInfo}
     */
    #_findObjectsOfType = null
 
    constructor() {
        super();
        this.#LoadFindObjectsOfType();
    }
 
    /**
     * 获取当前界面的所有控件元素
     * @return {UBehavior[]}
     */
    GetCurrentAllComponent() {
        let components = this.#FindObjectsOfType(UTypeDefinition.Api.U_Behaviour.Type);
        let behaviors = components
            .map(obj => new UBehavior({
                obj: obj
            }));
 
        // for (const behavior of behaviors) {
        //     console.log(`behavior.TypeName:${behavior.TypeName}`);
        // }
        //
        // console.log("----------------------")
        //
        // for (let behavior of behaviors) {
        //     console.log(`ID Name:${behavior.IDName}--`);
        // }
 
        return behaviors;
    }
 
    /**
     * @return {UTextMeshProUGUI[]}
     */
    GetCurrentComponentByTextMeshProUGUI() {
        let objs = this.#FindObjectsOfType(UTypeDefinition.Api.U_TextMeshProUGUI.Type);
        let tmps = objs.map(value => new UTextMeshProUGUI({
            obj: value
        }));
 
        // console.log(`tmps个数:${tmps.length}`)
        //
        // for (let elem of tmps) {
        //     console.log(`tmp text:${elem.TextContent}`);
        // }
 
        return tmps;
    }
 
    /**
     * @return {UIText[]}
     */
    GetCurrentComponentByText() {
        let objs = this.#FindObjectsOfType(UTypeDefinition.Api.U_UI_Text.Type);
        let texts = objs.map(value => new UIText({
            obj: value
        }));
 
        // console.log(`UI_Text个数:${texts.length}`)
        //
        // for (let elem of texts) {
        //     console.log(`ui text:${elem.TextContent}`);
        // }
 
        return texts;
    }
 
    /**
     * 获取指定类型的所有子类元素
     * @param {NativePointer} obj 实例对象
     * @param {NativePointer} type 类型Type信息
     * @return {NativePointer[]}
     */
    #FindObjectsOfType(type) {
        // 构建装参数指针的数组
        let argArr = Memory.alloc(Process.pointerSize);
        argArr.writePointer(type);
 
        let result = this.#_findObjectsOfType.Invoke(NULL, argArr);
 
        // 读取数组长度
        let length = result.add(Process.pointerSize * 3).readInt();
        // 读取元素数组头
        let elemArr = result.add(Process.pointerSize * 4);
 
        let objArr = [...Array(length).keys()]
            // 读取数组元素
            .map(value => ptr(elemArr).add(Process.pointerSize * value).readPointer());
 
        return objArr;
    }
 
    #LoadFindObjectsOfType() {
        this.#_findObjectsOfType= UTypeDefinition.Api.U_Resources.MethodByName("FindObjectsOfTypeAll",
            1);
 
    }
}
 
class AndroidApplicationContext {
    static #_self = null;
 
    #_context = null;
 
 
    constructor() {
        this.#LoadContext();
    }
 
    /**
     * @return {AndroidApplicationContext}
     */
    static get Api() {
        if (AndroidApplicationContext.#_self == null) {
            AndroidApplicationContext.#_self = new AndroidApplicationContext();
        }
 
        return AndroidApplicationContext.#_self;
    }
 
    /**
     * 获取路径结果:/data/app/包名+随机数/xx.apk
     * @return {string}
     */
    get getPackageCodePath() {
        return this.#_context.getPackageCodePath().value;
    }
 
    /**
     * @return {string}
     */
    get nativeLibraryDir() {
        return this.#_context.getApplicationInfo().nativeLibraryDir.value;
    }
 
 
    #LoadContext() {
        let activityThread = Java.use("android.app.ActivityThread");
        let currentApplication = activityThread.currentApplication();
        this.#_context = currentApplication.getApplicationContext();
    }
}
 
class AndroidFile {
    #_file = null;
    #_absPath = null;
 
    constructor(absPath) {
        this.#_absPath = absPath;
 
        let fileClass = Java.use("java.io.File");
        this.#_file = fileClass.$new(absPath);
    }
 
    /**
     * @return {boolean}
     */
    exists() {
        return this.#_file.exists();
    }
}
 
class UnityEngine {
    /**
     * @type {Find}
     */
    #_find;
 
    /**
     * 判断是否是Unity引擎的游戏
     * @param {function (boolean)} callback
     */
    IsUnity(callback) {
        // 此处如果不使用延迟加载,会很大概率出现无法找到context
        setTimeout(() => {
            // 直接读取apk文件夹是否有libil2cpp.so判断是否unity游戏
            let nativeLibraryDir = AndroidApplicationContext.Api.nativeLibraryDir;
            let file = new AndroidFile(`${nativeLibraryDir}/libil2cpp.so`);
            callback(file.exists());
        }, 1000);
    }
 
    /**
     * Unity引擎初始化
     * @param {function (UnityEngine)} onComplete 初始化完成后回调
     */
    Init(onComplete) {
        let that = this;
 
        let modules = Process.enumerateModules();
        let haveIl2Cpp = modules.find(value => value.name == "libil2cpp.so");
 
        // 先遍历内存,是否有il2cpp.so,没有就hook dlopen
        if (haveIl2Cpp) {
            this.#Load(onComplete);
        } else {
            // hook so加载节点
            AndroidApi.Api.AttachDlopen({
                onEnter(args) {
                    let soPath = args[0].readCString();
                    // 判断加载文件是否存在libil2cpp.so,如果存在,接下来hook该so相关东西
                    this.haveIl2cpp = soPath.endsWith("libil2cpp.so");
                },
                onLeave(rv) {
                    if (!this.haveIl2cpp)
                        return;
 
                    // 发现il2cpp.so加载,延迟一小会再加载,避免so无法找到
                    setTimeout(() => {
                        that.#Load(onComplete);
                    }, 2000);
                }
            });
        }
    }
 
    /**
     * @return {UFind}
     */
    get Find() {
        return this.#_find;
    }
 
    #Load(onComplete) {
        UnityApi.Init();
        this.#_find = new UFind();
 
        onComplete(this);
    }
}
 
class EngineManager {
    /**
     * @return {UnityEngine}
     */
    static GetUnityEngine(){
        return new UnityEngine();
    }
}
 
// 初始化成功后,在frida cli中调用样例
// Example.Print_CurrentAllComponent()
// Example.Print_CurrentComponentByTextMeshProUGUI()
// Example.Print_CurrentComponentByText()
 
class Example {
    static #_unityEngine = null;
 
    /**
     * 方便明亮行调用,所以此处设置一个静态属性
     * @return {UnityEngine}
     */
    static get UnityEngine() {
        return Example.#_unityEngine;
    }
 
    /**
     * 初始化成功后,在frida cli中调用样例
     * Example.Print_CurrentAllComponent()
     */
    static Print_CurrentAllComponent(){
        let uBehaviors = Example.UnityEngine.Find.GetCurrentAllComponent();
        for (let item of uBehaviors) {
            console.log(`组件类型名字:${item.TypeName}---组件ID名:${item.IDName}`);
        }
        console.log(`Behavior子类个数:${uBehaviors.length}`);
    }
 
    /**
     * 初始化成功后,在frida cli中调用样例
     * Example.Print_CurrentComponentByTextMeshProUGUI()
     */
    static Print_CurrentComponentByTextMeshProUGUI(){
        let uTextMeshProUGUIS = Example.UnityEngine.Find.GetCurrentComponentByTextMeshProUGUI();
        for (let item of uTextMeshProUGUIS) {
            console.log(`TextMeshProUGUI文本内容:【${item.TextContent}】`);
        }
        console.log(`TextMeshProUGUI子类个数:${uTextMeshProUGUIS.length}`);
 
    }
 
    /**
     * 初始化成功后,在frida cli中调用样例
     * Example.Print_CurrentComponentByText()
     */
    static Print_CurrentComponentByText(){
        let uiTexts =  Example.UnityEngine.Find.GetCurrentComponentByText();
        for (let item of uiTexts) {
            console.log(`Text组件内容:【${item.TextContent}】`);
        }
        console.log(`UIText子类个数:${uiTexts.length}`);
    }
 
    Entry() {
        // 使用样例
        let unityEngine = EngineManager.GetUnityEngine();
 
        unityEngine.IsUnity(isUnity=>{
            if (!isUnity)
            {
                console.error("此游戏非Unity引擎游戏");
                return ;
            }
            console.log("此游戏是Unity引擎游戏");
 
            unityEngine.Init(engine => {
                console.log("初始化成功!!");
                Example.#_unityEngine = engine;
            });
        });
    }
}
 
/**
 * 编译脚本入口。
 * 所有js脚本,全部自动编译整合进入"_agent.js"
 */
function main(){
    console.log("frida  main代码快进入执行了");
    Java.perform(() => {
        console.log("frida  perform代码快进入执行了");
 
        if (!Java.available) {
            console.log("Frida服务没有启动,取消执行");
        }
 
        let example = new Example();
        example.Entry();
    });
}
 
main();
/**
 * android框架的so接口
 */
class AndroidApi {
    static #_self;
 
    /**
     * @returns {AndroidApi}
     */
    static get Api() {
        if (!this.#_self) {
            this.#_self = new AndroidApi();
        }
 
        return this.#_self;
    }
 
    /**
     * @param {InvocationListenerCallbacks} callback
     * @constructor
     */
    AttachDlopen(callback) {
        let android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
        if (android_dlopen_ext != null) {
            Interceptor.attach(android_dlopen_ext, callback);
            console.log("找到了 android_dlopen_ext");
        } else {
            console.error("未找到 android_dlopen_ext");
        }
 
        let dlopen = Module.findExportByName(null, "dlopen");
        if (dlopen != null) {
            Interceptor.attach(dlopen, callback);
            console.log("找到了 dlopen");
        } else {
            console.error("未找到 dlopen");
        }
    }
 
 
 
}
 
class UCommonUtil {
    static #_self;
 
    /**
     * @return {UCommonUtil}
     */
    static get Api() {
        if (this.#_self == null) {
            this.#_self = new UCommonUtil();
        }
        return this.#_self;
    }
 
    /**
     * 获取il2cpp里的迭代器
     * @return {NativePointer}
     */
    GetEmptyIter() {
        let iter = Memory.alloc(Process.pointerSize);
        iter.writePointer(NULL);
 
        return iter;
    }
}
 
class CommonUtil {
    static #_self;
 
    /**
     * @return {CommonUtil}
     */
    static get Api() {
        if (this.#_self == null) {
            this.#_self = new CommonUtil();
        }
        return this.#_self;
    }
 
    /**
     * 创建NativeFunction封装,用于少写两行代码,方便使用
     * @returns {NativeFunction}
     */
    NewNativeFunction(module, exportName, retType, argTypes) {
        let ptr = module.findExportByName(exportName);
        if (ptr == null) {
            console.error(`没有找到【${exportName}】`);
            return null;
        }
 
        console.log(`成功找到【${exportName}】`);
 
        return new NativeFunction(ptr, retType, argTypes);
    }
}
 
/**
 * unity il2cpp中的so接口
 */
 
class UnityApi {
    static #_il2cppName = "libil2cpp.so";
 
    static #_self;
 
    /**
     * @type {Module}
     */
    #_il2cppMoudle;
 
    #func_il2cpp_get_corlib = null;
 
    // class
    #func_il2cpp_class_from_name = null;
    #func_il2cpp_class_get_method_from_name = null;
    #func_il2cpp_class_get_namespace = null;
    #func_il2cpp_class_get_name = null;
    #func_il2cpp_class_get_type = null;
    #func_il2cpp_class_from_type = null;
    #func_il2cpp_class_get_field_from_name = null;
    #func_il2cpp_class_get_fields = null;
    #func_il2cpp_class_get_properties = null;
    #func_il2cpp_class_get_property_from_name = null;
    #func_il2cpp_class_get_image = null;
 
    // domain
    #func_il2cpp_domain_get = null;
    #func_il2cpp_domain_get_assemblies = null;
 
    // assembly
    #func_il2cpp_assembly_get_image = null;
 
    // image
    #func_il2cpp_image_get_name = null;
    #func_il2cpp_image_get_class_count = null;
    #func_il2cpp_image_get_class = null;
 
    // runtime
    #func_il2cpp_runtime_invoke = null;
 
    // type
    #func_il2cpp_type_get_type = null;
    #func_il2cpp_type_get_object = null;
    #func_il2cpp_type_get_class_or_element_class = null;
 
    // field
    #func_il2cpp_field_get_value_object = null;
    #func_il2cpp_field_get_name = null;
    #func_il2cpp_field_get_type = null;
 
    // property
    #func_il2cpp_property_get_get_method = null;
    #func_il2cpp_property_get_name = null;
 
    // object
    #func_il2cpp_object_get_size = null;
    #func_il2cpp_object_get_class = null;
 
    // string
    #func_il2cpp_string_chars = null;
 
    constructor() {
        this.#init();
    }
 
    /**
     * 由于Unity Il2cpp相关接口,需要在il2cpp处加载后,
     * 才能正常发现,所以需要先在合适的地方初始化,再后续使用
     * @constructor
     */
    static Init() {
        if (!this.#_self) {
            this.#_self = new UnityApi();
        }
    }
 
    /**
     * 静态暴露接口
     * @returns {UnityApi}
     */
    static get Api() {
        if (!this.#_self) {
            throw "UnityApi还未初始化"
        }
        return this.#_self;
    }
 
    //-----------------------------------------------------【API】-------------------------------------------------------------//
 
    /**
     * @return {NativePointer}
     */
    il2cpp_get_corlib() {
        return this.#func_il2cpp_get_corlib();
    }
 
    /**
     * 根据类的限定名,获取Type信息
     * @param image_p .dll基址
     * @param namespace 命名空间
     * @param name 类名
     * @returns {NativePointer}
     */
    il2cpp_class_from_name(image_p, namespace, name) {
        let ns = Memory.allocUtf8String(namespace);
        let className = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_from_name(image_p, ns, className);
    }
 
    /**
     * 通过class获取type
     * @param {NativePointer} klass
     * @return {NativePointer}
     */
    il2cpp_class_get_type(klass) {
        return this.#func_il2cpp_class_get_type(klass);
    }
 
    /**
     * 反射获取指定方法
     * @param {NativePointer} klass class句柄
     * @param {string} methodName 指定方法名
     * @param {number} argCount 参数个数
     * @return {NativePointer}
     */
    il2cpp_class_get_method_from_name(klass, methodName, argCount) {
        let methodNameP = Memory.allocUtf8String(methodName);
        return this.#func_il2cpp_class_get_method_from_name(klass, methodNameP, argCount);
    }
 
    /**
     * 获取class下所有字段
     * @param {NativePointer} klass
     * @return {Generator<*, void, *>}
     */
    * il2cpp_class_get_fields(klass) {
        let iter = UCommonUtil.Api.GetEmptyIter();
        while (true) {
            let result = this.#func_il2cpp_class_get_fields(klass, iter);
 
            if (result.valueOf() == 0) {
                break;
            }
 
            yield  result;
        }
    }
 
    /**
     * 获取进程域
     * @returns {NativePointer}
     */
    il2cpp_domain_get() {
        return this.#func_il2cpp_domain_get();
    }
 
    /**
     * 获取所有程序集的基址
     * @param domain
     * @return {{size:number,assemblies:any}} .dll数组(const Il2CppAssembly**)
     */
    il2cpp_domain_get_assemblies(domain) {
        let size = Memory.alloc(4);
        size.writeInt(0);
        let assemblies = this.#func_il2cpp_domain_get_assemblies(domain, size);
        return {
            size: size.readInt(),
            assemblies: assemblies
        }
    }
 
    /**
     * 获取.dll的句柄
     * @param assembly .dll信息指针
     * @return {NativePointer} .dll句柄
     */
    il2cpp_assembly_get_image(assembly) {
        return this.#func_il2cpp_assembly_get_image(assembly);
    }
 
    /**
     * 获取image的name
     * @param {NativePointer} image
     * @return {string} image的名字
     */
    il2cpp_image_get_name(image) {
        let result = this.#func_il2cpp_image_get_name(image);
        return result.readPointer().readCString();
    }
 
    /**
     * 获取.dll下有多少个class
     * @param {NativePointer} image .dll句柄
     * @return {number} class个数
     */
    il2cpp_image_get_class_count(image) {
        let result = this.#func_il2cpp_image_get_class_count(image);
        return result;
    }
 
    /**
     * 获取class
     * @param {NativePointer} image
     * @param {number} index
     * @return {NativePointer}
     */
    il2cpp_image_get_class(image, index) {
        return this.#func_il2cpp_image_get_class(image, index);
    }
 
    /**
     * 通过class获取作用域名
     * @param {NativePointer} klass
     * @return {string};
     */
    il2cpp_class_get_namespace(klass) {
        let result = this.#func_il2cpp_class_get_namespace(klass);
        let ns = ptr(result).readCString();
        return ns;
    }
 
    /**
     * 通过class获取名字
     * @param {NativePointer} klass
     * @return {string}
     */
    il2cpp_class_get_name(klass) {
        let result = this.#func_il2cpp_class_get_name(klass);
        return ptr(result).readCString();
    }
 
    /**
     * @param {NativePointer} klass
     * @return {NativePointer}
     */
    il2cpp_class_get_image(klass) {
        return this.#func_il2cpp_class_get_image(klass);
    }
 
    /**
     * 反射调用方法
     * @param {NativePointer} methodInfo 反射方法对象
     * @param {NativePointer} obj 方法所属实例,static为NULL
     * @param {NativePointer} params 参数数组
     * @param {NativePointer} exception 报错
     * @return {NativePointer}
     */
    il2cpp_runtime_invoke(methodInfo, obj, params, exception) {
        return this.#func_il2cpp_runtime_invoke(methodInfo, obj, params, exception);
    }
 
    /**
     * 获取class的TypeInfo信息
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_class_from_type(type) {
        return this.#func_il2cpp_class_from_type(type);
    }
 
    /**
     * @param {NativePointer} klass
     * @param {string} name
     * @return {NativePointer}
     */
    il2cpp_class_get_field_from_name(klass, name) {
        let nameP = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_get_field_from_name(klass, nameP);
    }
 
    /**
     * 读取字段的名字
     * @param {NativePointer} field
     * @return {string}
     */
    il2cpp_field_get_name(field) {
        let result = this.#func_il2cpp_field_get_name(field);
        return ptr(result).readCString();
    }
 
    /**
     * @param {NativePointer} field
     * @return {NativePointer}
     */
    il2cpp_field_get_type(field) {
        return this.#func_il2cpp_field_get_type(field);
    }
 
    /**
     * 获取class所有属性
     * @param {NativePointer} klass
     * @return {*}
     */
    * il2cpp_class_get_properties(klass) {
        let iter = UCommonUtil.Api.GetEmptyIter();
        while (true) {
            let result = this.#func_il2cpp_class_get_properties(klass, iter);
 
            if (result.valueOf() == 0) {
                break;
            }
 
            yield  result;
        }
    }
 
 
    /**
     * 通过名字,获取class指定属性
     * @param {NativePointer} klass
     * @param {string} name
     * @return {NativePointer}
     */
    il2cpp_class_get_property_from_name(klass, name) {
        let nameP = Memory.allocUtf8String(name);
        return this.#func_il2cpp_class_get_property_from_name(klass, nameP);
    }
 
    /**
     * @param {NativePointer} type
     * @return {number}
     */
    il2cpp_type_get_type(type) {
        return this.#func_il2cpp_type_get_type(type);
    }
 
    /**
     * 根据反射信息,创建Type对象(即C#中反射的核心对象类)
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_type_get_object(type) {
        return this.#func_il2cpp_type_get_object(type);
    }
 
    /**
     * @param {NativePointer} type
     * @return {NativePointer}
     */
    il2cpp_type_get_class_or_element_class(type) {
        return this.#func_il2cpp_type_get_class_or_element_class(type);
    }
 
    /**
     * 反射读取字段值
     * @param {NativePointer} field
     * @param {NativePointer} obj
     * @return {NativePointer}
     */
    il2cpp_field_get_value_object(field, obj) {
        return this.#func_il2cpp_field_get_value_object(field, obj);
    }
 
    /**
     * 获取属性的get方法(及读取属性值行为)
     * @param {NativePointer} prop
     * @return {NativePointer}
     */
    il2cpp_property_get_get_method(prop) {
        return this.#func_il2cpp_property_get_get_method(prop);
    }
 
    /**
     * 获取属性名字
     * @param {NativePointer} prop
     * @return {NativePointer}
     */
    il2cpp_property_get_name(prop) {
        let result = this.#func_il2cpp_property_get_name(prop);
        return ptr(result).readCString();
    }
 
    /**
     * 获取对象大小
     * @param {NativePointer} obj
     * @return {number}
     */
    il2cpp_object_get_size(obj) {
        return this.#func_il2cpp_object_get_size(obj);
    }
 
    /**
     * @param {NativePointer} obj
     * @return {NativePointer}
     */
    il2cpp_object_get_class(obj) {
        return this.#func_il2cpp_object_get_class(obj);
    }
 
    /**
     * @param {NativePointer} str
     * @return {string}
     */
    func_il2cpp_string_chars(str) {
        let result = this.#func_il2cpp_string_chars(str);
        return ptr(result).readUtf16String();
    }
 
    //-----------------------------------------------------【Attach】-------------------------------------------------------------//
 
    /**
     * @param {InvocationListenerCallbacks} callback
     */
    Attach_il2cpp_get_corlib(callback) {
        let func = this.#_il2cppMoudle.findExportByName("il2cpp_get_corlib");
        Interceptor.attach(func, callback);
    }
 
    /**
     * @param {InvocationListenerCallbacks} callback
     */
    Attach_il2cpp_class_from_name(callback) {
        let func = this.#_il2cppMoudle.findExportByName("il2cpp_class_from_name");
        Interceptor.attach(func, callback);
    }
 
 
    /**
     * 初始化so函数
     */
    #init() {
        this.#_il2cppMoudle = Process.findModuleByName(UnityApi.#_il2cppName);
 
        if (!this.#_il2cppMoudle) {
            console.error("未发现il2cppModule");
            return;
        }
        // ---------------------------------------------------------------------------------//
 
        this.#func_il2cpp_get_corlib = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_get_corlib",
            "pointer",
            []);
 
        // class
        this.#func_il2cpp_class_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_from_name",
            "pointer",
            ["pointer", "pointer", "pointer"]);
        this.#func_il2cpp_class_get_method_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_method_from_name",
            "pointer",
            ["pointer", "pointer", "int"]);
        this.#func_il2cpp_class_get_namespace = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_namespace",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_name",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_from_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_from_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_field_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_field_from_name",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_fields = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_fields",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_properties = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_properties",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_class_get_property_from_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_property_from_name",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_object_get_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_object_get_class",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_class_get_image = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_class_get_image",
            "pointer",
            ["pointer"]);
 
        // domain
        this.#func_il2cpp_domain_get = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_domain_get",
            "pointer",
            []);
        this.#func_il2cpp_domain_get_assemblies = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_domain_get_assemblies",
            "pointer",
            ["pointer", "pointer"]);
 
        // assembly
        this.#func_il2cpp_assembly_get_image = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_assembly_get_image",
            "pointer",
            ["pointer"]);
 
        // image
        this.#func_il2cpp_image_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_name",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_image_get_class_count = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_class_count",
            "uint32",
            ["pointer"]);
        this.#func_il2cpp_image_get_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_image_get_class",
            "pointer",
            ["pointer", "uint32"]);
 
        // runtime
        this.#func_il2cpp_runtime_invoke = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_runtime_invoke",
            "pointer",
            ["pointer", "pointer", "pointer", "pointer"]);
 
        // type
        this.#func_il2cpp_type_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_type",
            "int",
            ["pointer"]);
        this.#func_il2cpp_type_get_object = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_object",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_field_get_type = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_type",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_type_get_class_or_element_class = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_type_get_class_or_element_class",
            "pointer",
            ["pointer"]);
 
        // field
        this.#func_il2cpp_field_get_value_object = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_value_object",
            "pointer",
            ["pointer", "pointer"]);
        this.#func_il2cpp_field_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_field_get_name",
            "pointer",
            ["pointer"]);
 
        // property
        this.#func_il2cpp_property_get_get_method = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_property_get_get_method",
            "pointer",
            ["pointer"]);
        this.#func_il2cpp_property_get_name = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_property_get_name",
            "pointer",
            ["pointer"]);
 
        // object
        this.#func_il2cpp_object_get_size = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_object_get_size",
            "uint32",
            ["pointer"]);
 
        // string
        this.#func_il2cpp_string_chars = CommonUtil.Api.NewNativeFunction(this.#_il2cppMoudle, "il2cpp_string_chars",
            "pointer",
            ["pointer"]);
        // ---------------------------------------------------------------------------------//
    }
 
 
}
 
/**
 * 懒加载包装类
 */
class Lazy {
    #_value = null;
 
    /**
     * @type {function ():*} value
     */
    #_lazyValue = null;
 
    /**
     * @param {*} this上下文
     * @param {function ():*} value 实例化对象的方法回调
     * @return {Lazy}
     */
    static New(context,value) {
        let lazy = new Lazy();
        lazy.Value = value.bind(context);
        return lazy;
    }
 
    /**
     * @param {function ():*} value
     */
    set Value(value) {
        this.#_lazyValue = value;
    }
 
    /**
     * @return {*}
     */
    get Value() {
        if (this.#_value == null) {
            this.#_value = this.#_lazyValue();
        }
 
        return this.#_value;
    }
}
 
class UMethodInfo {
    /**
     * @type {Lazy}
     */
    #_methodInfo = null;
 
    /**
     * @type {UnityApi}
     */
    #_unityApi = UnityApi.Api;
 
    /**
     * @param {
     *     {
     *         kalss:NativePointer,
     *         methodName:string
     *         argCount:number
     *     }
     * } input
     */
    constructor(input) {
        this.#_methodInfo = Lazy.New(this,() => {
            return this.#_unityApi.il2cpp_class_get_method_from_name(input.kalss,
                input.methodName,
                input.argCount);
        });
    }
 
    /**
     *
     * @param {NativePointer} args 参数数组
     * @param {NativePointer} obj 实例对象
     * @return {(NativePointer | *)}
     * @constructor
     */
    Invoke(obj, args) {
        let result = this.#_unityApi.il2cpp_runtime_invoke(this.#_methodInfo.Value,
            obj, args, NULL);
 
        return result;
    }
}
 
class UDomain {
    static #_self;
 
    /**
     * @type {NativePointer}
     */
    #_domain = null;
    /**
     * @type {{size:number,assemblies:any}}
     */
    #_assmblies = null;
    /**
     * @type {NativePointer[]}
     */
    #_assemblyImages = null;
 
    /**
     * @type {UnityApi}
     */
    #_unityApi = null;
 
    constructor() {
        this.#_unityApi = UnityApi.Api;
 
        this.#LoadDomain();
        this.#LoadAssemblies();
        this.#LoadAssemblyImages();
    }
 
    /**
     * @return {UDomain}
     */
    static get Api() {
        if (UDomain.#_self == null) {
            UDomain.#_self = new UDomain();
        }
 
        return UDomain.#_self;
    }
 
    /**
     * @return {NativePointer[]}
     */
    get AllAssemblyImages() {
        return this.#_assemblyImages;
    }
 
    /**
     * @param {string} name
     * @return {NativePointer}
     */
    GetAssemblyImageByName(name) {
        return this.#_assemblyImages
            .filter(image => this.#_unityApi.il2cpp_image_get_name(image) == name)
            .pop()
            .readPointer();
    }
 
    #LoadDomain() {
        this.#_domain = this.#_unityApi.il2cpp_domain_get();
    }
 
    #LoadAssemblies() {
        this.#_assmblies = this.#_unityApi.il2cpp_domain_get_assemblies(this.#_domain);
    }
 
    #LoadAssemblyImages() {
        let images = [...Array(this.#_assmblies.size).keys()]
            .map(value => ptr(this.#_assmblies.assemblies).add(Process.pointerSize * value))
            .map(assm => this.#_unityApi.il2cpp_assembly_get_image(assm));
 
        this.#_assemblyImages = images;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-7-14 19:03 被憨豆爆发编辑 ,原因: 调整标题
收藏
免费 8
支持
分享
最新回复 (17)
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2022-7-11 08:50
1
雪    币: 2552
活跃值: (4423)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2022-7-11 10:13
1
雪    币: 6573
活跃值: (3873)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2022-7-20 09:30
0
雪    币: 6084
活跃值: (5490)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2022-7-20 10:11
0
雪    币: 8437
活跃值: (5031)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2022-7-20 12:20
0
雪    币: 761
活跃值: (628)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2022-7-22 10:13
0
雪    币: 61
活跃值: (200)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享
2022-7-22 11:02
0
雪    币: 242
活跃值: (468)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
9
新鲜思路! 感谢分享! 
2022-8-13 14:04
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10

想請教,我已經有正常初始化成功,但是Example.Print_CurrentAllComponent()時遇到以下錯誤,求解
Error: access violation accessing 0x18
    at il2cpp_runtime_invoke (/frida/repl-2.js:363)  
    at Invoke (/frida/repl-2.js:807)
    at #FindObjectsOfType (/frida/repl-2.js:1517)    
    at GetCurrentAllComponent (/frida/repl-2.js:1451)
    at Print_CurrentAllComponent (/frida/repl-2.js:1699)
    at <eval> (<input>:1)
    at eval (native)

有嘗試先il2cpp_thread_attach(il2cpp_domain_get())了還是不行,謝謝!

最后于 2022-8-17 20:05 被wx_suzuke编辑 ,原因:
2022-8-17 19:21
0
雪    币: 207
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
wx_suzuke 想請教,我已經有正常初始化成功,但是Example.Print_CurrentAllComponent()時遇到以下錯誤,求解Error:&nbsp;access&nbsp;viola ...
可能是版本不兼容,这个方案也不是百分百兼容所有版本,不同版本引擎有一点细微调整。
没记错的话,我当时测试用的2021。
2022-8-18 03:27
0
雪    币: 197
活跃值: (166)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12

请教对于泛型方法应该怎么获取并执行?例如:public T GetNetObject<T>() { },用il2cpp_class_get_method_from_name虽然可以获取到方法信息,但是执行地址是NULL,而且这类方法好像是有约束的,il2cpp_class_get_method_from_name获取的方法用il2cpp_runtime_invoke调用并不会返回正确的数据。

最后于 2022-9-21 22:52 被higherlin编辑 ,原因:
2022-9-21 22:48
0
雪    币: 207
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
higherlin 请教对于泛型方法应该怎么获取并执行?例如:public&nbsp;T&nbsp;GetNetObject&lt;T&gt;()&nbsp;{&nbsp; ...
建议用unity写个demo对比看下,太久了确实记不太清清楚
2022-9-22 13:40
0
雪    币: 197
活跃值: (166)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
憨豆爆发 建议用unity写个demo对比看下,太久了确实记不太清清楚
通过CodeRegistration和MetadataRegistration倒是可以获取到methodPointer,但是如果不能获取到不同泛型的这个方法的MethodInfo,执行这个方法会直接闪退,MethodInfo->methodDefinition要和对应的泛型对应才能正确执行,如果不能通反射获取泛型MethodInfo,那Unity这错误有点低级啊。
2022-9-23 16:26
0
雪    币: 197
活跃值: (166)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
憨豆爆发 建议用unity写个demo对比看下,太久了确实记不太清清楚
终于搞定泛型方法调用,要通过反射调用MakeGenericMethod。
2022-9-23 22:12
1
雪    币: 207
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
higherlin 终于搞定泛型方法调用,要通过反射调用MakeGenericMethod。
哦~感谢佬分享经验  奶心奶心~~~
2022-10-2 02:29
0
雪    币: 226
活跃值: (2308)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
大佬请教下,MakeGenericMethod方法的参数是Type类型的列表Type[],这个要怎么在C或者js里面复现
2022-12-21 11:56
0
雪    币: 226
活跃值: (2308)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
higherlin 终于搞定泛型方法调用,要通过反射调用MakeGenericMethod。
老哥,最后调用MakeGenericMethod的时候参数是怎么构建的,我也frida一直报错
2022-12-21 22:23
0
游客
登录 | 注册 方可回帖
返回
//