Frida簡單說就是一個(gè)跨平臺(tái)的hook框架纱意,主要應(yīng)用場景是app運(yùn)行時(shí)运吓,附加hook腳本尘颓,監(jiān)視和修改進(jìn)程中的代碼, 從而實(shí)現(xiàn)對目標(biāo)程序的深度分析和修改团秽。
官方文檔:https://frida.re/docs/examples/android/
一主胧、Frida安裝
1.1 mac安裝frida及相關(guān)工具
pip3 install frida
pip3 install frida-tools
pip3 install objection
1.2 root手機(jī)安裝frida-server
① 獲取需要下載的frida-server版本和類型信息:
adb shell getprop ro.product.cpu.abi 查詢cpu架構(gòu)
frida --version 查詢電腦端frida版本
②根據(jù)上面信息下載對應(yīng)版本的frida-server
https://github.com/frida/frida/releases 例如:frida-server-16.4.2-android-arm64
adb push frida-server-16.4.2-android-arm64 /data/local/tmp
cd /data/local/tmp
chmod 777 frida-server-16.4.2-android-arm64
二、Frida使用
2.1 啟動(dòng)frida-server
adb root
cd /data/local/tmp
./frida-server-16.4.2-android-arm64
2.2 frida常用命令
frida-h 查看幫助
frida-ps -U 通過USB訪問手機(jī)上的frida-server (測試frida-server啟動(dòng)是否成功)
2.3 frida附加腳本執(zhí)行
- attach: 已存在目標(biāo)進(jìn)程习勤,內(nèi)部執(zhí)行過程hook
frida -U -N <packageName> -l demo.js
- spawn: 未存在目標(biāo)進(jìn)程踪栋,在啟動(dòng)目標(biāo)進(jìn)程的過程hook
frida -U -f <packageName> -l demo.js
使用進(jìn)程pid方式附加
frida -U -p <pid> -l demo.js
三、 hook java的常用實(shí)現(xiàn)
1)觸發(fā)時(shí)機(jī)設(shè)置
setImmediate(main) //立即執(zhí)行
setTimeout(main, 2000); // 延遲執(zhí)行
2)代碼運(yùn)行在 Java 環(huán)境
Java.perform(function(){
//do something...
});
3)加載一個(gè)Java類
var StringClass = Java.use("java.lang.String");
var innerClass = Java.use("com.example.lesson5.MainActivity$InnerClass");
4)被動(dòng)修改調(diào)用方法(依賴該方法在原有應(yīng)用邏輯中被觸發(fā))
可修改參數(shù)图毕、函數(shù)體實(shí)現(xiàn)夷都、返回值
mainActivity.text.implementation = function(){
return "222"
}
5)重載的函數(shù)
mainActivity.text.overload('int','int').implementation = function(a, b){
console.log("調(diào)用了text重載方法 a=", a, ",b=", b)
return this.text(3,4)
}
6)實(shí)例化對象
var string = Java.use("java.lang.String").$new("abc")
7)獲取調(diào)用棧
var throwInstance = Java.use("java.lang.Throwable").$new()
var thStr = Java.use("android.util.Log").getStackTraceString(throwInstance)
console.log("error=", thStr)
8)內(nèi)存中找實(shí)例,主動(dòng)調(diào)用類方法(不依賴該方法在原有應(yīng)用邏輯中被觸發(fā))
Java.choose("com.stan.secure.MainActivity",{
onMatch:function(instance){
console.log("result=",instance.text())
},
onComplete:function(){
console.log("onComplete")
}
})
9)加載dex并使用其中的類
Java.openClassFile("/data/local/tmp/xxx.dex").load();
const a = Java.use("com.xxx.xxx.A");
四予颤、hook native的常用實(shí)現(xiàn)
1)查看目標(biāo)進(jìn)程加載到內(nèi)存中的模塊(和cat /proc/<PID>/maps 效果一致)
Java.perform(() {
var modules = Process.enumerateModules()
for (var i in modules) {
var module = modules[i]
# 這里做了一些條件篩選:只列出應(yīng)用內(nèi)模塊损肛,這樣可以觀察目標(biāo)應(yīng)用實(shí)際加載了自身哪些動(dòng)態(tài)庫或者dex
if (module.path.includes('<packageName>')) {
console.log('path:', module.path, 'base:', module.base, 'size:', module.size)
}
}
})
- 查看so的導(dǎo)出符號
Java.perform(() {
var exportsMethods = Module.enumerateExports('libBugly.so')
for (var i in exportsMethods) {
var m = exportsMethods[i]
console.log('type:', m.type, 'name:', m.name)
}
})
- hook 具體函數(shù)
Java.perform(() {
var addr = Module.findExportByName('libBugly.so', 'JNI_OnLoad')
console.log('addr:', addr)
if (addr) {
Interceptor.attach(addr, {
onEnter(args) {
console.log('JNI_OnLoad onEnter JavaVM:', args[0])
},
onLeave(retval) {
console.log('JNI_OnLoad onLeave retval:', retval)
}
})
}
})