依据之前的课程,能够得悉有 4 种调用形式。其中 java->java,java->jni 在 switch 解释器下会通过 DoCall 办法。而 jni->jni,jni->java 则会通过反射相干的 InvokeWithArgArray 最初调用 ArtMethod 的 Invoke 办法。
这里思考先应用 frida 验证运行逻辑,再批改源码刷机。
(这里编译源码将解释器改成 Switch 不便查看源码)
首先写个 Demo,实现这几种调用
publicintJavaCallJava(inti) {Log.i( “javajnitrace”, “step1->JavaCallJava onEnter”); returnJavaCallJni(0x1111); } publicintJniCallJava(inti) {intjavajnitrace = Log.i( “javajnitrace”, “step4->JniCallJava onEnter “+ i); return1; } publicString JniCallJavaISS(inti, String s1, String s2) {intjavajnitrace = Log.i( “javajnitrace”, “stepX->JniCallJavaISS onEnter “+ i+ ” “+s1+ ” “+s2); JavaCallJavaIII(0x1111, 0x2222, 0x3333); return”JniCallJavaISS Called”; } publicintJavaCallJavaIII(inti, intj, intk) {Log.i( “javajnitrace”, “stepX->JavaCallJavaIII onEnter”); //JavaCallJavaI17(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17); returni+j+k; }
extern”C” JNIEXPORT jint JNICALL Java_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”); intcallResult = env->CallIntMethod(thiz, method_JniCallJni, 0x2222); returncallResult + 1; } extern”C” JNIEXPORT jint JNICALL Java_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”); intcallResult = env->CallIntMethod(thiz, method_JniCallJava, 0x3333); returncallResult + 1; }
首先进行 DoCall 办法的 HOOK
functionDoCall_onEnter(args) {varaddr_ArtMethod = args[ 2].add(8).readPointer; allocPrettyMethod.writeByteArray(allocPrettyMethodInit); PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100); varmethodName = allocPrettyMethod.readCString; if(methodName.indexOf(searchName) > -1){varaddr_Call_ArtMethod = args[ 0]; allocPrettyMethod.writeByteArray(allocPrettyMethodInit); PrettyMethod(addr_ArtMethod_PrettyMethod, addr_Call_ArtMethod, allocPrettyMethod, 0x100); varcall_methodName = allocPrettyMethod.readCString; console.log(“DoCall:”,methodName, “->”, call_methodName); } }
DoCall: voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) addr_InvokeWithArgArray onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) addr_InvokeWithArgArray onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) addr_InvokeWithArgArray onLeave addr_InvokeWithArgArray onLeave
DoCall 只能打印 java 层发动的调用,Jni 反射调用的并不走这个流程。
查看 InvokeWithArgArray 的 HOOK
这里也能够 HOOK ArtMethod 的 Invoke,参数基本上一样,而且 ArtMethod 的调用会多很多。
Interceptor.attach(addr_InvokeWithArgArray, { onEnter: function( args) {varaddr_ArtMethod = args[ 1]; allocPrettyMethod.writeByteArray(allocPrettyMethodInit); PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100); varmethodName = 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: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) addr_ArtMethod6InvokeonEnter addr_InvokeWithArgArrayonEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) addr_ArtMethod6InvokeonEnter addr_InvokeWithArgArrayonEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) addr_ArtMethod6InvokeonEnter DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> intandroid.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: voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) [3741]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) [3741]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) [3741]addr_ArtMethod6Invoke onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) [3741]addr_ArtMethod6Invoke onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) [3741]addr_ArtMethod6Invoke onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) [3741]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String)
打印参数
InvokeWithArgArray 调用的参数
InvokeWithArgArray 次要是 va_list 的解决,我这里先写 Demo 应用 AS 确定内存散布。之后读取参数就比拟不便了。
这里打印参数就对立打印 U32 值,也能够依据办法名,判断参数类型,而后自定义打印。
Interceptor.attach(addr_InvokeWithArgArray, { onEnter: function( args) {varaddr_ArtMethod = args[ 1]; allocPrettyMethod.writeByteArray(allocPrettyMethodInit); PrettyMethod(addr_ArtMethod_PrettyMethod, addr_ArtMethod, allocPrettyMethod, 0x100); varmethodName = allocPrettyMethod.readCString; if(methodName.indexOf( “com.cwuzao.javajnitrace”) > -1){this.showResult = true; this.methodName = methodName; this.tid = args[ 0].readPointer.add(0x10).readU32; varargscount = 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)); varargspointer = args[2].add(0x10).readPointer; for(vari= 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){varaddr_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; // varregisters_size_ = args[1].readU16; varins_size_ = args[1].add(0x2).readU16; varouts_size_ = args[1].add(0x4).readU16; // console.log(“registers_size_->”,registers_size_, “ins_size_->”,ins_size_,”outs_size_->”,outs_size_); // 读取参数 varargsPointer = args[2].add(0x3C+ 4outs_size_); // console.log(hexdump(argsPointer)); for(vari= 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){varaddr_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]); varregisters_size_ = args[3].add(0x30).readU32; varargsPointer = args[3].add(0x3C); // 这里并不是参数数量 for(vari= 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 打印所有寄存器值
XM 外汇 MT4 metatrader4service.net
[22344]ArtInterpreterToInterpreterBridge onEnter-> voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View) [22344] args_0-> 0x1309e270 [22344] args_1-> 0x1309da98 [22344]DoCall: voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) [22344]ArtInterpreterToInterpreterBridge onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) [22344] args_0-> 0x13097278 [22344] args_1-> 0x1234 [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) [22344]ArtInterpreterToCompiledCodeBridge onEnter-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) 0x773f0870680x00x7ff6a60400 [22344] args_0-> 0x13097278 [22344] args_1-> 0x1111 [22344]InvokeWithArgArray-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) 0x773f0871880x7ff6a5f8680x7ff6a5f8600x772585b765 [22344] args_0-> 0x13097278 [22344] args_1-> 0x2222 [22344]InvokeWithArgArray-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) 0x773f0871280x7ff6a5eb780x7ff6a5eb700x772585b765 [22344] args_0-> 0x13097278 [22344] args_1-> 0x3333 [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> voidjava.lang.StringBuilder.<init> [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.StringBuilder java.lang.StringBuilder.append(int) [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> java.lang.String java.lang.StringBuilder.toString [22344]DoCall: intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) [22344]InvokeWithArgArray onLeave-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) result-> 0x1 [22344]InvokeWithArgArray-> java.lang.String com.cwuzao.javajnitrace.MainActivity.JniCallJavaISS(int, java.lang.String, java.lang.String) 0x773f0871580x7ff6a5eb780x7ff6a5eb700x772585d0e0 [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) -> voidjava.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) -> intandroid.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) -> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int) ArtInterpreterToInterpreterBridge onEnter-> intcom.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: intcom.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int) -> intandroid.util.Log.i(java.lang.String, java.lang.String) [22344]ArtInterpreterToInterpreterBridge onLeave-> intcom.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-> intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) result-> 0x2 ArtInterpreterToCompiledCodeBridge onLeave-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) result-> 0x3 [22344]ArtInterpreterToInterpreterBridge onLeave-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) result-> 0x3 [22344]ArtInterpreterToInterpreterBridge onLeave-> voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View) result-> 0x3
接下来就能够去批改源码刷机了
这里就偷懒了,刷机比较慢,只写调用,不读取参数了,只加了 2 行日志:
//reflection.cc staticvoidInvokeWithArgArray(constScopedObjectAccessAlreadyRunnable& soa, ArtMethod method, ArgArray arg_array, JValue result, constchar shorty) //add constchar 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.cc boolDoCall(ArtMethod called_method, Thread self, ShadowFrame& shadow_frame, constInstruction inst, uint16_tinst_data, JValue result) {//add constchar 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 voidcom.cwuzao.javajnitrace.MainActivity.<clinit>-> voidjava.lang.System.loadLibrary(java.lang.String) [6825]DoCall voidandroidx.appcompat.app.AppCompatActivity.onCreate(android.os.Bundle)-> voidandroidx.appcompat.app.AppCompatActivity.onCreate(android.os.Bundle) [6825]DoCall voidandroidx.appcompat.app.AppCompatActivity.setContentView(int)-> voidandroidx.appcompat.app.AppCompatActivity.setContentView(int) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->java.lang.String com.cwuzao.javajnitrace.MainActivity.stringFromJNI [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)-> voidandroid.widget.TextView.setText(java.lang.CharSequence) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity$ 1.<init>(com.cwuzao.javajnitrace.MainActivity)-> voidcom.cwuzao.javajnitrace.MainActivity$ 1.<init>(com.cwuzao.javajnitrace.MainActivity) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity$ 1.<init>(com.cwuzao.javajnitrace.MainActivity)-> voidjava.lang.Object.<init> [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)-> voidandroid.view.View.setOnClickListener(android.view.View$OnClickListener) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)->android.view.View androidx.appcompat.app.AppCompatActivity.findViewById(int) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity$ 2.<init>(com.cwuzao.javajnitrace.MainActivity)-> voidcom.cwuzao.javajnitrace.MainActivity$ 2.<init>(com.cwuzao.javajnitrace.MainActivity) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity$ 2.<init>(com.cwuzao.javajnitrace.MainActivity)-> voidjava.lang.Object.<init> [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity.onCreate(android.os.Bundle)-> voidandroid.view.View.setOnClickListener(android.view.View$OnClickListener) [6825]DoCall voidcom.cwuzao.javajnitrace.MainActivity$ 1.onClick(android.view.View)-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJava(int) [6825]DoCall intandroid.util.Log.i(java.lang.String, java.lang.String)-> intandroid.util.Log.i(java.lang.String, java.lang.String) [6825]DoCall intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int)-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJni(int) [6825]InvokeWithArgArray intcom.cwuzao.javajnitrace.MainActivity.JniCallJni(int) [6825]InvokeWithArgArray intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int) [6825]DoCall intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int)-> voidjava.lang.StringBuilder.<init> [6825]DoCall intcom.cwuzao.javajnitrace.MainActivity.JniCallJava(int)->java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) [6825]DoCall intcom.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 intandroid.util.Log.i(java.lang.String, java.lang.String)-> intandroid.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)-> voidjava.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)-> intandroid.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)-> intcom.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int) [6825]DoCall intcom.cwuzao.javajnitrace.MainActivity.JavaCallJavaIII(int, int, int)-> intandroid.util.Log.i(java.lang.String, java.lang.String)
这里打印反而有问题,刚调用函数打印调用和被调用办法名字一样?没了解什么起因,应该是哪里还要设置 ShadowFrame,Frida 那边失常,这边也能看到上一步调用,倒也不影响流程查看。
为了测试不便,这里加了过滤,间接 hook strstr 即可批改过滤字符。