反射系统限制API方式

79 阅读1分钟

1、反射访问系统限制API

前提:Android 9以后通过 hidden 隐藏系统级API,反射无法访问API问题;

结论:

  1. 系统自带的 App 具备系统签名,所以具有访问系统限制API的能力,反射访问不受限制(保证可以编译通过即可);
  2. 第三方App需要访问系统限制API,需要通过漏洞来绕开API限制能力;思路:因为System.loadLibrary 加载 so 库时, domain 级别较高是 corePlatform,因为可以在该时机在 jni 层反射修改 VMRuntimesetHiddenApiExemptions ,从而放开API访问限制;
//
// Created by liuzhuangzhuang on 2021/8/16.
//
#define DEBUG
#include <android/log.h>
#include <jni.h>
 
#define LOG_TAG "apifake"
#define DEBUG
#ifdef DEBUG
#define ALOGD(fmt, args...)  do {__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args);} while(0)
#define ALOGI(fmt, args...)  do {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args);} while(0)
#else
#define ALOGD(fmt, args...)  do {} while(0)
#define ALOGI(fmt, args...)  do {} while(0)
#endif
#define ALOGE(fmt, args...)  do {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args);} while(0)
 
typedef union {
    JNIEnv* env;
    void* venv;
} UnionJNIEnvToVoid;
 
bool setApiBlacklistExemptions(JNIEnv* env) {
    /*=================在这里使用了ZygoteInit,而不是VMRuntime, 效果一样==================*/
    jclass zygoteInitClass = env->FindClass("com/android/internal/os/ZygoteInit");
    if (zygoteInitClass == nullptr) {
        ALOGE("not found class");
        env->ExceptionClear();
        return false;
    }
 
 
    jmethodID setApiBlackListApiMethod =
            env->GetStaticMethodID(zygoteInitClass,
                    "setApiBlacklistExemptions",
                    "([Ljava/lang/String;)V");
    if (setApiBlackListApiMethod == nullptr) {
        env->ExceptionClear();
        setApiBlackListApiMethod =
                env->GetStaticMethodID(zygoteInitClass,
                        "setApiDenylistExemptions",
                        "([Ljava/lang/String;)V");
    }
 
    if (setApiBlackListApiMethod == nullptr) {
        ALOGE("not found method");
        return false;
    }
 
    jclass stringCLass = env->FindClass("java/lang/String");
 
    jstring fakeStr = env->NewStringUTF("L");
 
    jobjectArray fakeArray = env->NewObjectArray(
            1, stringCLass, NULL);
 
    env->SetObjectArrayElement(fakeArray, 0, fakeStr);
 
    env->CallStaticVoidMethod(zygoteInitClass,
            setApiBlackListApiMethod, fakeArray);
 
    env->DeleteLocalRef(fakeStr);
    env->DeleteLocalRef(fakeArray);
    ALOGD("fakeapi success!");
    return true;
}
 
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv* env = NULL;
 
    ALOGD("JNI_OnLoad");
 
    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) {
        ALOGE("ERROR: GetEnv failed");
        goto bail;
    }
    env = uenv.env;
 
    if (!setApiBlacklistExemptions(env)) {
        ALOGE("failed");
        goto bail;
    }
    result = JNI_VERSION_1_6;
 
    bail:
    return result;
}

2、参考文档

安卓hiddenapi访问绝技