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

關閉防火牆

adb shell
su
setenforce 0

使用

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...
});


免責聲明!

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



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