frida反射调用对象中的方法与字段

原创
2020/12/06 15:31
阅读数 3.3K

该篇文章主要介绍当我们碰到参数或者返回值是一个对象时,如何通过frida反射调用该对象的方法(methods)与获取该对象的字段(fields)


  1. 添加测试frida反射调用的demo app

    写一个测试类,其中包含字段(fields)int类型的count、String类型的plainText

    及多个简单方法。其中display方法参数为ParametersTest对象

    在文中,我们要hook display方法并hook它的参数ParametersTest对象反射调用ParametersTest对象的所有方法及打印parametersTest的所有字段‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

    public class ParametersTest {
        private final int count = 523;//字段count    private final String plainText = "this is a test";//字段plainText
    public int multiply(int val1,int val2){ return val1 * val2; }
    public byte multiply(byte val1,byte val2){ return (byte)(val1 * val2); }
    public short multiply(short val1,short val2){ return (short)(val1 * val2); }
    public long multiply(long val1,long val2){ return val1 * val2; }
    public float multiply(float val1,float val2){ return val1 * val2; }
    public double multiply(double val1,double val2){ return val1 * val2; }
    public String addMethod(String str1,String str2){ return str1 + str2; }
    public void addMethod(int[] initArray){ for(int i = 0; i < initArray.length;i++){ initArray[i] = initArray[i] + 1; } }
    public void addMethod(byte[] byteArray){ for(int i = 0; i < byteArray.length;i++){ byteArray[i] = (byte)(byteArray[i] + 1); } }
    public void addMethod(long[] longArray){ for(int i = 0; i < longArray.length; i++){ longArray[i] = longArray[i] + 1; } }
    public void addMethod(float[] floatArray){ for(int i = 0; i < floatArray.length; i++){ floatArray[i] = floatArray[i] + 1; } }
    public void addMethod(double[] doubleArray){ for(int i = 0; i < doubleArray.length; i++){ doubleArray[i] = doubleArray[i] + 1; } }
    public void addMethod(String[] strArray){ String result = ""; for(int i = 0; i < strArray.length; i++){ result = result + strArray[i]; } }    //display方法参数为ParametersTest对象 public void display(ParametersTest parametersTest){ int[] intArray = {1,2,3,4,5}; parametersTest.addMethod(intArray);
    byte[] byteArray = {0x10,0x11,0x12,0x13}; parametersTest.addMethod(byteArray);
    long[] longArray = {0x1,0x2,0x3,0x4}; parametersTest.addMethod(longArray);
    String[] strArray = {"abcde","1222CDedd","12daer","cder"}; parametersTest.addMethod(strArray);
    float[] floatArray = {0x1,0x2,0x3,0x4}; parametersTest.addMethod(floatArray);
    double[] doubleArray = {0x1,0x2,0x3,0x4}; parametersTest.addMethod(doubleArray);
    String str1 = "acerwe"; String str2 = "werwed"; parametersTest.addMethod(str1,str2);
    int intVal1 = 3; int intVal2 = 4; int retInt = parametersTest.multiply(intVal1,intVal2);
    byte byteVal1 = 0x1; byte byteVal2 = 0x2; byte retByte = parametersTest.multiply(byteVal1,byteVal2);
    long longVal1 = 0x3; long longVal2 = 0x4; long retLong = parametersTest.multiply(longVal1,longVal2);
    float floatVal1 = 0x3; float floatVal2 = 0x4; float retFloat = parametersTest.multiply(floatVal1,floatVal2);
    short shortVal1 = 0x3; short shortVal2 = 0x4; short retShort = parametersTest.multiply(shortVal1,shortVal2);
    double doubleVal1 = 0x3; double doubleVal2 = 0x4; double retDouble = parametersTest.multiply(doubleVal1,doubleVal2); }
    }


  2. frida反射调用打印字段(fields)类型、名称、值

    //hook display方法parametersTestClass.display.overload("com.example.parameterstest.ParametersTest").implementation = function (val1{  getReflectFields(val1);//打印所有字段(fields)类型、名称、值  getReflectMethod(val1)//hook ParametersTest对象的所有方法  this.display(val1);//调用display方法}
    function getReflectFields(val1) {  var clazz = Java.use("java.lang.Class");  var parametersTest = Java.cast(val1.getClass(),clazz);  //getDeclaredFields()获取所有字段  var fields = parametersTest.getDeclaredFields();  fields.forEach(function (field) {//依次打印字段的类型、名称、值    send("field type is: " + (field.getType()));    send("field name is: " + (field.getName()));    send("field value is: " + field.get(val1));  })}

    结果如下:


  3. frida反射调用类中的方法

    function getReflectMethod(val1{  try{    var clazz = Java.use("java.lang.Class");    var parametersTest = Java.cast(val1.getClass(),clazz);    //getDeclaredMethods()获取所有方法    var methods = parametersTest.getDeclaredMethods();      methods.forEach(function (method{        var methodName = method.getName();        var val1Class = val1.getClass();        var val1ClassName = Java.use(val1Class.getName());        var overloads = val1ClassName[methodName].overloads;        overloads.forEach(function (overload{          var proto = "(";          overload.argumentTypes.forEach(function (type{            proto += type.className + ", ";          });          if(proto.length > 1){            proto = proto.substr(0 ,proto.length - 2);          }          proto += ")";          overload.implementation = function ({            var args = [];            for(var j = 0; j < arguments.length; j++){              for(var i in arguments[j]){                var value = String(arguments[j][i]);                send(val1ClassName + "." + methodName + " and arguments value is: " + value);              }              args[j] = arguments[j] + "";            }            //打印方法参数            send(val1ClassName + "." + methodName + " and args is: " + args);            //调用方法            var retval = this[methodName].apply(this,arguments);            //打印方法返回值            send(methodName + " return value is: " + retval);            return retval;//返回方法返回值          }        })      })
        }catch(e){     send("'" + val1 + "' hook fail: " + e);    }  }  

    结果如下:


  4. 完整测试代码可以在公众号回复“frida reflect”通过百度云下载(包含测试demo、frida脚本)

本文分享自微信公众号 - 网络安全技术点滴分享(gh_c85d6ae14603)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部