使用Frida打印Java类函数调用关系

  • A+
所属分类:逆向工程

使用Frida打印Java类函数调用关系

本文为看雪论坛文章

看雪论坛作者ID:无造



本文为看雪安卓高研3w班(8月班)优秀学员作品。


下面先让我们来看看讲师对学员学习成果的点评,以及学员的学习心得吧!


讲师点评


感谢Google的开源精神。通过对Android源码进行阅读,可以很快发现ART下类函数的四种调用:java调用java,java调用jni,jni调用java,jni调用jni;而java函数又有两种运行模式:interpreter模式和quick模式。

ART对不用的调用过程有着不同的处理逻辑。文章使用frida对ART下函数调用流程中的关键逻辑进行hook,同时结合对ART的定制,便可以得到APP运行过程中的执行轨迹,当然,对于函数调用过程中发生的参数传递以及返回结果等,事实上都可以通过对ART定制得到,进而能够构建一个动态分析沙箱。




学员感想


本题来自于3W班8月的第二题:请定制ART,完成对APP运行流程中所有的java类函数(包含java函数和jni函数)调用关系的trace。

对于Java层的单纯调用关系,可以比较方便的打印。参数的打印还是比较麻烦,Java对象的地址如何获取属性值等信息还是需要进一步深入研究。


ps. 题目附件请点击“阅读原文”下载。

好消息!!


现在看雪《安卓高级研修班》线下班 & 网课(12月班)开始同步招生啦!


以前没报上高研班的小伙伴赶快抓紧机会报名,升职加薪唾手可得!!





解题流程



根据之前的课程,可以得知有4种调用方式。其中java->java,java->jni在switch解释器下会通过DoCall方法。而jni->jni,jni->java则会通过反射相关的InvokeWithArgArray最后调用ArtMethod的Invoke方法。
 
这里考虑先使用frida验证运行逻辑,再修改源码刷机。
 
(这里编译源码将解释器改成Switch方便查看源码


首先写个Demo,实现这几种调用


public int JavaCallJava(int i){    Log.i("javajnitrace","step1->JavaCallJava onEnter");    return JavaCallJni(0x1111);} public int JniCallJava(int i){    int javajnitrace = Log.i("javajnitrace", "step4->JniCallJava onEnter " + i);    return 1;} public String JniCallJavaISS(int i, String s1, String s2){    int javajnitrace = Log.i("javajnitrace", "stepX->JniCallJavaISS onEnter " + i+" "+s1+" "+s2);    JavaCallJavaIII(0x1111,0x2222,0x3333);    return "JniCallJavaISS Called";} public int JavaCallJavaIII(int i, int j, int k){    Log.i("javajnitrace","stepX->JavaCallJavaIII onEnter");    //JavaCallJavaI17(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);    return i+j+k;}


extern "C"JNIEXPORT jint JNICALLJava_com_cwuzao_javajnitrace_MainActivity_JavaCallJni(JNIEnv *env, jobject thiz, jint i) {    __android_log_print(4, "javajnitrace", "step2->JavaCallJni onEnter %0x", i);    jclass class_MainActivity = env->FindClass("com/cwuzao/javajnitrace/MainActivity");    jmethodID  method_JniCallJni = env->GetMethodID(class_MainActivity, "JniCallJni", "(I)I");     int callResult = env->CallIntMethod(thiz, method_JniCallJni, 0x2222);    return  callResult + 1;} extern "C"JNIEXPORT jint JNICALLJava_com_cwuzao_javajnitrace_MainActivity_JniCallJni(JNIEnv *env, jobject thiz, jint i) {    __android_log_print(4, "javajnitrace", "step3->JniCallJni onEnter %0x",i);    jclass class_MainActivity = env->FindClass("com/cwuzao/javajnitrace/MainActivity");    jmethodID  method_JniCallJava = env->GetMethodID(class_MainActivity, "JniCallJava", "(I)I");    int callResult = env->CallIntMethod(thiz, method_JniCallJava, 0x3333);    return  callResult + 1;}


首先进行DoCall方法的HOOK


function DoCall_onEnter(args) {    var addr_ArtMethod = args[2].add(8).readPointer();    allocPrettyMethod.writeByteArray(allocPrettyMethodInit);    PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100);    var methodName = allocPrettyMethod.readCString();    if(methodName.indexOf(searchName) > -1){        var addr_Call_ArtMethod = args[0];        allocPrettyMethod.writeByteArray(allocPrettyMethodInit);        PrettyMethod(addr_ArtMethod_PrettyMethod, addr_Call_ArtMethod, allocPrettyMethod, 0x100);        var call_methodName = allocPrettyMethod.readCString();        console.log("DoCall:",methodName,"->", call_methodName);    }}

DoCall: void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)addr_InvokeWithArgArray onEnter-> int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int)addr_InvokeWithArgArray onEnter-> int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)addr_InvokeWithArgArray onLeaveaddr_InvokeWithArgArray onLeave

DoCall只能打印java层发起的调用,Jni反射调用的并不走这个流程。


查看InvokeWithArgArray的HOOK


这里也可以HOOK ArtMethod的Invoke,参数基本上一样,而且ArtMethod的调用会多很多。

Interceptor.attach(addr_InvokeWithArgArray, {       onEnter: function(args){           var addr_ArtMethod = args[1];           allocPrettyMethod.writeByteArray(allocPrettyMethodInit);           PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100);           var methodName = allocPrettyMethod.readCString();            if(methodName.indexOf(searchName) > -1 ){               this.methodName = methodName;               console.log("InvokeWithArgArray->",methodName,  args[1],  args[2],  args[3],  args[4]);           }       },       onLeave: function(retval){       }   });

DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)addr_ArtMethod6Invoke onEnteraddr_InvokeWithArgArray onEnter-> int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int)addr_ArtMethod6Invoke onEnteraddr_InvokeWithArgArray onEnter-> int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)addr_ArtMethod6Invoke onEnterDoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)

InvokeWithArgArray方法有个问题就是,我没有找到调用方的方法,虽然java->jni可以确定是哪里调用,但是jni->jni的可能会导致不知道上方是哪里调用的。

打印线程Tid


根据源码中这些方法都有Thread参数,所以尝试直接打印出tid,这样就算没有调用方,单一线程也只能同时运行一个方法。
 
源码中Thread可以直接调用GetTid获取线程ID,frida则可以根据内存分布,得知+0x10就是线程ID:

[3741]DoCall: void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)[3741]DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)[3741]DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)[3741]addr_ArtMethod6Invoke onEnter->int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)[3741]addr_ArtMethod6Invoke onEnter->int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int)[3741]addr_ArtMethod6Invoke onEnter->int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)[3741]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)

打印参数


InvokeWithArgArray调用的参数


InvokeWithArgArray主要是va_list的处理,我这里先写Demo使用AS确定内存分布。之后读取参数就比较方便了。
 
这里打印参数就统一打印U32值,也可以根据方法名,判断参数类型,然后自定义打印。

Interceptor.attach(addr_InvokeWithArgArray, {       onEnter: function(args){           var addr_ArtMethod = args[1];           allocPrettyMethod.writeByteArray(allocPrettyMethodInit);           PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100);           var methodName = allocPrettyMethod.readCString();            if(methodName.indexOf("com.cwuzao.javajnitrace") > -1 ){               this.showResult = true;               this.methodName = methodName;                this.tid = args[0].readPointer().add(0x10).readU32();               var argscount =  args[2].add(0x8).readU32();                console.log("["+this.tid+"]InvokeWithArgArray->",methodName,  args[1],  args[2],  args[3],  args[4]);               // console.log("["+this.tid+"]args count:", argscount, "NumBytes:", args[2].add(0xC).readU32());               // console.log("addr_InvokeWithArgArray args[0]->", hexdump(args[2].add(0x10).readPointer()));               var argspointer = args[2].add(0x10).readPointer();               for(var i=0; i< argscount; i++){                   console.log("["+this.tid+"]  args_", i+1,"->0x"+argspointer.add(i*4).readU32().toString(16));               }           }       },       onLeave: function(retval){           if(this.showResult){               console.log("["+this.tid+"]InvokeWithArgArray onLeave->",this.methodName, "n  result->0x"+retval.toString(16));           }       }   });

第一个参数是this指针,后续才是参数传递的值。


DoCall方法的参数打印


DoCall函数虽然可以打印调用关系,但是还没有为被调用方法初始化ShadowFrame,所以往下找了一些,最后HOOK了PerformCall里面的ArtInterpreterToInterpreterBridge和ArtInterpreterToCompiledCodeBridge。因为在DoCallCommon函数中初始化了ShadowFrame。
 
接下来就可以读取参数了,这里是通过修改参数,直接找到偏移进行读取,没有仔细理解ShadowFrame。

Interceptor.attach(addr_ArtInterpreterToInterpreterBridge, {    onEnter: function(args){         var addr_ArtMethod = args[2].add(8).readPointer();        allocPrettyMethod.writeByteArray(allocPrettyMethodInit);        PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100);        this.methodName = allocPrettyMethod.readCString();        if(this.methodName.indexOf(searchName) > -1){            this.showReuslt = true;            // this.result = args[4];            this.result = args[2].add(0x3C)            this.tid = args[0].add(0x10).readU32();            console.log("["+this.tid+"]ArtInterpreterToInterpreterBridge onEnter->",this.methodName);             // var regcount = args[2].add(0x30).readU32(); //            var registers_size_ = args[1].readU16();            var ins_size_ = args[1].add(0x2).readU16();            var outs_size_ = args[1].add(0x4).readU16();            // console.log("registers_size_->",registers_size_, "ins_size_->",ins_size_,"outs_size_->",outs_size_);             //读取参数            var argsPointer = args[2].add(0x3C + 4*outs_size_);            // console.log(hexdump(argsPointer));            for(var i=0; i< ins_size_; i++){                console.log("["+this.tid+"]  args_"+i+"->0x"+argsPointer.add(i*4).readU32().toString(16));            }        }    },    onLeave: function(retval){        if(this.showReuslt){            console.log("["+this.tid+"]ArtInterpreterToInterpreterBridge onLeave->",this.methodName,"n  result->0x"+this.result.readU32().toString(16));        }    }}); Interceptor.attach(addr_ArtInterpreterToCompiledCodeBridge, {    onEnter: function(args){         var addr_ArtMethod = args[3].add(8).readPointer();        allocPrettyMethod.writeByteArray(allocPrettyMethodInit);        PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100);        this.methodName = allocPrettyMethod.readCString();        if(this.methodName.indexOf(searchName) > -1){            this.showReuslt = true;            this.result = args[4];            this.tid = args[0].add(0x10).readU32();            console.log("["+this.tid+"]ArtInterpreterToCompiledCodeBridge onEnter->",this.methodName, args[1],args[2],args[3]);            var registers_size_ = args[3].add(0x30).readU32();             var argsPointer = args[3].add(0x3C);//这里并不是参数数量            for(var i=0; i< registers_size_; i++){                console.log("["+this.tid+"]  args_"+i+"->0x"+argsPointer.add(i*4).readU32().toString(16));            }        }    },    onLeave: function(retval){        if(this.showReuslt){            console.log("["+this.tid+"]ArtInterpreterToCompiledCodeBridge onLeave->",this.methodName,"n  result->0x"+this.result.readU16().toString(16));        }    }});

关于ArtInterpreterToCompiledCodeBridge的参数个数,不像ArtInterpreterToInterpreterBridge可以直接通过DexFile::CodeItem对象获取参数数量。所以直接读取的ShadowFrame的number_ofvregs打印所有寄存器值


打印查看效果


[22344]ArtInterpreterToInterpreterBridge onEnter-> void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View)[22344]  args_0->0x1309e270[22344]  args_1->0x1309da98[22344]DoCall: void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)[22344]ArtInterpreterToInterpreterBridge onEnter-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)[22344]  args_0->0x13097278[22344]  args_1->0x1234[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)[22344]ArtInterpreterToCompiledCodeBridge onEnter-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) 0x773f087068 0x0 0x7ff6a60400[22344]  args_0->0x13097278[22344]  args_1->0x1111[22344]InvokeWithArgArray-> int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int) 0x773f087188 0x7ff6a5f868 0x7ff6a5f860 0x772585b765[22344]  args_0->0x13097278[22344]  args_1->0x2222[22344]InvokeWithArgArray-> int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) 0x773f087128 0x7ff6a5eb78 0x7ff6a5eb70 0x772585b765[22344]  args_0->0x13097278[22344]  args_1->0x3333[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> void java.lang.StringBuilder.<init>()[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.StringBuilder java.lang.StringBuilder.append(int)[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.String java.lang.StringBuilder.toString()[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> int android.util.Log.i(java.lang.String, java.lang.String)[22344]InvokeWithArgArray onLeave-> int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)  result->0x1[22344]InvokeWithArgArray-> java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) 0x773f087158 0x7ff6a5eb78 0x7ff6a5eb70 0x772585d0e0[22344]  args_0->0x13097278[22344]  args_1->0x4444[22344]  args_2->0x12c41b58[22344]  args_3->0x12c41b78[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> void java.lang.StringBuilder.<init>()[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(int)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> java.lang.String java.lang.StringBuilder.toString()[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> int android.util.Log.i(java.lang.String, java.lang.String)[22344]DoCall: java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) -> int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)ArtInterpreterToInterpreterBridge onEnter-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)[22344]  args_0->0x13097278[22344]  args_1->0x1111[22344]  args_2->0x2222[22344]  args_3->0x3333[22344]DoCall: int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int) -> int android.util.Log.i(java.lang.String, java.lang.String)[22344]ArtInterpreterToInterpreterBridge onLeave-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)  result->0x6666[22344]InvokeWithArgArray onLeave-> java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)  result->0x12c41d70[22344]InvokeWithArgArray onLeave-> int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int)  result->0x2ArtInterpreterToCompiledCodeBridge onLeave-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)  result->0x3[22344]ArtInterpreterToInterpreterBridge onLeave-> int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)  result->0x3[22344]ArtInterpreterToInterpreterBridge onLeave-> void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View)  result->0x3

接下来就可以去修改源码刷机了


这里就偷懒了,刷机比较慢,只写调用,不读取参数了,只加了2行日志:

//reflection.ccstatic void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,                               ArtMethod* method, ArgArray* arg_array, JValue* result,                               const char* shorty)  //add  const char* methodName = method->PrettyMethod().c_str();  if(strstr(methodName, "com.cwuzao.javajnitrace")){        LOG(ERROR)<< android::base::StringPrintf("[%d]InvokeWithArgArray %s", soa.Self()->GetTid(),methodName);  }  //addend} //interpreter_common.ccbool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame,            const Instruction* inst, uint16_t inst_data, JValue* result) {  //add  const char* methodName = shadow_frame.GetMethod()->PrettyMethod().c_str();  if(strstr(methodName, "com.cwuzao.javajnitrace")){        LOG(ERROR)<< android::base::StringPrintf("[%d]DoCall %s->%s", self->GetTid(), methodName, called_method->PrettyMethod().c_str());  }  //addend}

[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.<clinit>()->void java.lang.System.loadLibrary(java.lang.String)[6825]DoCall void androidx.appcompat.app.AppCompatActivity.onCreate(android.os.Bundle)->void androidx.appcompat.app.AppCompatActivity.onCreate(android.os.Bundle)[6825]DoCall void androidx.appcompat.app.AppCompatActivity.setContentView(int)->void androidx.appcompat.app.AppCompatActivity.setContentView(int)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->java.lang.String com.cwuzao.javajnitrace.MainActivity.stringFromJNI()[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->void android.widget.TextView.setText(java.lang.CharSequence)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity$1.<init>(com.cwuzao.javajnitrace.MainActivity)->void com.cwuzao.javajnitrace.MainActivity$1.<init>(com.cwuzao.javajnitrace.MainActivity)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity$1.<init>(com.cwuzao.javajnitrace.MainActivity)->void java.lang.Object.<init>()[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->void android.view.View.setOnClickListener(android.view.View$OnClickListener)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity$2.<init>(com.cwuzao.javajnitrace.MainActivity)->void com.cwuzao.javajnitrace.MainActivity$2.<init>(com.cwuzao.javajnitrace.MainActivity)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity$2.<init>(com.cwuzao.javajnitrace.MainActivity)->void java.lang.Object.<init>()[6825]DoCall void com.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->void android.view.View.setOnClickListener(android.view.View$OnClickListener)[6825]DoCall void com.cwuzao.javajnitrace.MainActivity$1.onClick(android.view.View)->int com.cwuzao.javajnitrace.MainActivity.JavaCallJava(int)[6825]DoCall int android.util.Log.i(java.lang.String, java.lang.String)->int android.util.Log.i(java.lang.String, java.lang.String)[6825]DoCall int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)->int com.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)[6825]InvokeWithArgArray int com.cwuzao.javajnitrace.MainActivity.JniCallJni(int)[6825]InvokeWithArgArray int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)[6825]DoCall int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)->void java.lang.StringBuilder.<init>()[6825]DoCall int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)->java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[6825]DoCall int com.cwuzao.javajnitrace.MainActivity.JniCallJava(int)->java.lang.StringBuilder java.lang.StringBuilder.append(int)[6825]DoCall java.lang.String java.lang.StringBuilder.toString()->java.lang.String java.lang.StringBuilder.toString()[6825]DoCall int android.util.Log.i(java.lang.String, java.lang.String)->int android.util.Log.i(java.lang.String, java.lang.String)[6825]InvokeWithArgArray java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->void java.lang.StringBuilder.<init>()[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->java.lang.StringBuilder java.lang.StringBuilder.append(int)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->java.lang.String java.lang.StringBuilder.toString()[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->int android.util.Log.i(java.lang.String, java.lang.String)[6825]DoCall java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String)->int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)[6825]DoCall int com.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)->int android.util.Log.i(java.lang.String, java.lang.String)

这里打印反而有问题,刚调用函数打印调用和被调用方法名字一样?没理解什么原因,应该是哪里还要设置ShadowFrame,Frida那边正常,这边也能看到上一步调用,倒也不影响流程查看。
 
为了测试方便,这里加了过滤,直接hook strstr即可修改过滤字符。



使用Frida打印Java类函数调用关系
- End -

使用Frida打印Java类函数调用关系


看雪ID:无造

https://bbs.pediy.com/user-home-571058.htm

  *本文由看雪论坛 无造 原创,转载请注明来自看雪社区。


使用Frida打印Java类函数调用关系

推荐文章++++

使用Frida打印Java类函数调用关系

* Linux Kernel Pwn_1_Double fetch

Linux Kernel Pwn_0_kernel ROP与驱动调试

* 使用Frida分析动态注册jni函数绑定流程

* OneFuzz踩坑教程

* 最右sign-v2签名算法追踪及逆向还原





使用Frida打印Java类函数调用关系
公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]



求分享

求点赞

使用Frida打印Java类函数调用关系

求在看


使用Frida打印Java类函数调用关系
“阅读原文一起来充电吧!

本文始发于微信公众号(看雪学院):使用Frida打印Java类函数调用关系

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: