Frida學習04-RPC及其自動化
日期:Mar-3-2022
作者:狐狸大劍眼鏡
書籍:安卓Frida逆向與抓包實戰-陳佳林
3.1節中,曾介紹過Frida存在兩種操作模式,其中第一種命令行模式在之前的章節中一直使用,在這一節中,將介紹一些關於RPC模式以及使用RPC完成自動化的相關知識。在Frida中,可以使用Python完成JavaScript腳本對進程的注入以及相應的Hook。
package com.example.myapplication;
import androidx.annotation.LongDef;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private String total = "hello";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("MainActivity","hollowed!");
while (true){
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
fun(50,30);
Log.d("MainActivity.string", fun("LoWeRcAsE !!!!!!!!!!!!!"));
}
}
void fun(int x ,int y) {
Log.d("MainActivity", String.valueOf(x+y));
}
String fun(String x) {
return x.toLowerCase();
}
void secret(){
total += "secretFunc";
Log.d("MainActivity.secret", "secret: 999");
}
static void staticSecret(){
Log.d("MainActivity.Secret", "staticSecret: 777");
}
}
增加了一個字符串類型的實例變量total,同時每次調用secret()函數對字符串進行擴展。
這次的目的是獲取total的值。
在主動調用時需要注意的是,Java中的變量也存在是否使用static
修飾的區別。在用Frida對Java中的變量進行處理時也要區分是否使用
static修飾:類變量,使用static修飾,可以直接通過類進行獲取;實
例變量,不使用static修飾,和特定的對象綁定在一起。
function CallSecretFunc() {
Java.perform(function () {
//動態函數主動調用
Java.choose("com.example.myapplication.MainActivity", {
onMatch: function (instance) {
instance.secret()
},
onComplete: function () {
}
})
})
}
function getTotalValue() {
Java.perform(function () {
var MainActivity = Java.use("com.example.myapplication.MainActivity")
//動態函數主動調用
Java.choose("com.example.myapplication.MainActivity", {
onMatch: function (instance) {
console.log("total value = ", instance.total.value)
},
onComplete: function () {
console.log("search complate")
}
})
})
}
setImmediate(getTotalValue)
這是如果直接調用getTotalValue的值會報錯,需要先執行CallSecretFunc()函數,調用所在動態函數。
在確認我們的函數都沒有寫錯且功能達到預期后,接下來我們開始
RPC遠程調用。將CallSecretFunc()函數和getTotalValue()函數導
出,使得外部可以進行調用,在JavaScript代碼末尾加上RPC相關代
碼:
rpc.exports = {
callsecretfunc: CallSecretFunc,
gettotalvalue: getTotalValue
};
部分代碼實現的功能就是將CallSecretFunc()函數和
getTotalValue()函數分別導出為callsecretfunc和gettotalvalue。需
要注意的是,導出名不可以有大寫字母或者下划線。接下來在外部就可
以調用這兩個函數了
import frida
import sys
def on_message(message, data):
if message['type'] == 'send':
print("{*} {0}".format(message['payload']))
else:
print(message)
# 首先通過frida.get_usb_device()獲取到USB設備句柄
device = frida.get_usb_device()
# device.attach()進程進行注入
process = device.attach('com.example.myapplication')
with open('javahook4.js') as f:
jscode = f.read()
# 使用create_script()函數加載了編寫的JavaScript代碼
script = process.create_script(jscode)
"""
使用script.on('message', on_message)注冊了自己的消息對應的函
數,每當JavaScript想要輸出時都會經過這里指定的on_message進行
"""
script.on('message', on_message)
script.load()
command = ''
while True:
"""
最重要的RPC調用代碼,即通過script.exports訪問所
有我們在JavaScript中定義的導出名,進而調用導出函數。這樣就完成
了RPC遠程調用,達到在主機上可以隨意調用App代碼的目的。
"""
command = input(
"\nEnter command:\n:Exit\n2:Call secret function\n3:Get Total value:\nchoice:")
if command == '1':
break
elif command == '2':
script.exports.callsecretfunc()
elif command == '3':
script.exports.gettotalvalue()
運行frida-server
運行python腳本,好像有點bug,js的這句注釋掉//setImmediate(getTotalValue),先不獲取Total值。