首页
社区
课程
招聘
[原创]安卓hiddenapi访问绝技
发表于: 2021-8-16 17:33 26852

[原创]安卓hiddenapi访问绝技

2021-8-16 17:33
26852

下面摘录自官方

从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。如需详细了解有关此限制的决定,请参阅通过减少非 SDK 接口的使用来提高稳定性

随着每个 Android 版本的发布,会有更多非 SDK 接口受到限制。 我们知道这些限制会影响您的发布工作流,同时我们希望确保您拥有相关工具来检测非 SDK 接口的使用情况、有机会向我们提供反馈,并且有时间根据相应新政策做出规划和调整。

为最大程度地降低非 SDK 使用限制对开发工作流的影响,我们将非 SDK 接口分成了几个名单,这些名单界定了非 SDK 接口使用限制的严格程度(取决于应用的目标 API 级别)。下表介绍了这些名单:

尽管您目前仍可以使用某些非 SDK 接口(取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。如果您的应用依赖于非 SDK 接口,建议您开始计划迁移到 SDK 接口或其他替代方案。如果您无法为应用中的功能找到无需使用非 SDK 接口的替代方案,我们建议您请求添加新的公共 API

下表说明了当您的应用尝试访问屏蔽名单中的非 SDK 接口时可能会出现的预期行为。

1.谷歌建议开发者尽量使用公开的sdk接口,并没有禁止非sdk接口的使用

2.非sdk接口,开发者一般都是通过反射的机制进行使用,api>=28会进行限制,也就是说访问非sdk接口可能会失败

3.非sdk接口会进行等级分类,包括blacklist, greylist-max-x, greylist, whitelist等,其中greylist与whitelist不受限制

4.非sdk接口的等级可能会随着targetSdk以及系统sdk版本变化

Blacklist-api的配置文件一般在aops源码的aosp/frameworks/base/config/hiddenapi-force-blacklist.txt

以访问Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V为例

然后运行时抛出了异常NoSuchMethodException

​ 非sdk接口,greylist以及whitelist不受限制,但是blacklist以及greylist-max-x会进行限制

​ 这个是本文的主题,后面会通过手段达到目的

其内部调用了getMethod函数

第三个参数recursivePublicMethods为false,所以内部实际调用的是getDeclaredMethodInternal

getDeclaredMethodInternal为native函数,会调用到c++,源码可在art/runtime/native/java_lang_Class.cc中查找

大家可以留意一下art/runtime/native这个目录,包含了很多native-jni的函数实现

其内部调用了mirror::Class::GetDeclaredMethodInternal

源码中关键的地方做了标注,上述代码中有9个关键的地方,大家可自行查看,其中ShouldDenyAccessToMember为非sdk接口限制的关键函数

fn_get_access_context的源头是在java_lang_Class->getMethodIdInternal传过来的函数指针,即GetHiddenapiAccessContextFunction

也就是说,如果caller的domain值越小,能访问的hiddenapi范围越广。比如corePlatform能访问所有级别的api,但是application级别不能访问corePlatform以及platform级别的api。

###

这里返回了false(重点), 后边的代码省略,因为当前已经找到了两处返回false的地方(返回false表示可以访问)。

也就是说policy策略关闭时,可以自由访问hiddenapi,该方案可使用开源方案,但是需要适配不同的系统版本。

开源的方案是通过修改runtime内存实现的, 内存hidden_apipolicy的偏移值可因为系统版本,也可因为厂家定制导致不统一,所以该方案兼容性问题较大。

runtime->GetHiddenApiExemptions, 顾名思义:获取豁免的hiddenapi签名

该函数会遍历exemptions,只要有一个exemption,匹配当前访问的method->signature前缀,就可返回false。

无论MemberSignature的type_为field还是method,其返回值都是以class_name.c_str为前缀

另外,我们知道一个class的签名,形式都是如Ljava/lang/String;这种,肯定是以L开头的。

也就是说,想要调用setHiddenApiExemptions, 必须fake掉hiddenapi的限制。

所以看一下java_lang_Class中的GetHiddenapiAccessContextFunction

在此,domain_通过ComputeDomain初始化

直接搜索

代码中一共判断了5个文件位置,分别对应不同的domain

1.只是为了判断相关module的dir是否存在,一般都是存在的

2.artModule路径为/apex/com.android.art(android 11), 安卓10上的代码稍有区别

3.conscryptModule路径为/apex/com.android.conscrypt

4.apex的路径为/apex/

5.SystemFramework的路径为/system/framework

先随便找个debug的app看一下运行时apex路径都有哪些

这里有一个java.lang.System类,该类我们经常使用其加载so库,比如System.loadLibrary。

所以,我们可以通过System.loadLibrary,然后在native层的JNI_OnLoad中通过反射调用setHiddenApiExemptions(此时caller为java.lang.System.其domain级别为corePlatform),然后就可以随意访问hiddenapi了

核心代码

 
名单 说明
屏蔽名单 (blacklist) 无论应用的目标 API 级别是什么,您都无法使用的非 SDK 接口。 如果您的应用尝试访问其中任何一个接口,系统就会抛出错误
有条件屏蔽 (greylist-max-x) 从 Android 9(API 级别 28)开始,当有应用以该 API 级别为目标平台时,我们会在每个 API 级别分别限制某些非 SDK 接口。这些名单会以应用无法再访问该名单中的非 SDK 接口之前可以作为目标平台的最高 API 级别 (max-target-x) 进行标记。例如,在 Android Pie 中未被屏蔽、但现在已被 Android 10 屏蔽的非 SDK 接口会列入 max-target-p (greylist-max-p) 名单,其中的“p”表示 Pie 或 Android 9(API 级别 28)。如果您的应用尝试访问受目标 API 级别限制的接口,系统就会将此 API 视为已列入屏蔽名单
不支持 (greylist) 当前不受限制且您的应用可以使用的非 SDK 接口。 但请注意,这些接口不受支持,可能会在未发出通知的情况下随时发生更改。预计这些接口在未来的 Android 版本中会被有条件地屏蔽,并列在 max-target-x 名单中。
SDK (whitelist) 已在 Android 框架软件包索引中正式记录、受支持并且可以自由使用的接口。
 
访问方式 结果
Dalvik 指令引用某个字段 抛出 NoSuchFieldError
Dalvik 指令引用某个方法 抛出 NoSuchMethodError
通过 Class.getDeclaredField()Class.getField() 进行反射 抛出 NoSuchFieldException
通过 Class.getDeclaredMethod()Class.getMethod() 进行反射 抛出 NoSuchMethodException
通过 Class.getDeclaredFields()Class.getFields() 进行反射 结果中未获取到非 SDK 成员
通过 Class.getDeclaredMethods()Class.getMethods() 进行反射 结果中未获取到非 SDK 成员
通过 env->GetFieldID() 进行 JNI 调用 返回 NULL,抛出 NoSuchFieldError
通过 env->GetMethodID() 进行 JNI 调用 返回 NULL,抛出 NoSuchMethodError
 
 
 
//android-11.0.0_r36
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$ vim config/hiddenapi-force-blacklist.txt
 
Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/invoke/VarHandle;->acquireFence()V
Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->fullFence()V
Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->loadLoadFence()V
Ljava/lang/invoke/VarHandle;->releaseFence()V
Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->storeStoreFence()V
Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
//android-11.0.0_r36
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$ vim config/hiddenapi-force-blacklist.txt
 
Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/invoke/VarHandle;->acquireFence()V
Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->fullFence()V
Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->loadLoadFence()V
Ljava/lang/invoke/VarHandle;->releaseFence()V
Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->storeStoreFence()V
Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
try {
    Class runtimeClass = Class.forName("dalvik.system.VMRuntime");
    Method nativeLoadMethod = runtimeClass.getDeclaredMethod("setTargetSdkVersionNative",
            new Class[] {int.class});
 
    Log.d("whulzz", "setTargetSdkVersionNative success!");
} catch (Exception e) {
    e.printStackTrace();
}
try {
    Class runtimeClass = Class.forName("dalvik.system.VMRuntime");
    Method nativeLoadMethod = runtimeClass.getDeclaredMethod("setTargetSdkVersionNative",
            new Class[] {int.class});
 
    Log.d("whulzz", "setTargetSdkVersionNative success!");
} catch (Exception e) {
    e.printStackTrace();
}
08-16 12:57:13.379 21326 21326 W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [int]
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.Class.getMethod(Class.java:2072)
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.Class.getDeclaredMethod(Class.java:2050)
08-16 12:57:13.380 21326 21326 W System.err:    at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:17)
08-16 12:57:13.380 21326 21326 W System.err:    at com.example.demo.DemoApplication.onCreate(DemoApplication.java:26)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1190)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6584)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.access$1400(ActivityThread.java:226)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1889)
08-16 12:57:13.380 21326 21326 W System.err:    at android.os.Handler.dispatchMessage(Handler.java:107)
08-16 12:57:13.380 21326 21326 W System.err:    at android.os.Looper.loop(Looper.java:225)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.main(ActivityThread.java:7564)
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
08-16 12:57:13.380 21326 21326 W System.err:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
08-16 12:57:13.381 21326 21326 W System.err:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
08-16 12:57:13.379 21326 21326 W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [int]
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.Class.getMethod(Class.java:2072)
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.Class.getDeclaredMethod(Class.java:2050)
08-16 12:57:13.380 21326 21326 W System.err:    at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:17)
08-16 12:57:13.380 21326 21326 W System.err:    at com.example.demo.DemoApplication.onCreate(DemoApplication.java:26)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1190)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6584)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.access$1400(ActivityThread.java:226)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1889)
08-16 12:57:13.380 21326 21326 W System.err:    at android.os.Handler.dispatchMessage(Handler.java:107)
08-16 12:57:13.380 21326 21326 W System.err:    at android.os.Looper.loop(Looper.java:225)
08-16 12:57:13.380 21326 21326 W System.err:    at android.app.ActivityThread.main(ActivityThread.java:7564)
08-16 12:57:13.380 21326 21326 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
08-16 12:57:13.380 21326 21326 W System.err:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
08-16 12:57:13.381 21326 21326 W System.err:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
本文 Free reflection
setHiddenApiExemptions
dex放到bootclasspath
元反射
兼容安卓11 不太清楚
第三方ROM兼容性得分 优秀 良好
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    throws NoSuchMethodException, SecurityException {
    return getMethod(name, parameterTypes, false);
}
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    throws NoSuchMethodException, SecurityException {
    return getMethod(name, parameterTypes, false);
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
        throws NoSuchMethodException {
    if (name == null) {
        throw new NullPointerException("name == null");
    }
    if (parameterTypes == null) {
        parameterTypes = EmptyArray.CLASS;
    }
    for (Class<?> c : parameterTypes) {
        if (c == null) {
            throw new NoSuchMethodException("parameter type is null");
        }
    }
    Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
                                           : getDeclaredMethodInternal(name, parameterTypes);
    // Fail if we didn't find the method or it was expected to be public.
    if (result == null ||
        (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
        throw new NoSuchMethodException(getName() + "." + name + " "
                + Arrays.toString(parameterTypes));
    }
    return result;
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
        throws NoSuchMethodException {
    if (name == null) {
        throw new NullPointerException("name == null");
    }
    if (parameterTypes == null) {
        parameterTypes = EmptyArray.CLASS;
    }
    for (Class<?> c : parameterTypes) {
        if (c == null) {
            throw new NoSuchMethodException("parameter type is null");
        }
    }
    Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
                                           : getDeclaredMethodInternal(name, parameterTypes);
    // Fail if we didn't find the method or it was expected to be public.
    if (result == null ||
        (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
        throw new NoSuchMethodException(getName() + "." + name + " "
                + Arrays.toString(parameterTypes));
    }
    return result;
}
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
 
liuzhuangzhuang.das@virtualbox:~/work/aosp/art/runtime/native$ ls
dalvik_system_BaseDexClassLoader.cc   java_lang_Object.cc                  java_lang_reflect_Proxy.cc  java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h    java_lang_Object.h                   java_lang_reflect_Proxy.h   java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc              java_lang_ref_FinalizerReference.cc  java_lang_ref_Reference.cc  libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h               java_lang_ref_FinalizerReference.h   java_lang_ref_Reference.h   libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc              java_lang_reflect_Array.cc           java_lang_String.cc         native_util.h
dalvik_system_VMDebug.h               java_lang_reflect_Array.h            java_lang_StringFactory.cc  org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc            java_lang_reflect_Constructor.cc     java_lang_StringFactory.h   org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h             java_lang_reflect_Constructor.h      java_lang_String.h          org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc              java_lang_reflect_Executable.cc      java_lang_System.cc         org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h               java_lang_reflect_Executable.h       java_lang_System.h          scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc          java_lang_reflect_Field.cc           java_lang_Thread.cc         scoped_fast_native_object_access-inl.h
dalvik_system_ZygoteHooks.h           java_lang_reflect_Field.h            java_lang_Thread.h          sun_misc_Unsafe.cc
java_lang_Class.cc                    java_lang_reflect_Method.cc          java_lang_Throwable.cc      sun_misc_Unsafe.h
java_lang_Class.h                     java_lang_reflect_Method.h           java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc  java_lang_reflect_Parameter.cc       java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h   java_lang_reflect_Parameter.h        java_lang_VMClassLoader.h
liuzhuangzhuang.das@virtualbox:~/work/aosp/art/runtime/native$ ls
dalvik_system_BaseDexClassLoader.cc   java_lang_Object.cc                  java_lang_reflect_Proxy.cc  java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h    java_lang_Object.h                   java_lang_reflect_Proxy.h   java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc              java_lang_ref_FinalizerReference.cc  java_lang_ref_Reference.cc  libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h               java_lang_ref_FinalizerReference.h   java_lang_ref_Reference.h   libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc              java_lang_reflect_Array.cc           java_lang_String.cc         native_util.h
dalvik_system_VMDebug.h               java_lang_reflect_Array.h            java_lang_StringFactory.cc  org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc            java_lang_reflect_Constructor.cc     java_lang_StringFactory.h   org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h             java_lang_reflect_Constructor.h      java_lang_String.h          org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc              java_lang_reflect_Executable.cc      java_lang_System.cc         org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h               java_lang_reflect_Executable.h       java_lang_System.h          scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc          java_lang_reflect_Field.cc           java_lang_Thread.cc         scoped_fast_native_object_access-inl.h
dalvik_system_ZygoteHooks.h           java_lang_reflect_Field.h            java_lang_Thread.h          sun_misc_Unsafe.cc
java_lang_Class.cc                    java_lang_reflect_Method.cc          java_lang_Throwable.cc      sun_misc_Unsafe.h
java_lang_Class.h                     java_lang_reflect_Method.h           java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc  java_lang_reflect_Parameter.cc       java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h   java_lang_reflect_Parameter.h        java_lang_VMClassLoader.h
static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
                                               jstring name, jobjectArray args) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
  DCHECK(!Runtime::Current()->IsActiveTransaction());
  ObjPtr<mirror::Class> klass = DecodeClass(soa, javaThis);/*1.获取class.*/
  if (UNLIKELY(klass->IsObsoleteObject())) {
    ThrowRuntimeException("Obsolete Object!");
    return nullptr;
  }
  Handle<mirror::Method> result = hs.NewHandle(
      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
          soa.Self(),
          klass,
          soa.Decode<mirror::String>(name),
          soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
          GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
  if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
    return nullptr;
  }
  return soa.AddLocalReference<jobject>(result.Get());
}
static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
                                               jstring name, jobjectArray args) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
  DCHECK(!Runtime::Current()->IsActiveTransaction());
  ObjPtr<mirror::Class> klass = DecodeClass(soa, javaThis);/*1.获取class.*/
  if (UNLIKELY(klass->IsObsoleteObject())) {
    ThrowRuntimeException("Obsolete Object!");
    return nullptr;
  }
  Handle<mirror::Method> result = hs.NewHandle(
      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
          soa.Self(),
          klass,
          soa.Decode<mirror::String>(name),
          soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
          GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
  if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
    return nullptr;
  }
  return soa.AddLocalReference<jobject>(result.Get());
}
vim art/runtime//mirror/class.cc
template <PointerSize kPointerSize, bool kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
    Thread* self,
    ObjPtr<Class> klass,
    ObjPtr<String> name,
    ObjPtr<ObjectArray<Class>> args,
    const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
  // Covariant return types (or smali) permit the class to define
  // multiple methods with the same name and parameter types.
  // Prefer (in decreasing order of importance):
  //  1) non-hidden method over hidden
  //  2) virtual methods over direct
  //  3) non-synthetic methods over synthetic
  // We never return miranda methods that were synthesized by the runtime.
  StackHandleScope<3> hs(self);
  auto h_method_name = hs.NewHandle(name);
  if (UNLIKELY(h_method_name == nullptr)) {
    ThrowNullPointerException("name == null");
    return nullptr;
  }
  auto h_args = hs.NewHandle(args);
  Handle<Class> h_klass = hs.NewHandle(klass);
  constexpr hiddenapi::AccessMethod access_method = hiddenapi::AccessMethod::kNone;
  ArtMethod* result = nullptr;
  bool result_hidden = false;
  for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {/*4.遍历virtual method*/
    if (m.IsMiranda()) {
      continue;
    }
    auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
    // May cause thread suspension.
    ObjPtr<String> np_name = np_method->ResolveNameString();
    if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*5.判断方法名与参数类型*/
      if (UNLIKELY(self->IsExceptionPending())) {
        return nullptr;
      }
      continue;
    }
    bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*6.调用ShouldDenyAccessToMember*/
    if (!m_hidden && !m.IsSynthetic()) {
      // Non-hidden, virtual, non-synthetic. Best possible result, exit early.
      return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
    } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
      // Remember as potential result.
      result = &m;
      result_hidden = m_hidden;
    }
  }
 
  if ((result != nullptr) && !result_hidden) {
    // We have not found a non-hidden, virtual, non-synthetic method, but
    // if we have found a non-hidden, virtual, synthetic method, we cannot
    // do better than that later.
    DCHECK(!result->IsDirect());
    DCHECK(result->IsSynthetic());
  } else {
    for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {/*7.遍历direct method*/
      auto modifiers = m.GetAccessFlags();
      if ((modifiers & kAccConstructor) != 0) {
        continue;
      }
      auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
      // May cause thread suspension.
      ObjPtr<String> np_name = np_method->ResolveNameString();
      if (np_name == nullptr) {
        self->AssertPendingException();
        return nullptr;
      }
      if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*8.判断方法名与参数类型*/
        if (UNLIKELY(self->IsExceptionPending())) {
          return nullptr;
        }
        continue;
      }
      DCHECK(!m.IsMiranda());  // Direct methods cannot be miranda methods.
      bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*9.调用ShouldDenyAccessToMember*/
      if (!m_hidden && !m.IsSynthetic()) {
        // Non-hidden, direct, non-synthetic. Any virtual result could only have been
        // hidden, therefore this is the best possible match. Exit now.
        DCHECK((result == nullptr) || result_hidden);
        return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
      } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
        // Remember as potential result.
        result = &m;
        result_hidden = m_hidden;
      }
    }
  }
 
  return result != nullptr
      ? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
      : nullptr;
}
vim art/runtime//mirror/class.cc
template <PointerSize kPointerSize, bool kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
    Thread* self,
    ObjPtr<Class> klass,
    ObjPtr<String> name,
    ObjPtr<ObjectArray<Class>> args,
    const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
  // Covariant return types (or smali) permit the class to define
  // multiple methods with the same name and parameter types.
  // Prefer (in decreasing order of importance):
  //  1) non-hidden method over hidden
  //  2) virtual methods over direct
  //  3) non-synthetic methods over synthetic
  // We never return miranda methods that were synthesized by the runtime.
  StackHandleScope<3> hs(self);
  auto h_method_name = hs.NewHandle(name);
  if (UNLIKELY(h_method_name == nullptr)) {
    ThrowNullPointerException("name == null");
    return nullptr;
  }
  auto h_args = hs.NewHandle(args);
  Handle<Class> h_klass = hs.NewHandle(klass);
  constexpr hiddenapi::AccessMethod access_method = hiddenapi::AccessMethod::kNone;
  ArtMethod* result = nullptr;
  bool result_hidden = false;
  for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {/*4.遍历virtual method*/
    if (m.IsMiranda()) {
      continue;
    }
    auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
    // May cause thread suspension.
    ObjPtr<String> np_name = np_method->ResolveNameString();
    if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*5.判断方法名与参数类型*/
      if (UNLIKELY(self->IsExceptionPending())) {
        return nullptr;
      }
      continue;
    }
    bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*6.调用ShouldDenyAccessToMember*/
    if (!m_hidden && !m.IsSynthetic()) {
      // Non-hidden, virtual, non-synthetic. Best possible result, exit early.
      return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
    } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
      // Remember as potential result.
      result = &m;
      result_hidden = m_hidden;
    }
  }
 
  if ((result != nullptr) && !result_hidden) {
    // We have not found a non-hidden, virtual, non-synthetic method, but
    // if we have found a non-hidden, virtual, synthetic method, we cannot
    // do better than that later.
    DCHECK(!result->IsDirect());
    DCHECK(result->IsSynthetic());
  } else {
    for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {/*7.遍历direct method*/
      auto modifiers = m.GetAccessFlags();
      if ((modifiers & kAccConstructor) != 0) {
        continue;
      }
      auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
      // May cause thread suspension.
      ObjPtr<String> np_name = np_method->ResolveNameString();
      if (np_name == nullptr) {
        self->AssertPendingException();
        return nullptr;
      }
      if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*8.判断方法名与参数类型*/
        if (UNLIKELY(self->IsExceptionPending())) {
          return nullptr;
        }
        continue;
      }
      DCHECK(!m.IsMiranda());  // Direct methods cannot be miranda methods.
      bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*9.调用ShouldDenyAccessToMember*/
      if (!m_hidden && !m.IsSynthetic()) {
        // Non-hidden, direct, non-synthetic. Any virtual result could only have been
        // hidden, therefore this is the best possible match. Exit now.
        DCHECK((result == nullptr) || result_hidden);
        return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
      } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
        // Remember as potential result.
        result = &m;
        result_hidden = m_hidden;
      }
    }
  }
 
  return result != nullptr
      ? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
      : nullptr;
}
template<typename T>
inline bool ShouldDenyAccessToMember(T* member,
                                     const std::function<AccessContext()>& fn_get_access_context,
                                     AccessMethod access_method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(member != nullptr);
 
  // Get the runtime flags encoded in member's access flags.
  // Note: this works for proxy methods because they inherit access flags from their
  // respective interface methods.
  const uint32_t runtime_flags = GetRuntimeFlags(member);
 
  // Exit early if member is public API. This flag is also set for non-boot class
  // path fields/methods.
  if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
    return false;
  }
 
  // Determine which domain the caller and callee belong to.
  // This can be *very* expensive. This is why ShouldDenyAccessToMember
  // should not be called on every individual access.
  const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
  const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
 
  // Non-boot classpath callers should have exited early.
  DCHECK(!callee_context.IsApplicationDomain());
 
  // Check if the caller is always allowed to access members in the callee context.
  if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
    return false;
  }
 
  // Check if this is platform accessing core platform. We may warn if `member` is
  // not part of core platform API.
  /*5.根据domain级别区分对待hiddenapi策略*/
  switch (caller_context.GetDomain()) {
    case Domain::kApplication: {
      DCHECK(!callee_context.IsApplicationDomain());
 
      // Exit early if access checks are completely disabled.
      EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
      if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
        return false;
      }
 
      // If this is a proxy method, look at the interface method instead.
      member = detail::GetInterfaceMemberIfProxy(member);
 
      // Decode hidden API access flags from the dex file.
      // This is an O(N) operation scaling with the number of fields/methods
      // in the class. Only do this on slow path and only do it once.
      ApiList api_list(detail::GetDexFlags(member));
      DCHECK(api_list.IsValid());
 
      // Member is hidden and caller is not exempted. Enter slow path.
      return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
    }
 
    case Domain::kPlatform: {
      DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
 
      // Member is part of core platform API. Accessing it is allowed.
      if ((runtime_flags & kAccCorePlatformApi) != 0) {
        return false;
      }
 
      // Allow access if access checks are disabled.
      EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
      if (policy == EnforcementPolicy::kDisabled) {
        return false;
      }
 
      // If this is a proxy method, look at the interface method instead.
      member = detail::GetInterfaceMemberIfProxy(member);
 
      // Access checks are not disabled, report the violation.
      // This may also add kAccCorePlatformApi to the access flags of `member`
      // so as to not warn again on next access.
      return detail::HandleCorePlatformApiViolation(member,
                                                    caller_context,
                                                    access_method,
                                                    policy);
    }                                              
 
    case Domain::kCorePlatform: {
      LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
      UNREACHABLE();
    }
  }
}
template<typename T>
inline bool ShouldDenyAccessToMember(T* member,
                                     const std::function<AccessContext()>& fn_get_access_context,
                                     AccessMethod access_method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(member != nullptr);
 
  // Get the runtime flags encoded in member's access flags.
  // Note: this works for proxy methods because they inherit access flags from their
  // respective interface methods.
  const uint32_t runtime_flags = GetRuntimeFlags(member);
 
  // Exit early if member is public API. This flag is also set for non-boot class
  // path fields/methods.
  if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
    return false;
  }
 
  // Determine which domain the caller and callee belong to.
  // This can be *very* expensive. This is why ShouldDenyAccessToMember
  // should not be called on every individual access.
  const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
  const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
 
  // Non-boot classpath callers should have exited early.
  DCHECK(!callee_context.IsApplicationDomain());
 
  // Check if the caller is always allowed to access members in the callee context.
  if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
    return false;
  }
 
  // Check if this is platform accessing core platform. We may warn if `member` is
  // not part of core platform API.
  /*5.根据domain级别区分对待hiddenapi策略*/
  switch (caller_context.GetDomain()) {
    case Domain::kApplication: {
      DCHECK(!callee_context.IsApplicationDomain());
 
      // Exit early if access checks are completely disabled.
      EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
      if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
        return false;
      }
 
      // If this is a proxy method, look at the interface method instead.
      member = detail::GetInterfaceMemberIfProxy(member);
 
      // Decode hidden API access flags from the dex file.
      // This is an O(N) operation scaling with the number of fields/methods
      // in the class. Only do this on slow path and only do it once.
      ApiList api_list(detail::GetDexFlags(member));
      DCHECK(api_list.IsValid());
 
      // Member is hidden and caller is not exempted. Enter slow path.
      return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
    }
 
    case Domain::kPlatform: {
      DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
 
      // Member is part of core platform API. Accessing it is allowed.
      if ((runtime_flags & kAccCorePlatformApi) != 0) {
        return false;
      }
 
      // Allow access if access checks are disabled.
      EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
      if (policy == EnforcementPolicy::kDisabled) {
        return false;
      }
 
      // If this is a proxy method, look at the interface method instead.
      member = detail::GetInterfaceMemberIfProxy(member);
 
      // Access checks are not disabled, report the violation.
      // This may also add kAccCorePlatformApi to the access flags of `member`
      // so as to not warn again on next access.
      return detail::HandleCorePlatformApiViolation(member,
                                                    caller_context,
                                                    access_method,
                                                    policy);
    }                                              
 
    case Domain::kCorePlatform: {
      LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
      UNREACHABLE();
    }
  }
}
//java_lang_Class.cc
    Handle<mirror::Method> result = hs.NewHandle(
      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
          soa.Self(),
          klass,
          soa.Decode<mirror::String>(name),
          soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
          GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
//java_lang_Class.cc
    Handle<mirror::Method> result = hs.NewHandle(
      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
          soa.Self(),
          klass,
          soa.Decode<mirror::String>(name),
          soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
          GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
//java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread* self) {
  return [=]() REQUIRES_SHARED(Locks::mutator_lock_) { return GetReflectionCaller(self); };
}
//java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread* self) {
  return [=]() REQUIRES_SHARED(Locks::mutator_lock_) { return GetReflectionCaller(self); };
}
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
  return false;
}
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
  return false;
}
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
  return false;
}
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
  return false;
}
//hidden_api.h 
// Returns true if this domain is always allowed to access the domain of `callee`.
  bool CanAlwaysAccess(const AccessContext& callee) const {
    return IsDomainMoreTrustedThan(domain_, callee.domain_);
  }
//hidden_api.h 
// Returns true if this domain is always allowed to access the domain of `callee`.
  bool CanAlwaysAccess(const AccessContext& callee) const {
    return IsDomainMoreTrustedThan(domain_, callee.domain_);
  }
//art/libartbase/base/hiddenapi_domain.h
enum class Domain : char {
  kCorePlatform = 0,
  kPlatform,
  kApplication,
};
 
inline bool IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
  return static_cast<char>(domainA) <= static_cast<char>(domainB);
}
//art/libartbase/base/hiddenapi_domain.h
enum class Domain : char {
  kCorePlatform = 0,
  kPlatform,
  kApplication,
};
 
inline bool IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
  return static_cast<char>(domainA) <= static_cast<char>(domainB);
}
 
template<typename T>
bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) {
  DCHECK(member != nullptr);
  Runtime* runtime = Runtime::Current();
 
  EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
  DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
      << "Should never enter this function when access checks are completely disabled";
 
  MemberSignature member_signature(member);
 
  // Check for an exemption first. Exempted APIs are treated as white list.
  if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
    // Avoid re-examining the exemption list next time.
    // Note this results in no warning for the member, which seems like what one would expect.
    // Exemptions effectively adds new members to the whitelist.
    MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
    return false;
  }
.....
省略
....
template<typename T>
bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) {
  DCHECK(member != nullptr);
  Runtime* runtime = Runtime::Current();
 
  EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
  DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
      << "Should never enter this function when access checks are completely disabled";
 
  MemberSignature member_signature(member);
 
  // Check for an exemption first. Exempted APIs are treated as white list.
  if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
    // Avoid re-examining the exemption list next time.
    // Note this results in no warning for the member, which seems like what one would expect.
    // Exemptions effectively adds new members to the whitelist.
    MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
    return false;
  }
.....
省略
....
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
  return false;
}
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
  return false;
}
 
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
  return hidden_api_policy_;
}
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
  return hidden_api_policy_;
}
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
  // Avoid re-examining the exemption list next time.
  // Note this results in no warning for the member, which seems like what one would expect.
  // Exemptions effectively adds new members to the whitelist.
  MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
  return false;
}
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
  // Avoid re-examining the exemption list next time.
  // Note this results in no warning for the member, which seems like what one would expect.
  // Exemptions effectively adds new members to the whitelist.
  MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
  return false;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-8-16 20:53 被whulzz编辑 ,原因: 添加git仓库
收藏
免费 9
支持
分享
最新回复 (11)
雪    币: 2089
活跃值: (3933)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这种方式利用了加载so时JNI_OnLoad没有反射限制的漏洞进行反射限制绕过,如果不使用so的话其实FreeReflection也是可行的。
FreeReflection利用了安卓10上直接元反射设置反射限制的办法,安卓11利用DexFile设置父ClassLoader为null(BootClassLoader)的方法进行限制绕过,实际上targetsdk到30、31也是可以的,安卓12 Beta 4仍然可用,适合不方便加载so的项目。
2021-8-16 18:49
2
雪    币: 105
活跃值: (549)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
总结不错
2021-8-16 18:59
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
lhxdiao 这种方式利用了加载so时JNI_OnLoad没有反射限制的漏洞进行反射限制绕过,如果不使用so的话其实FreeReflection也是可行的。 FreeReflection利用了安卓10上直接元反射 ...
感谢大佬来访,https://github.com/whulzz1993/RePublic点个星星
2021-8-16 20:56
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
支持一下
2021-8-18 07:39
0
雪    币: 2677
活跃值: (5340)
能力值: ( LV10,RANK:177 )
在线值:
发帖
回帖
粉丝
6
mark
2021-8-21 09:24
0
雪    币: 163
活跃值: (509)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
mark
2021-12-9 08:59
0
雪    币: 2225
活跃值: (1078)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
mark
2023-2-8 13:34
0
雪    币: 650
活跃值: (4202)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
mark
2023-2-8 14:06
0
雪    币: 163
活跃值: (1623)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
lhxdiao 这种方式利用了加载so时JNI_OnLoad没有反射限制的漏洞进行反射限制绕过,如果不使用so的话其实FreeReflection也是可行的。 FreeReflection利用了安卓10上直接元反射 ...

安卓11利用DexFile设置父ClassLoader为null,caller 的domain按照我的理解是Domain::kPlatform。因为Android11源码static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file) {
    if (dex_file == nullptr) {
      // dex_file == nullptr && class_loader == nullptr(即被BootClassLoader加载的类),那么可信
      return ComputeDomain(/* is_trusted= */ class_loader.IsNull());
    }
    
    // 获取dex_file的Domain
    return dex_file->GetHiddenapiDomain();
  }. 那11以上为什么也可以绕过呢。Domain::kPlatform可以访问Domain::kCorePlatform级别的API吗?

最后于 2023-4-3 15:11 被学编程编辑 ,原因:
2023-4-3 15:08
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
学编程 lhxdiao 这种方式利用了加载so时JNI_OnLoad没有反射限制的漏洞进行反射限制绕过,如果不使用so的话其实FreeReflection ...

pthread_create创建线程,访问hiddenapi时caller为null,is_trusted 为true, domain为kCorePlatform。使用元反射访问hiddenapi时caller为javacore,domain也为kCorePlatform。所以这两种情况都能绕过hiddenapi的check

最后于 2023-4-4 18:38 被whulzz编辑 ,原因:
2023-4-4 18:32
0
雪    币: 163
活跃值: (1623)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
whulzz 学编程 lhxdiao 这种方式利用了加载so时JNI_OnLoad没有反射限制的漏洞进行反 ...
我们讲的不是同一个东西哦。你说的对,但元反射在Android 10就失效了。
2023-4-14 09:48
0
游客
登录 | 注册 方可回帖
返回
//