frida主動調用app方法


frida主動調用函數

除了使用frida進行hook, 很多場景我們需要用frida主動調用app的java方法和so方法。

因為hook大多數時候只能被動的等待觸發,如果函數一直不觸發咋辦,你就干等着嗎。所以主動調用要靈活的多。

大家好,我是王鐵頭 一個乙方安全公司搬磚的菜雞
持續更新移動安全,iot安全,編譯原理相關原創視頻文章
更多frida調用app方法 frida rpc視頻演示:[https://space.bilibili.com/430241559]

frida主動調用方法分類

frida主動調用分為下面幾種情況

  1. frida 主動調用java類方法 (靜態java方法)
  2. frida 主動調用native類方法 (靜態native方法)

  1. frida 主動調用對象的java方法
  2. frida 主動調用對象的native方法

  1. frida 主動調用so方法

這里把類方法和對象方法區分開是因為。
類方法可以直接調用 對象方法必須要有對象
區別在於有沒有static這個關鍵字
有static關鍵字就是靜態方法 沒有static就是對象方法

這里獲取對象的方法有兩個

  1. 直接獲取內存中已經有的對象
  2. 自己 創建(new)一個

好 下面演示一下5種方式的具體調用代碼

1. frida主動調用類方法(java靜態方法)代碼

要調用的函數聲明如下

public static String enc(String str_data, int n_conunt)

可以看到這個函數是有static關鍵字的 所以是個類方法(靜態方法)
調用格式:

類名引用.方法名(參數,...)

主動調用代碼

function call_enc(str_data, n_cnt) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;

  Java.perform(function () 
  {
    //打log方便調試
    console.log("===========>on enc");  

    // 獲取類
    var obj = Java.use(str_cls_name);

    //調用類方法 因為這里是靜態方法 所以可以直接調用
    str_ret = obj.enc(str_data, n_cnt);
    
    //打印結果 方便調試
    console.log("enc result: " + str_ret);
  });
  return str_ret;
}

2. frida 主動調用native類方法 (靜態native方法)代碼

要調用的函數聲明如下

public static native String c_enc(String str_data)

可以看到這個函數是有static關鍵字的 所以是個類方法(靜態方法)這里有native 關鍵字 所以是個靜態的c方法

調用格式:

類名引用.方法名(參數,...)

主動調用代碼

function call_c_enc(str_data) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;

  Java.perform(function () 
  {
    //打log方便調試
    console.log("===========>on enc");  

    // 獲取類
    var obj = Java.use(str_cls_name);

    //調用類方法 因為這里是靜態方法 所以可以直接調用
    str_ret = obj.c_enc(str_data);
    
    //打印結果 方便調試
    console.log("enc result: " + str_ret);
  });
  return str_ret;
}

3.frida 主動調用對象的java方法

要調用的函數聲明如下

public  String enc(String str_data)

可以看到這個函數是沒有有static關鍵字的 所以是個對象方法(實例方法)
主動調用有2種方式

  1. 直接獲取內存中已存在的對象(建議使用)
  2. 自己創建一個新對象

因為運行過程中對象的成員的值可能已經發生了變化,所以如果重新創建一個對象,新對象的值還是初始值,在調用算法或者函數的時候,可能會產生影響。
所以這里建議直接獲取內存中已經有的對象

舉個例子 A對象有個成員 m_a 初始值是3
在app運行過程中,被設置成了666
在調用 A對象算法的時候 m_a參與了運算
666這個值可能才是算法需要的合法的值。

如果創建一個新對象A1,那么m_a的值是3
這時候調用算法 那么因為m_a的改變 很可能返回一個錯誤的值

調用格式

1.instance.方法名(參數,...)  //直接獲取已有對象
2.類名引用.方法名(參數,...) //新創建的對象

1) 直接獲取內存中對象主動調用

這里介紹一個frida的api

      //從內存中(堆)直接搜索已存在的對象
      Java.choose('xxx.xxx.xxx ', //這里寫類名 
      {
        //onMatch 匹配到對象執行的回調函數
        onMatch: function (instance) 
        {
        },
       //堆中搜索完成后執行的回調函數
        onComplete: function () 
        {
        }
      });

主動調用代碼

function call_enc(str_data) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;
  
  Java.perform(function () 
  {
      Java.choose(str_cls_name, 
      {
        onMatch: function (instance) 
        {
            //調試用
            console.log("onMatch ");  
            //直接調用對象的函數 instance是找到的對象
            str_ret = instance.enc(str_data);
        },
        onComplete: function () 
        {
        }
      });
  });
  console.log("enc result: " + str_ret);
  return str_ret;
}

2) 創建一個新對象 主動調用代碼

這里要用frida創建對象的語法 $new()

 //獲取類的引用
var cls = Java.use('這里寫類名');

//調用構造函數 創建新對象  這里注意參數
var obj = cls.$new();

這里$new()是調用類的構造函數 新建一個對象
這里注意兩點

  1. 如果沒有構造函數 或者 構造函數沒有參數 這里直接寫$new()
  2. 如果構造函數有參數,那么一定要填參數 $new(參數,...)

創建一個對象 主動調用代碼

function call_enc(str_data) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;
  
  Java.perform(function () 
  {
       //獲取類的引用
       var cls = Java.use(str_cls_name);

       //調用構造函數 創建新對象  這里注意參數
       var obj = cls.$new();
      
       //調用新對象的對象方法 enc
       str_ret = obj.enc(str_data);
  });
  console.log("enc result: " + str_ret);
  return str_ret;
}

4.frida 主動調用對象的native方法

要調用的函數聲明如下

public native String enc(String str_data, int n_num)

可以看到這個函數是沒有有static關鍵字的 所以是個對象方法(實例方法)
主動調用有2種方式

  1. 直接獲取內存中已存在的對象(建議使用)
  2. 自己創建一個新對象
    建議直接獲取內存中已經有的對象

調用格式

1.instance.方法名(參數,...)  //直接獲取已有對象
2.類名引用.方法名(參數,...) //新創建的對象

1) 直接獲取內存中對象主動調用

主動調用代碼

function call_enc(str_data,  n_num) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;
  
  Java.perform(function () 
  {
      Java.choose(str_cls_name, 
      {
        onMatch: function (instance) 
        {
            //調試用
            console.log("onMatch ");  
            //直接調用對象的函數 instance是找到的對象
            str_ret = instance.enc(str_data, n_num);
        },
        onComplete: function () 
        {
        }
      });
  });
  console.log("enc result: " + str_ret);
  return str_ret;
}

2) 創建一個新對象 主動調用代碼

function call_enc(str_data, n_num) 
{
 //這里寫函數對應的類名
  var str_cls_name = "com.wangtietou.test_rpc_all.Test_Enc_Dec";
  //返回值 
  var str_ret = null;
  
  Java.perform(function () 
  {
       //獲取類的引用
       var cls = Java.use(str_cls_name);

       //調用構造函數 創建新對象  這里注意參數
       var obj = cls.$new();
      
       //調用新對象的對象方法 enc
       str_ret = obj.enc(str_data, n_num);
  });
  console.log("enc result: " + str_ret);
  return str_ret;
}

5 frida 主動調用so方法

so層函數聲明

char* c_enc_2(char* p_str_data,  int n_num)

這里介紹一個frida用於調用c層函數的API

NativeFunction(address, returnType, argTypes[, abi])

1)address:要hook的函數地址
2)returnType:返回值類型
3)argTypes[, abi]: 參數類型 這里參數可以是多個

frida NativeFunction支持的類型
image.png
這里參數有兩個 一個是 char* 一個是int
大家可以看上面的圖 NativeFunction是支持int這個類型的

但是沒有char* 對於指針一系列的參數 我們可以用 pointer表示 所以這里的返回值類型就是 'pointer',
參數類型是['pointer', 'int']


注意 JavaScript 是沒有char* 這個類型的,所以要通過frida的api去模擬 這里Memory.allocUtf8String()申請空間 存入支付串 模擬char*

function test_c(str_data, n_num) 
{
    var str_name_so = "libnative-lib.so";    //要hook的so名
    var str_name_func = "c_enc_2";          //要hook的函數名
    
    //獲取函數的地址
    var n_addr_func = Module.findExportByName(str_name_so , str_name_func);
    console.log("func addr is ---" + n_addr_func);

    //定義NativeFunction 等下要調用
    var func_c_enc = new NativeFunction(n_addr_func , 'pointer', ['pointer', 'int']);
    
    //調用frida的api申請空間 填入字符串 模擬char*
    var str_data_arg = Memory.allocUtf8String(str_data);
    
     //調用so層的c函數
    var p_str_ret = func_c_enc(str_data_arg, n_num);
    
    //讀取字符串  
    var str_ret = Memory.readCString(p_str_ret);
    return str_ret;
}

持續更新移動安全,iot安全,編譯原理相關原創視頻文章
更多frida調用app方法 frida rpc視頻演示:[https://space.bilibili.com/430241559]
相關資料關注公眾號 回復rpc進行下載:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM