监听点击事件
var jclazz = null;
var jobj = null;
function getObjClassName(obj) {
if (!jclazz) {
var jclazz = Java.use("java.lang.Class");
}
if (!jobj) {
var jobj = Java.use("java.lang.Object");
}
return jclazz.getName.call(jobj.getClass.call(obj));
}
function watch(obj, mtdName) {
var listener_name = getObjClassName(obj);
var target = Java.use(listener_name);
if (!target || !mtdName in target) {
return;
}
// send("[WatchEvent] hooking " + mtdName + ": " + listener_name);
target[mtdName].overloads.forEach(function (overload) {
overload.implementation = function () {
//send("[WatchEvent] " + mtdName + ": " + getObjClassName(this));
console.log("[WatchEvent] " + mtdName + ": " + getObjClassName(this))
return this[mtdName].apply(this, arguments);
};
})
}
function OnClickListener() {
Java.perform(function () {
//以spawn启动进程的模式来attach的话
Java.use("android.view.View").setOnClickListener.implementation = function (listener) {
if (listener != null) {
watch(listener, 'onClick');
}
return this.setOnClickListener(listener);
};
//如果frida以attach的模式进行attch的话
Java.choose("android.view.View$ListenerInfo", {
onMatch: function (instance) {
instance = instance.mOnClickListener.value;
if (instance) {
console.log("mOnClickListener name is :" + getObjClassName(instance));
watch(instance, 'onClick');
}
},
onComplete: function () {
}
})
})
}
获取app运行时信息
获取系统信息:hook android.os.Build ,Hook android 4大组件,File类等:例子
Java.perform(function () {
var Activity = Java.use("android.app.Activity");
Activity.startActivity.overload('android.content.Intent').implementation=function(p1){
console.log("Hooking android.app.Activity.startActivity(p1) successfully,p1="+p1);
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
// 查看Intent 携带的内容,大多数时候Bundle才放了数据,还是自己解析Bundle
console.log(decodeURIComponent(p1.toUri(256)));
this.startActivity(p1);
}
Activity.startActivity.overload('android.content.Intent', 'android.os.Bundle').implementation=function(p1,p2){
console.log("Hooking android.app.Activity.startActivity(p1,p2) successfully,p1="+p1+",p2="+p2);
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
console.log(decodeURIComponent(p1.toUri(256)));
this.startActivity(p1,p2);
}
Activity.startService.overload('android.content.Intent').implementation=function(p1){
console.log("Hooking android.app.Activity.startService(p1) successfully,p1="+p1);
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
console.log(decodeURIComponent(p1.toUri(256)));
this.startService(p1);
}
})
补充:
1、frida的objection框架,在hook一个类时,并没有hook类的
i
n
i
t
方
法
,
可
以
自
己
在
o
b
j
e
c
t
i
o
n
源
码
中
自
己
添
加
可
以
手
动
h
o
o
k
init方法,可以自己在objection源码中自己添加 可以手动hook
init方法,可以自己在objection源码中自己添加可以手动hookinit类:android hooking watch class_methoid java.io.File.$init --dump-args
2、frida snippets : android-file-system-access-hook 基本上把android文件读写的内容都hook了
hook 网络框架
主流的框架:URLHTTPConnection和OKHTTP(3)
代码apk看看使用了那个框架,hook框架,打印调用栈,定位到业务代码
frida反调试 antiFrida
java api ,native api,syscall(绕过libc.so)
github frida-detection-demo 可以看这个项目
void *detect_frida_loop(void *) {
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
inet_aton("0.0.0.0", &(sa.sin_addr));
int sock;
int i;
int ret;
char res[7];
while(1){
/*
* 1:Frida Server Detection
*/
//LOGI("entering frida server detect loop started");
for(i=20000;i<30000;i++){
sock = socket(AF_INET,SOCK_STREAM,0);
sa.sin_port = htons(i);
LOGI("entering frida server detect loop started,now i is %d",i);
if (connect(sock , (struct sockaddr*)&sa , sizeof sa) != -1) {
memset(res, 0 , 7);
send(sock, "\x00", 1, NULL);
send(sock, "AUTH\r\n", 6, NULL);
usleep(500); // Give it some time to answer
if ((ret = recv(sock, res, 6, MSG_DONTWAIT)) != -1) {
if (strcmp(res, "REJECT") == 0) {
LOGI("FOUND FRIDA SERVER: %s,FRIDA DETECTED [1] - frida server running on port %d!",APPNAME,i);
}else{
LOGI("not FOUND FRIDA SERVER");
}
}
}
close(sock);
}
}
}
frida native hook
1、替换参数
2、修改返回值
3、打印native层堆栈
4、native层函数,主动调用
5、native层函数替换(或者不执行)
function hook_nativelib(){
var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
var myfirstjniJNI = Module.findExportByName("libnative-lib.so", "Java_com_example_demoso1_MainActivity_myfirstjniJNI");
var myfirstjniJNI_invoke = new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"])
Interceptor.attach(myfirstjniJNI,{
onEnter:function(args){
console.log("Interceptor.attach myfirstjniJNI args:",args[0],args[1],args[2]);
console.log("args2 jstring is ",Java.vm.getEnv().getStringUtfChars( args[2],null).readCString())
console.log("myfirstjniJNI_invoke result => ",myfirstjniJNI_invoke(args[0],args[1],args[2]))
// 1
var newArgs2 = Java.vm.getEnv().newStringUtf("new args2 from frida");
args[2] = newArgs2;
},onLeave:function(retval){
console.log("Interceptor.attach myfirstjniJNI retval => ",retval)
console.log("retval jstring is ",Java.vm.getEnv().getStringUtfChars( retval,null).readCString())
var newRetval = Java.vm.getEnv().newStringUtf("new Retval from frida");
// 2
retval.replace(newRetval);
}
})
}
function hookandinvoke_add(){
var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
var r0add_addr = Module.findExportByName("libnative-lib.so", "_Z5r0addii");
Interceptor.attach(r0add_addr,{
onEnter:function(args){
console.log("x=>",args[0]," y=>",args[1]);
// 3
console.log('CCCryptorCreate called from:\n' +
Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\n') + '\n');
},onLeave:function(retval){
console.log("retval is => ",retval);
}
})
// 4
var r0add = new NativeFunction(r0add_addr,"int",["int","int"]);
var r0add_result = r0add(50,1);
console.log("invoke result is => ",r0add_result);
}
function hook_replace(){
var native_lib_addr = Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr => ",native_lib_addr);
var myfirstjniJNI = Module.findExportByName("libnative-lib.so", "Java_com_example_demoso1_MainActivity_myfirstjniJNI");
console.log("myfirstjniJNI addr => ",myfirstjniJNI);
var myfirstjniJNI_invoke = new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"])
// 5
Interceptor.replace(myfirstjniJNI,new NativeCallback(function(args0,args1,args2){
console.log("Interceptor.replace myfirstjniJNI args:",args0,args1,args2);
//var result = myfirstjniJNI_invoke(args0,args1,args2)
return Java.vm.getEnv().newStringUtf("new Retval from frida");;
},"pointer",["pointer","pointer","pointer"]))
}
function EnumerateAllExports(){
var modules = Process.enumerateModules();
//console.log("Process.enumerateModules => ",JSON.stringify(modules))
for(var i=0;i<modules.length;i++){
var module = modules[i];
var module_name = modules[i].name;
var exports = module.enumerateExports();
console.log("module_name=>",module_name," module.enumerateExports = > ",JSON.stringify(exports))
}
}
其他代码
function hook_JNI(){
var GetStringUTFChars_addr = null;
var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
//console.log(JSON.stringify(symbols))
for(var i = 0;i<symbols.length;i++){
var symbol = symbols[i].name;
if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
if(symbol.indexOf("GetStringUTFChars")>=0){
console.log("finally found GetStringUTFChars name :",symbol);
GetStringUTFChars_addr =symbols[i].address ;
console.log("finally found GetStringUTFChars address :",GetStringUTFChars_addr);
}
}
}
Interceptor.attach(GetStringUTFChars_addr,{
onEnter:function(args){
console.log("art::JNI::GetStringUTFChars(_JNIEnv*, _jstring*, unsigned char*)=>",args[0],Java.vm.getEnv().getStringUtfChars( args[1],null).readCString(),args[2]);
},onLeave:function(retval){
console.log("retval is => ",retval.readCString());
}
})
}
function replace_JNI(){
var NewStringUTF_addr = null;
var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
//console.log(JSON.stringify(symbols))
for(var i = 0;i<symbols.length;i++){
var symbol = symbols[i].name;
if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
if(symbol.indexOf("NewStringUTF")>=0){
console.log("finally found NewStringUTF_name :",symbol);
NewStringUTF_addr =symbols[i].address ;
console.log("finally found NewStringUTF_addr :",NewStringUTF_addr);
}
}
}
var NewStringUTF = new NativeFunction(NewStringUTF_addr,"pointer",["pointer","pointer"])
Interceptor.replace(NewStringUTF_addr,
new NativeCallback(function(parg1,parg2){
console.log("parg1,parg2=>",parg1,parg2.readCString());
var newPARG2 = Memory.allocUtf8String("newPARG2")
var result = NewStringUTF(parg1,newPARG2);
return result;
},"pointer",
["pointer","pointer"]))
}
function hook_RegisterNatives(){
var RegisterNatives_addr = null;
var symbols = Process.findModuleByName("libart.so").enumerateSymbols()
//console.log(JSON.stringify(symbols))
for(var i = 0;i<symbols.length;i++){
var symbol = symbols[i].name;
if((symbol.indexOf("CheckJNI")==-1)&&(symbol.indexOf("JNI")>=0)){
if(symbol.indexOf("RegisterNatives")>=0){
console.log("finally found RegisterNatives_name :",symbol);
RegisterNatives_addr =symbols[i].address ;
console.log("finally found RegisterNatives_addr :",RegisterNatives_addr);
}
}
}
if(RegisterNatives_addr!=null){
Interceptor.attach(RegisterNatives_addr,{
onEnter:function(args){
console.log("[RegisterNatives]method counts :",args[3]);
var env = args[0];
var jclass = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(jclass);
var methods_ptr = ptr(args[2]);
var method_count = parseInt(args[3]);
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var find_module = Process.findModuleByAddress(fnPtr_ptr);
console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
}
},onLeave:function(retval){
}
})
}else{
console.log("didn`t found RegisterNatives address")
}
}
setImmediate(hook_RegisterNatives);
function hook_pthread(){
var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
var time_addr = Module.findExportByName("libc.so", "time");
console.log("pthread_create_addr=>",pthread_create_addr)
Interceptor.attach(pthread_create_addr,{
onEnter:function(args){
console.log("args=>",args[0],args[1],args[2],args[4])
var libnativebaseaddress = Module.findBaseAddress("libnative-lib.so")
if(libnativebaseaddress!=null){
console.log("libnativebaseaddress=>",libnativebaseaddress);
//var detect_frida_loop_addr = args[2]-libnativebaseaddress;
//console.log("detect_frida_loop offset is =>",detect_frida_loop_addr)
if(args[2]-libnativebaseaddress == 64900){
console.log("found anti frida loop!,excute time_addr=>",time_addr);
args[2]=time_addr;
}
}
},onLeave:function(retval){
console.log("retval is =>",retval)
}
})
}
function replace_pthread(){
var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
console.log("pthread_create_addr=>",pthread_create_addr)
var pthread_create = new NativeFunction(pthread_create_addr,"int",["pointer","pointer","pointer","pointer"])
Interceptor.replace(pthread_create_addr,
new NativeCallback(function(parg1,parg2,parg3,parg4){
console.log(parg1,parg2,parg3,parg4)
var libnativebaseaddress = Module.findBaseAddress("libnative-lib.so")
if(libnativebaseaddress!=null){
console.log("libnativebaseaddress=>",libnativebaseaddress);
if(parg3-libnativebaseaddress == 64900){
return null;
}
}
return pthread_create(parg1,parg2,parg3,parg4)
},"int",["pointer","pointer","pointer","pointer"]))
}
function writeSomething(path,contents){
var fopen_addr = Module.findExportByName("libc.so", "fopen");
var fputs_addr = Module.findExportByName("libc.so", "fputs");
var fclose_addr = Module.findExportByName("libc.so", "fclose");
//console.log("fopen=>",fopen_addr," fputs=>",fputs_addr," fclose=>",fclose_addr);
var fopen = new NativeFunction(fopen_addr,"pointer",["pointer","pointer"])
var fputs = new NativeFunction(fputs_addr,"int",["pointer","pointer"])
var fclose = new NativeFunction(fclose_addr,"int",["pointer"])
console.log(path,contents)
var fileName = Memory.allocUtf8String(path);
var mode = Memory.allocUtf8String("a+");
var fp = fopen(fileName,mode);
var contentHello = Memory.allocUtf8String(contents);
var ret = fputs(contentHello,fp)
fclose(fp);
}
function EnumerateAllExports(){
/*
var packageName = null
Java.perform(function(){
packageName = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext().getPackageName();
console.log("package name is :",packageName)
})
*/
var modules = Process.enumerateModules();
//console.log("Process.enumerateModules => ",JSON.stringify(modules))
for(var i=0;i<modules.length;i++){
var module = modules[i];
var module_name = modules[i].name;
//var exports = module.enumerateExports();
var exports = module.enumerateSymbols();
console.log("module_name=>",module_name," module.enumerateExports = > ",JSON.stringify(exports))
for(var m =0; m<exports.length;m++){
console.log("m=>",m)
//writeSomething("/sdcard/"+packageName+"/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
writeSomething("/sdcard/settings/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
}
}
}
//应用以32位在64位终端环境下运行
//adb install --abi armeabi-v7a <path to apk>
function EnumerateAllExports() {
var linker = Process.getModuleByName("linker")
//console.log("exports=>",JSON.stringify(linker.enumerateSymbols()))
var call_function_addr = null;
var exports = linker.enumerateSymbols();
//console.log("module_name=>",module_name," module.enumerateExports = > ",JSON.stringify(exports))
for (var m = 0; m < exports.length; m++) {
//console.log("m=>",m)
//writeSomething("/sdcard/"+packageName+"/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
//writeSomething("/sdcard/settings/"+module_name+".txt", "type:"+exports[m].type+ " name:"+ exports[m].name+" address:"+exports[m].address+"\n")
if (exports[m].name == "__dl__ZL13call_functionPKcPFviPPcS2_ES0_") {
call_function_addr = exports[m].address;
console.log("found call_function_addr => ", call_function_addr)
hook_call_function(call_function_addr)
}
}
}
frida一些好用的框架脚本
frida_fuzzer_based_on_Stalker :
用于分析ollvm执行流 : Hooah-Trace
frida_hook_libart
jnitrace