hook so 常用工具
SubstrateCydia-需root
frIDA--需root :Frida是一款基于Python + JavaScript的Hook与调试框架。从Java层到Native层的Hook无所不能。我们分析app的参数加密的时候,经常使用他来帮助分析我们分析调试。
VA系列-非root(VA、VXP、SandVXposed)
frida方式hook材料准备
- heibaobao.apk
- jadx
- ida
- root手机(小米4- androdi6.0)
- frida环境
目标:
通过静态分析,学会使用frida对so 函数的hook,替换或更改返回值。
静态分析
jadx打开heibaobao.apk
myJNI->check 实现在libJniTest.so中
[Asm] 纯文本查看 复制代码 public native String check(Object obj, String str, String str2);
ida打开libJniTest.so(解压apk中得到)
[C] 纯文本查看 复制代码 int __fastcall Java_demo2_jni_com_myapplication_myJNI_check(_JNIEnv *a1, int a2, int a3, int a4, int a5)
其实check函数包括了一下签名校验,如果签名不一致,则杀死进程,不过我们这里的目的不是采用回编译修改so或修改arm指令方式过签名校验。
我们这里其实就是想打印check方法的输出参数;并修改返回值
frida hook 该函数
基本步骤
frida环境准备-pc+手机端(略)
ida查看其偏移地址
获取libJniTest内存地址
获取或计算Java_demo2_jni_com_myapplication_myJNI_check的绝对地址
ida 查看函数的偏移地址,并记录在下来(text:00000EB8)备用
fridia脚本
编写hook_libJniTest_check.js脚本
[JavaScript] 纯文本查看 复制代码 function hook_myJNI_check(){
// 获取 So 地址
var libJniTest_addr = Module.findBaseAddress("libJniTest.so");
if (libJniTest_addr) {
var myapplication_myJNI_check = Module.findExportByName("libJniTest.so", "Java_demo2_jni_com_myapplication_myJNI_check");
console.log("Java_demo2_jni_com_myapplication_myJNI_check 地址:", myapplication_myJNI_check);
}
send("libJniTest.so地址:" + libJniTest_addr);
//未导出的函数我们需要手动的计算出函数地址,然后将其转化成一个NativePointer的对象然后进行hook操作
// 函数地址 = so地址.add(偏移地址 + 1) // 是否+1 取决于cpu平台型号
//thumb和arm指令的区分,地址最后一位的奇偶性来进行标志,所以这里还需加1
var myJNI_check = libJniTest_addr.add(0x0EB8+1) // 0x 代表 16进制 text:00000EBC
send('myJNI->check地址:'+myJNI_check)
// hook 这个地址
// hook 函数不需要写参数类型、参数个数
Interceptor.attach(myJNI_check, {
// 进入函数前Hook
onEnter: function(args){
console.log("Java_demo2_jni_com_myapplication_myJNI_check 进来:"); //
console.log("参数4--密码:", args[4],"这里是jstring 的地址,所有打印该参数是需要转换为Str.");
console.log("参数3--用户:", jstring2Str(args[3]));
console.log("参数4--密码:", jstring2Str(args[4]));
send(args[4])
},
// 完成函数hook, retval是返回值
onLeave: function(retval){
console.log("Java_demo2_jni_com_myapplication_myJNI_check 离开:"); //
//retval.replace("恭喜你,这是你要的返回");
send(retval);
console.log("函数返回old值:", jstring2Str(retval));
//构造env,然后调用env.newStringUtf创建jstring (想知道env有哪些js方法可调用,看查看frida-java-master/lib/env.js 源码)
var env = Java.vm.getEnv();
var jstring = env.newStringUtf("frida hook native 你要的jstring");
retval.replace(ptr(jstring));//修改返回值
console.log("函数返回new值:", jstring2Str(retval));
}
});
}
function jstring2Str(jstring) { //从frida_common_funs.js中copy出来
var ret;
Java.perform(function() {
var String = Java.use("java.lang.String");
ret = Java.cast(jstring, String);//jstring->String
});
return ret;
}
function main() {
hook_myJNI_check();
}
setImmediate(main);
运行脚本
frida -U --no-pause -f demo2.jni.com.myapplication -l hook_libJniTest_check.js
frida hook so函数后的日志与界面
frida常用脚本
这里仅提供截图,大部分javascritpy脚本都来自github,可通过名字去github搜索
|