本文為看雪論壇文章
看雪論壇作者ID:無造
好消息!!
現在看雪《安卓高級研修班》線下班 & 網課(12月班)開始同步招生啦!
以前沒報上高研班的小夥伴趕快抓緊機會報名,升職加薪唾手可得!!
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"); 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方法的HOOKfunction 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 onLeaveDoCall只能列印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]); 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)); } } });
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[2].add(0x3C) this.tid = args[0].add(0x10).readU32(); console.log("["+this.tid+"]ArtInterpreterToInterpreterBridge onEnter->",this.methodName); var registers_size_ = args[1].readU16(); var ins_size_ = args[1].add(0x2).readU16(); var outs_size_ = args[1].add(0x4).readU16(); var argsPointer = args[2].add(0x3C + 4*outs_size_); 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行日誌:static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa, ArtMethod* method, ArgArray* arg_array, JValue* result, const char* shorty) 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); } } bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data, JValue* result) { 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()); } }[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即可修改過濾字符。看雪ID:無造
https://bbs.pediy.com/user-home-571058.htm
*本文由看雪論壇 無造 原創,轉載請註明來自看雪社區。