1. 程式人生 > 實用技巧 >Frida 環境部署及使用

Frida 環境部署及使用

目錄

Frida 環境部署

Frida 是一款基於 Python + JavaScriptHook 與除錯框架

Frida大致原理是手機端安裝一個server程式,然後把手機端的埠轉到PC端,PC端寫python指令碼進行通訊,而python指令碼中需要hook的程式碼採用javascript語言。

官方文件:https://frida.re/docs/javascript-api/#java-cast

安裝:

pip install frida
pip install frida-tools

服務端配置

https://github.com/frida/frida/releases下載對應平臺的服務端

frida-server-12.11.12-android-arm64.xz

然後解壓,移動到Android裝置

adb

下載地址

https://developer.android.google.cn/studio/releases/platform-tools

然後配置環境變數

adb push frida-server-12.5.7-android-x86 /data/local/tmp/

adb shell
cd  /data/local/tmp/
chmod 777 frida-server-12.11.12-android-arm64

然後啟動執行,轉發埠

./frida-server-12.11.12-android-arm64

adb forward tcp:27042 tcp:27042

基本執行

檢視連線到的裝置

frida-ls-devices

Id                Type    Name
----------------  ------  ------------
local             local   Local System
ENU7N15A30003435  usb     Nexus 6P
socket            remote  Local Socket

檢視裝置上的程序資訊

frida-ps -U

使用

import frida
import sys

def on_message(message , data):
    if message["type"] == "send":
        print("[*] {0}".format(message['payload']))
    else:
        print(message)



jscode_signature = """
Java.perform(function(){
    var TestSig = Java.use('com.yaotong.crackme.MainActivity');
    
    TestSig.securityCheck.implementation = function(str){
    send('I am here');
    return true;
    };
});
"""

# 查詢USB裝置並附加到目標程序
process = frida.get_remote_device().attach('com.yaotong.crackme')
# 在目標程序裡建立指令碼
script = process.create_script(jscode_signature)
# 註冊訊息回撥
script.on("message", on_message)
print('[*] Runing CTF')
# 載入建立好的javascript指令碼
script.load()
# 讀取系統輸入
sys.stdin.read()

載入類

Java.use方法用於宣告一個Java類,在用一個Java類之前首先得宣告。比如宣告一個String類,要指定完整的類名:

var StringClass=Java.use("java.lang.String");

修改函式的實現

修改一個函式的實現是逆向除錯中相當有用的。修改一個函式的實現後,如果這個函式被呼叫,我們的Javascript程式碼裡的函式實現也會被呼叫

函式引數型別表示

不同的引數型別都有自己的表示方法

  1. 對於基本型別,直接用它在Java中的表示方法就可以了,不用改變,例如:
  • int
  • short
  • char
  • byte
  • boolean
  • float
  • double
  • long
  1. 基本型別陣列,用左中括號接上基本型別的縮寫

基本型別縮寫表示表:

基本型別 縮寫
boolean Z
byte B
char C
double D
float F
int I
long J
short S

例如:int[]型別,在過載時要寫成[I

  1. 任意類,直接寫完整類名即可

例如:java.lang.String

  1. 物件陣列,用左中括號接上完整類名再接上分號

例如:[java.lang.String;

帶引數的建構函式

修改引數為byte[]型別的建構函式的實現

ClassName.$init.overload('[B').implementation=function(param){
    //do something
}

注:ClassName是使用Java.use定義的類;param是可以在函式體中訪問的引數

修改多引數的建構函式的實現

ClassName.$init.overload('[B','int','int').implementation=function(param1,param2,param3){
    //do something
}

無引數建構函式

ClassName.$init.overload().implementation=function(){
    //do something
}

呼叫原建構函式

ClassName.$init.overload().implementation=function(){
    //do something
    this.$init();
    //do something
}

注意:當建構函式(函式)有多種過載形式,比如一個類中有兩個形式的func:void func()void func(int),要加上overload來對函式進行過載,否則可以省略overload

一般函式

修改函式名為func,引數為byte[]型別的函式的實現

ClassName.func.overload('[B').implementation=function(param){
    //do something
    //return ...
}

無引數的函式

ClassName.func.overload().implementation=function(){
    //do something
}

注: 在修改函式實現時,如果原函式有返回值,那麼我們在實現時也要返回合適的值

ClassName.func.overload().implementation=function(){
    //do something
    return this.func();
}

呼叫函式

和Java一樣,建立類例項就是呼叫建構函式,而在這裡用$new表示一個建構函式。

var ClassName=Java.use("com.luoye.test.ClassName");
var instance = ClassName.$new();

例項化以後呼叫其他函式

var ClassName=Java.use("com.luoye.test.ClassName");
var instance = ClassName.$new();
instance.func();

型別轉換

Java.cast方法來對一個物件進行型別轉換,如將variable轉換成java.lang.String

var StringClass=Java.use("java.lang.String");
var NewTypeClass=Java.cast(variable,StringClass);

Java.available欄位

這個欄位標記Java虛擬機器(例如: Dalvik 或者 ART)是否已載入, 操作Java任何東西的之前,要確認這個值是否為true

Java.perform方法

Java.perform(fn)在Javascript程式碼成功被附加到目標程序時呼叫,我們核心的程式碼要在裡面寫。格式:

Java.perform(function(){
//do something...
});
var classnames = java.enumerateLoadeClassesSync();
for (var i=0; i<classnames.length; i++){
    send('class name:'+classnames[i]);
# jscode = """
# Java.perform(function (){
# var v = Java.androidVersion;
# send('version:'+v);
# //var classnames = Java.enumerateLoadedClassesSync();
# //for (var i=0; i<classnames.length; i++){
# //    send('class name:'+classnames[i]);
# //}
# });
"""