跳至主要內容

JniTrace

missking大约 3 分钟

目前有很多JniTrace方案,Jni的调用监控是分析过程必不可少的。为了保护代码,大多数关键函数都是native化的。而native化的关键函数必然少不了和Jni相关的api打交道。而该ROM级JniTrace是直接在函数执行的内部输出,而非hook打印。所以优势在于能绕过一定检测。缺点就是目前并没有对所有jni函数进行处理。并且其针对的是所有动态库的所有jni函数,导致输出量会巨大。下面介绍该栏目的功能

jni
jni

JNI模块名称

目标动态库的名称,在堆栈1的输出中,可以过滤掉一些输出。

JNI函数名称

当指定函数执行时,才激活JNI日志输出

CallMethod过滤

当通过Jni调用Java中的指定函数时,才触发CallMethod的日志

无堆栈输出

由于是针对全局的监控输出,所以jni的调用量非常巨大,在这种情况下还进行堆栈输出,有一定概率导致崩溃。所以可以关闭到堆栈的输出,来降低出问题的概率。输出日志如下

mikrom           /* TID 9698 */
mikrom           [+] JNIEnv->GetMethodID
mikrom           |- jclass           :Landroid/system/ErrnoException;
mikrom           |- char*            :0x70727c7900
mikrom           |:     <init>
mikrom           |- char*            :0x70727c80b0
mikrom           |:     (Ljava/lang/String;I)V
mikrom           /* TID 9698 */
mikrom           [+] JNIEnv->CallNonvirtualVoidMethodV
mikrom           /* TID 9698 */
mikrom           [+] JNIEnv->GetStringUTFChars
mikrom           |- jboolean*        : 0
mikrom           |= char*            : rc4
mikrom           |- jmethodID        :0x0   {void android.system.ErrnoException.<init>(java.lang.String, int)}
mikrom           |- va_list          :0x6fe62a4420
mikrom           /* TID 9698 */
mikrom           [+] JNIEnv->GetStringUTFChars
mikrom           |- jboolean*        : 0
mikrom           |= char*            : cn.mik.kmodule.callback.Cipher
mikrom           |:     jstring      : stat
mikrom           |:     jint         : 2

堆栈输出1

最早先封装的堆栈输出方案,是基于自封装的so实现,jni调用过多时出现崩溃,输出日志如下

mikrom           /* TID 11307 */
mikrom           [+] JNIEnv->GetStringUTFChars
mikrom           |- jboolean*        : 0
mikrom           |= char*            : cn.mik.kmodule.callback.MessageDigest
-------------------------mikrom Backtrace-------------------------
#00 pc 00000000000ade48  /apex/com.android.runtime/lib64/bionic/libc.so (tgkill+8)
#01 pc 0000000000000c24  /system/lib64/libkbacktrace.so (_Z10kbacktracebPKc+148)
#02 pc 000000000062f994  /apex/com.android.art/lib64/libart.so (_ZN3art11ShowVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEPKcPhS4_+260)
#03 pc 00000000004be984  /apex/com.android.art/lib64/libart.so (_ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh+1316)
#04 pc 00000000005923dc  /apex/com.android.art/lib64/libart.so (_ZN3artL18Class_classForNameEP7_JNIEnvP7_jclassP8_jstringhP8_jobject+92)
mikrom           /* TID 11307 */
mikrom           [+] JNIEnv->GetStringUTFChars
mikrom           |- jboolean*        : 0
mikrom           |= char*            : cn.mik.kmodule.callback.MessageDigest
-------------------------mikrom Backtrace-------------------------
#00 pc 00000000000ade48  /apex/com.android.runtime/lib64/bionic/libc.so (tgkill+8)
#01 pc 0000000000000c24  /system/lib64/libkbacktrace.so (_Z10kbacktracebPKc+148)
#02 pc 000000000062f994  /apex/com.android.art/lib64/libart.so (_ZN3art11ShowVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEPKcPhS4_+260)
#03 pc 00000000004be984  /apex/com.android.art/lib64/libart.so (_ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh+1316)
#04 pc 00000000005923dc  /apex/com.android.art/lib64/libart.so (_ZN3artL18Class_classForNameEP7_JNIEnvP7_jclassP8_jstringhP8_jobject+92)

堆栈输出2

后来找到的android系统中自带的堆栈输出方案。测试同样有崩溃的可能,输出日志如下

mikrom           /* TID 12030 */
mikrom           [+] JNIEnv->GetMethodID
mikrom           |- jclass           :Ljava/io/InputStream;
mikrom           |- char*            :0x6ff6727160
mikrom           |:     read
mikrom           |- char*            :0x6ff6727158
mikrom           |:     ([BII)I
mikrom #00 pc 000000000062f2a8  /apex/com.android.art/lib64/libart.so (art::print_stack_trace()+88)
mikrom #01 pc 000000000062f6c8  /apex/com.android.art/lib64/libart.so (art::ShowVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, char const*, _jclass*, char const*, char const*, _jmethodID*)+680)
mikrom #02 pc 00000000004828f4  /apex/com.android.art/lib64/libart.so (art::JNI<false>::GetMethodID(_JNIEnv*, _jclass*, char const*, char const*)+660)
mikrom #03 pc 000000000002c0e0  <anonymous:0000006ff660e000>
mikrom           /* TID 12030 */
mikrom           [+] JNIEnv->CallIntMethodV
mikrom           |- jmethodID        :0x11   {int java.io.InputStream.read(byte[], int, int)}
mikrom           |- va_list          :0x6ff642c6e0
mikrom           |:     jobject      : 0x6ff642c4b0
mikrom           |:     jint         : 0
mikrom           |:     jint         : 8192
mikrom           /* TID 12030 */
mikrom           [+] JNIEnv->GetStringUTFChars
mikrom           |- jboolean*        : 0
mikrom           |= char*            : cn.mik.kmodule.callback.MessageDigest
mikrom #00 pc 000000000062f2a8  /apex/com.android.art/lib64/libart.so (art::print_stack_trace()+88)
mikrom #01 pc 00000000004be980  /apex/com.android.art/lib64/libart.so (art::JNI<false>::GetStringUTFChars(_JNIEnv*, _jstring*, unsigned char*)+1312)
mikrom #02 pc 00000000005923d8  /apex/com.android.art/lib64/libart.so (art::Class_classForName(_JNIEnv*, _jclass*, _jstring*, unsigned char, _jobject*)+88)
mikrom #03 pc 00000000000978ec  /system/framework/arm64/boot.oat (art_jni_trampoline+124)
mikrom #04 pc 000000000022eb10  /system/framework/arm64/boot.oat (java.lang.Class.forName+112)
mikrom #05 pc 0000000000209398  /apex/com.android.art/lib64/libart.so (nterp_helper+152)
mikrom #06 pc 00000000000ffb16  /apex/com.android.art/javalib/core-oj.jar (java.lang.krom.Reflect.forName+2)
mikrom #07 pc 0000000000209334  /apex/com.android.art/lib64/libart.so (nterp_helper+52)
mikrom #08 pc 00000000001002d4  /apex/com.android.art/javalib/core-oj.jar (java.lang.krom.Reflect.on)
mikrom #09 pc 0000000000209334  /apex/com.android.art/lib64/libart.so (nterp_helper+52)
mikrom #10 pc 00000000000ff4b4  /apex/com.android.art/javalib/core-oj.jar (java.lang.krom.KCommon.CallInjectMethod+76)
mikrom #11 pc 00000000001a5b18  /system/framework/arm64/boot.oat (java.security.MessageDigest.update+184)
mikrom #12 pc 0000000000145930  /system/framework/arm64/boot.oat (sun.security.util.ManifestEntryVerifier.update+208)
mikrom #13 pc 00000000001018cc  /system/framework/arm64/boot.oat (java.util.jar.JarVerifier.update+92)
mikrom #14 pc 0000000000312bf8  /system/framework/arm64/boot.oat (java.util.jar.JarVerifier$VerifierStream.read+200)
mikrom #15 pc 000000000021096c  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+556)
mikrom #16 pc 0000000000281328  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+1032)
mikrom #17 pc 000000000062efb4  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, std::__va_list)+468)
mikrom #18 pc 000000000062f21c  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+92)
mikrom #19 pc 0000000000489f4c  /apex/com.android.art/lib64/libart.so (art::JNI<false>::CallIntMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+684)
mikrom #20 pc 000000000002c160  <anonymous:0000006ff660e000>