一、課程目標

1.了解Frida-Native-Hook讀寫、主動調用

2.了解常見的frida_trace工具

3.了解控制流混淆對抗新思路

二、工具

1.教程Demo(更新)

2.jadx-gui

3.VS Code

4.jeb

三、課程內容

1.Frida寫數據

 復制代碼 隱藏代碼
//一般寫在app的私有目錄里,不然會報錯:failed to open file (Permission denied)(實際上就是權限不足)
var file_path = "/data/user/0/com.zj.wuaipojie/test.txt";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
        file_handle.write(data); //寫入數據
        file_handle.flush(); //刷新
        file_handle.close(); //關閉
}

2.Frida_inlineHook與讀寫匯編

什么是inlinehook?

Inline hook(內聯鉤子)是一種在程序運行時修改函數執行流程的技術。它通過修改函數的原始代碼,將目標函數的執行路徑重定向到自定義的代碼段,從而實現對目標函數的攔截和修改。

簡單來說就是可以對任意地址的指令進行hook讀寫操作

常見inlinehook框架:

Android-Inline-Hook

whale

Dobby

substrate

PS:Frida的inlinehook不是太穩定,崩潰是基操,另外新版的frida兼容性會比較好

 復制代碼 隱藏代碼
function inline_hook() {
    var soAddr = Module.findBaseAddress("lib52pojie.so");
    if (soAddr) {
        var func_addr = soAddr.add(0x10428);
        Java.perform(function () {
            Interceptor.attach(func_addr, {
                onEnter: function (args) {
                    console.log(this.context.x22); //注意此時就沒有args概念了
                    this.context.x22 = ptr(1); //賦值方法參考上一節課
                },
                onLeave: function (retval) {
                }
            }
            )
        })
    }
}
  1. 將地址的指令解析成匯編
 復制代碼 隱藏代碼
var soAddr = Module.findBaseAddress("lib52pojie.so");
var codeAddr = Instruction.parse(soAddr.add(0x10428));
console.log(codeAddr.toString());
  1. Frida Api
  2. arm轉hex
 復制代碼 隱藏代碼
var soAddr = Module.findBaseAddress("lib52pojie.so");
var codeAddr = soAddr.add(0x10428);
Memory.patchCode(codeAddr, 4, function(code) {
const writer = new Arm64Writer(code, { pc: codeAddr });
writer.putBytes(hexToBytes("20008052"));
writer.flush();
});
function hexToBytes(str) {
var pos = 0;
var len = str.length;
if (len % 2 != 0) {
    return null;
}
len /= 2;
var hexA = new Array();
for (var i = 0; i < len; i++) {
    var s = str.substr(pos, 2);
    var v = parseInt(s, 16);
    hexA.push(v);
    pos += 2;
}
return hexA;
}

3.普通函數與jni函數的主動調用

nativefunction

數據類型描述void無返回值pointer指針int整數long長整數char字符float浮點數double雙精度浮點數bool布爾值  復制代碼 隱藏代碼
var funcAddr = Module.findBaseAddress("lib52pojie.so").add(0x1054C);
//聲明函數指針
//NativeFunction的第一個參數是地址,第二個參數是返回值類型,第三個[]里的是傳入的參數類型(有幾個就填幾個)
var aesAddr = new NativeFunction(funcAddr , 'pointer', ['pointer', 'pointer']);
var encry_text = Memory.allocUtf8String("OOmGYpk6s0qPSXEPp4X31g==");    //開辟一個指針存放字符串       
var key = Memory.allocUtf8String('wuaipojie0123456'); 
console.log(aesAddr(encry_text ,key).readCString());

jni的主動調用

參考java的主動調用,簡單快捷

4.Trace

工具名稱描述鏈接jnitrace老牌,經典,信息全,攜帶方便jnitracejnitrace-engine基于jnitrace,可定制化jnitrace-enginejtrace定制方便,信息全面,直接在_agent.js或者_agent_stable.js 里面加自己的邏輯就行jtracehook_art.js可提供jni trace,可以靈活的增加你需要hook的函數hook_art.jsJNI-Frida-Hook函數名已定義,方便定位JNI-Frida-Hookfindhashida插件,可用于檢測加解密函數,也可作為Native Trace庫findhashStalkerfrida官方提供的代碼跟蹤引擎,可以在Native層方法級別,塊級別,指令級別實現代碼修改,代碼跟蹤Stalkersktrace類似 ida 指令 trace 功能sktracefrida-qbdi-tracer速度比frida stalker快,免補環境frida-qbdi-tracer PS:這次介紹的幾款工具都是基礎用法,更深入的還需要大家去看看源碼學習

4.1 frida-trace

官方文檔

frida-trace 可以一次性監控一堆函數地址。還能打印出比較漂亮的樹狀圖,不僅可以顯示調用流程,還能顯示調用層次。并且貼心的把不同線程調用結果用不同的顏色區分開了。

大佬整理的文檔:

frida-trace

 復制代碼 隱藏代碼
D:\> frida-trace.exe --help  
用法: frida-trace [options] target

位置參數:  
   args                  extra arguments and/or target

選項:  
  -h, --help               顯示幫助  
  -D ID, --device ID       通過 ID 連接設備  
  -U, --usb                通過 USB 連接設備  
  -R, --remote             連接到遠程 frida-server  
  -H HOST, --host HOST     連接到遠程 host 上的 frida-server  
  --certificate 證書       設置證書,通過 TSL 與 host 交互                          
  --origin ORIGIN          設置連接到遠程服務的 "Origin" 頭部  
  --token TOKEN            設置 與host 認證  
  --keepalive-interval     時間間隔。0表示禁用,-1表示基于傳輸自動選擇                          
  --p2p                    建立一個點對點的連接  
  --stun-server ADDRESS    設置--p2p 的 STUN 服務地址  
  --relay address,username,password,turn-{udp,tcp,tls}  添加--p2p 延遲  
  -f TARGET, --file TARGET       spawn 模式  
  -F, --attach-frontmost         附加到最前端的 application  
  -n NAME, --attach-name NAME    附加到一個名字                          
  -N IDENTIFIER, --attach-identifier IDENTIFIER   附加到標識符                          
  -p PID, --attach-pid PID        附加到 pid                          
  -W PATTERN, --await PATTERN  
                        await spawn matching PATTERN  
  --stdio {inherit,pipe}  
                        stdio behavior when spawning (defaults to “inherit”)  
  --aux option          set aux option when spawning, such as “uid=(int)42” (supported types are:  
                        string, bool, int)  
  --realm {native,emulated}            附件的范圍  
  --runtime {qjs,v8}                   使用的腳本運行環境  
  --debug                              啟用 Node.js 兼容的腳本調試器  
  --squelch-crash                      如果啟用,將不會將崩潰報告轉儲到控制臺  
  -O FILE, --options-file FILE         將信息保存到文件中
  --version                            顯示版本號
  • -i / -a: 跟蹤 C 函數或 so 庫中的函數。
  • PS:-a 包含模塊+偏移跟蹤,一般用于追蹤未導出函數,例子:-a "lib52pojie.so!0x4793c"

包含/排除模塊或函數:

  • -I : 包含指定模塊。
  • -X : 排除指定模塊。

Java 方法跟蹤:

  • -j JAVA_METHOD: 包含 Java 方法。
  • -J JAVA_METHOD: 排除 Java 方法。

附加方式:

  • -f:通過 spwan 方式啟動
  • -F:通過 attach 方式附加當前進程

日志輸出:

-o:日志輸出到文件

 復制代碼 隱藏代碼
使用案例:
frida-trace -U -F -I "lib52pojie.so" -i "Java_" #附加當前進程并追蹤lib52pojie.so里的所有Java_開頭的jni導出函數

4.2jnitrace

前提

 復制代碼 隱藏代碼
pip install jnitrace==3.3.0

使用方法

 復制代碼 隱藏代碼
jnitrace -m attach -l lib52pojie.so com.zj.wuaipojie -o trace.json //attach模式附加52pojie.so并輸出日志

-l libnative-lib.so- 用于指定要跟蹤的庫

-m <spawn|attach>- 用于指定要使用的 Frida 附加機制

-i <regex>- 用于指定應跟蹤的方法名稱,例如,-i Get -i RegisterNatives將僅包含名稱中包含 Get 或 RegisterNatives 的 JNI 方法

-e <regex>- 用于指定跟蹤中應忽略的方法名稱,例如,-e ^Find -e GetEnv將從結果中排除所有以 Find 開頭或包含 GetEnv 的 JNI 方法名稱

-I <string>- 用于指定應跟蹤的庫的導出

-E <string>用于指定不應跟蹤的庫的導出

-o path/output.json- 用于指定jnitrace存儲所有跟蹤數據的輸出路徑

4.3sktrace

 復制代碼 隱藏代碼
python sktrace.py -m attach -l lib52pojie.so -i 0x103B4 com.zj.wuaipojie

5.控制流混淆對抗新發現

細品sec2023安卓賽題

JEB Decompiler 5.5.0.202311022109 mod by CXV

PS:注意jdk的版本要高于17,不然打不開

下載地址

恐怖如斯的效果對比圖: