Frida使用java.lang.reflect.Array类打印Java反射数组

前言

通过frida进行java反射调用String的getBytes方法,得到了[B类型的引用
无论如何尝试都无法打印输出其内容,甚至java.util.Arrays类的相关方法也无法正确输出

之后刷到这篇文章了解到java.lang.reflect.Array类用于反射打印数组
https://www.cnblogs.com/liwxmyself/p/14758632.html
进而了解到另一篇文章,详细介绍了相关方法
https://www.cnblogs.com/pony1223/p/7470382.html

总之,通过反射获取到的数组,不能直接通过Arrays类操作,应该通过reflect包下的Array类操作

案例

创建Java字符串后,有如下3个字节数组

  • result 直接通过反射调用getBytes方法获取字符串对应的字节数组
  • result2 调用java方法getBytes后转换为字节数组类型
  • result3 调用getBytes后不进行其他操作

分别通过Typeof打印类型以及直接打印结果

                //反射操作String
                var str=Java.use("java.lang.String").$new("demo")
                var result=Reflection.invokeMethod("java.lang.String","getBytes",str, [], [])//[B byte[]数组,无法直接打印
                var result2=Java.cast(str.getBytes(),Java.use("[B"))//转换为byte[]数组,无法直接打印
                var result3=str.getBytes()//可直接打印
                //打印类型
                console.log("Typeof result:", typeof result);//Typeof result: object
                console.log("Typeof result2:", typeof result2);//Typeof result2: object
                console.log("Typeof result3:", typeof result3);//Type of result3: object
                //打印结果
                console.log("[+] result:", result);//[+] result: [B@7ab81e8
                console.log("[+] result2:", result2);//[+] result2: [B@70b3001
                console.log("[+] result3:", result3);//[+] result3: 100,101,109,111

打印结果如下,可以发现均为object类型,但是直接打印结果略有区别
只有result3可以直接显示内容,其他均为引用
在这里插入图片描述
之后利用java.lang.reflect.Array类的静态方法

  • Object get(Object[],int index) 反射获取任意类型数组指定下标的元素
  • byte getByte(Object[],int index) 反射获取byte[]类型数组指定下标的元素
                //反射调用得到的数组类型需要使用java.lang.reflect.Array类进行操作,而非java.util.Arrays类
                const reflectArray = Java.use("java.lang.reflect.Array");
                //基本操作
                console.log(typeof reflectArray.get(result,0))//object
                console.log(typeof reflectArray.getByte(result,0))//number
                console.log("length:",reflectArray.getLength(result));//length: 4
                //遍历
                for(var i=0;i<reflectArray.getLength(result);i++){
                    console.log("result["+i+"]:",reflectArray.getByte(result,i));
                }
                for(var i=0;i<reflectArray.getLength(result2);i++){
                    console.log("result2["+i+"]:",reflectArray.getByte(result2,i));
                }

打印结果如下
get获取的是object类型
getByte获取到的是number类型
并且成功遍历
在这里插入图片描述

其中invokeMethod封装如下

// 核心:通过 ClassLoader 获取类引用
function getClass(className, classLoader) {
    try {
        if (classLoader) 
            return classLoader.loadClass(className);// 使用指定的 ClassLoader
        else 
            return Java.use(className).class;// 默认使用全局 ClassLoader
    } catch (e) {
        console.error(`[Reflection] getClass error: ${e}`);
        return null;
    }
}
    /**
     * 调用实例方法(支持指定 ClassLoader)
     * @param {string} className      类名
     * @param {string} methodName     方法名
     * @param {Object} instance      实例对象
     * @param {Array<Class>} paramTypes  参数类型
     * @param {Array<any>} paramValues 参数值
     * @param {ClassLoader} [classLoader] 类加载器(可选)
     */
    invokeMethod: function (className, methodName, instance, paramTypes, paramValues, classLoader) {
            try {
                const clazz = getClass(className, classLoader);
                if (!clazz) return null;

                const method = clazz.getDeclaredMethod(
                    methodName,
                    Java.array('java.lang.Class', paramTypes)
                );
                method.setAccessible(true);
                const jArgs = Java.array('java.lang.Object', paramValues);
                return method.invoke(instance, jArgs);
            } catch (e) {
                console.error(`[Reflection] invokeMethod error: ${e}`);
                return null;
            }
    },
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OrientalGlass

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值