Skip to main content

JniTrace

misskingAbout 3 min

There are currently many JniTrace solutions, and Jni call monitoring is essential for the analysis process. To protect the code, most key functions are native. The key functions of nativeization must deal with Jni-related APIs. The ROM-level JniTrace directly outputs the internal output of function execution instead of hook printing. So the advantage is that it can bypass certain detections. The disadvantage is that not all jni functions are currently processed. And it targets all jni functions of all dynamic libraries, resulting in huge output. The following introduces the functions of this column

jni
jni

JNI module name

The name of the target dynamic library. In the output of stack 1, some output can be filtered out.

JNI method name

JNI log output is only activated when the specified function is executed.

CallMethod filtering

The log of CallMethod is only triggered when the specified function in Java is called through Jni.

no stack

Since it is a global monitoring output, the amount of jni calls is very large. In this case, stack output is also performed, which may lead to a crash with a certain probability. Therefore, the output to the stack can be turned off to reduce the probability of problems. The output log is as follows

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

stack1

The earliest encapsulated stack output solution is based on self-encapsulated so implementation. When there are too many jni calls, it crashes. The output log is as follows

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)

stack2

Later I found the stack output solution that comes with the android system. The test may also crash. The output log is as follows

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>