美文网首页
Android native层监控JNI方法调用

Android native层监控JNI方法调用

作者: carrys17 | 来源:发表于2023-09-10 20:09 被阅读0次

    分析一些东西时,想实现监控Android JNI函数的调用,网上找了下,发现这个库https://github.com/w296488320/JnitraceForCpp实现了这样的效果,但是实际使用时,我自己遇到了一些问题,比如hook打印jobject数据时,陷入了死循环,然后调用FindClass解析时,有时也会闪退等,最终自己处理问题后的版本如下https://github.com/carrys17/Study-Notes/tree/master/JniHelper
    主要改动:
    1、在getJObjectInfo等方法中,会调用Jni方法去解析jobject数据,例如调用CallObjectMethod时,因为前边hook了CallObjectMethodV导致死循环。处理方式就是判断定义一个CallObjectMethod_SAFE方法,如果判断到CallObjectMethodV_f不为空(即CallObjectMethodV函数已经被hook了),则调用它而不是CallObjectMethod方法。

            jobject CallObjectMethod_SAFE(JNIEnv *env, jobject jobj, jmethodID jmethodId,...){
    //            WLOGD("enter CallObjectMethod_SAFE method, CallObjectMethodV_f = %p",CallObjectMethodV_f);
                if (CallObjectMethodV_f){
                    va_list args;
                    jobject result;
                    va_start(args,jmethodId);
                    result = CallObjectMethodV_f(env, jobj,jmethodId,args);
                    va_end(args);
                    return result;
                }else{
                    return env->CallObjectMethod(jobj,jmethodId);
                }
            }
    
            // 直接通过toString获取jobject 信息
            const char *getJObjectToString(JNIEnv *env, jobject obj) {
                if(!g_method_id_Object_toString){
                    g_method_id_Object_toString =
                            GetMethodID_SAFE(env,FindClass_SAFE(env,ENCRYPT("java/lang/Object")), ENCRYPT("toString"),
                                             ENCRYPT("()Ljava/lang/String;"));
                }
                jobject jobj = CallObjectMethod_SAFE(env, obj, g_method_id_Object_toString);
                return GetStringUTFChars_SAFE(env,(jstring) (jobj), nullptr);
            }
    

    2、FindClass方法在部分JNI方法hook了之后再去调用时,会触发闪退,从日志的行为看是一直打印了CallObjectMethod方法然后闪退,这里之所以会去调用FindClass,其实是为了最终拿到Object_toString的method_id,所以在init初始化的时候保存一个Object_toString的method_id

        void init(JNIEnv *env, bool isForbidMode, const std::list<std::string> &forbid_list, const std::list<std::string> &filter_list){
                WLOGD("enter init method");
                g_method_id_Class_getName =
                        env->GetMethodID(env->FindClass(ENCRYPT("java/lang/Class")), ENCRYPT("getName"),
                                                     ENCRYPT("()Ljava/lang/String;"));
                g_method_id_Object_toString =
                        env->GetMethodID(env->FindClass(ENCRYPT("java/lang/Object")), ENCRYPT("toString"),
                                         ENCRYPT("()Ljava/lang/String;"));
    
                gForbidSoList = std::list<std::string>(forbid_list);
                gFilterSoList = std::list<std::string>(filter_list);
                gIsForbidMode = isForbidMode;
                WLOGD("init success!");
            }
    

    其他的一些就是避免我们主动调用的JNI方法解析数据时,过滤掉不让干扰我们分析目标的JNI方法打印。
    3、因为我的场景是注入so到目标里边,所以我们打印堆栈过滤一些so时,需要调用dladdr((void *) __builtin_return_address(1), &info); 而不是__builtin_return_address(0),因为__builtin_return_address(0)获取到的永远是我自己注入的so名称

    相关文章

      网友评论

          本文标题:Android native层监控JNI方法调用

          本文链接:https://www.haomeiwen.com/subject/jrgsvdtx.html