【问题标题】:Frida - Calling a specific method overloadFrida - 调用特定方法重载
【发布时间】:2020-07-28 09:21:00
【问题描述】:

我正在探索一个 Android 程序,它有多个具有相同名称和参数的方法。

我需要调用一个特定的方法重载。 像这样的Java代码

package a;
public class d
{
     public int a() {
        return 10;
    }

    public long a() {
        return 20;
    }
    public long b() {
        long ret = a();
        return ret + 1;
    }
}

我需要替换 b() 的实现并调用 (int)a() 而不是 (long)a()。 请帮我修复我的 frida js 代码。

Java.perform(function () {
  Var Class_A_D = java.Use("a.d");
  Class_A_D.b.implementation = function(){
    var ret = this.(a); // need to call int implementation
    return ret;
 }
}

【问题讨论】:

  • 对于构造函数的特殊情况,这里已经回答:stackoverflow.com/a/60880361/150978 对于常规方法,这也应该以相同的方式工作。
  • 这不是我的情况。 “重载”构造按输入参数类型选择函数。但是我的两种方法都没有参数。 М方法的返回参数不同。
  • 好的;代码被严重混淆,甚至违反了Java重载方法的基本原则(不知道这是可能的)。因此,我只看到获取所有方法列表的方法,然后过滤它们的名称、参数和返回类型,直到只剩下一个方法。然后你可以调用这个方法,如我上一条评论中链接的答案所示。

标签: javascript java android security frida


【解决方案1】:

我用 Java.reflect 找到了答案

Java.perform(function () {
    var Java_lang_Object = Java.use('java.lang.Object');
    var Java_lang_String = Java.use('java.lang.String');
//This function get method reference by reflect
        function dynamic_search_method(io_object, iv_name, iv_ret_type, it_par){ 
          var lt_methods = io_object.getMethods()  ;
          var lv_found;
          for(var  lv_i=0;lv_i < lt_methods.length;lv_i++){
             if(lt_methods[lv_i].getName().toString()  == iv_name && lt_methods[lv_i].getGenericReturnType().toString() == iv_ret_type){
                var lt_par_type = lt_methods[lv_i].getParameterTypes();
                if(lt_par_type.length == it_par.length){
                  lv_found = true; 
                  for(var  lv_j=0;lv_j < lt_par_type.length && lv_found == true;lv_j++){
                    if(lt_par_type[lv_j].getName().toString() != it_par[lv_j]) lv_found = false  ; 
                  }                   
                  if(lv_found == true) return lt_methods[lv_i];
                }
             }
          }
         return null;
        }
//This function call method dynamically 
        function dynamic_invoke(io_object,io_method, it_par){
          if(io_object===null || io_method ===null ) return null;
          try{
            var lo_cast_obj = Java.cast( io_object ,Java_lang_Object);
          }catch(e){
            return null;
          }
          var lt_par = Java.array('java.lang.Object',it_par);
          return io_method.invoke(lo_cast_obj,lt_par);
        }
//example of use
  Var Class_A_D = java.Use("a.d");


  Class_A_D.b.implementation = function(){
// call method "a" of instance, with "long" return and without parameter
var lo_meth = dynamic_search_method(this.getClass(),"a","long",[]);
var lv_var= dynamic_invoke(this,lo_meth,[]);

// call method "c" of instance, with "android.content.Context" return and with 2 parameters
lo_meth = dynamic_search_method(this.getClass(),"a","class android.content.Context",['java.lang.String','java.lang.String']);
var lv_var= dynamic_invoke(this,lo_meth,[Java_lang_String.$new("Test"),Java_lang_String.$new("String")]);
// call static method
var lo_meth = dynamic_search_method(Class_A_D.class,"d","class java.lang.String",[]);
var lv_var= dynamic_invoke(Class_A_D.class,lo_meth,[]);    
};

)};

【讨论】:

    【解决方案2】:

    d类中的代码违反了方法名和每个参数类型定义的方法签名原则。

    因为方法类型不是签名的一部分,Java 将这些方法读取为相同: 公共 int a() {...} public long a(){...}

    两个签名都是“a()”

    您应该将这些方法重命名为具有不同的名称(或具有不同类型的输入参数)

    更多信息在这里:https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html

    【讨论】:

    • 当然,我不能在“外来”的APK文件中重命名方法(完全反编译成smali,改名重建apk太费时间了)
    猜你喜欢
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 2017-12-05
    • 2021-05-04
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    相关资源
    最近更新 更多