Android9 开端,体系开端针对非SDK接口做约束。

在国内做 Android 开发的都经历过,如果想要实现一些黑科技,性能优化,或者沙箱等功用,常常需求反射一些躲藏接口。
随着安卓开产生态的逐步规范化,以及体系的性能与安全性的提高,一方面不再答应直接调用非SDK接口避免安全与安稳性问题,另一方面也无需经过黑科技来提高运用的性能。

关于Android突破非SDK接口限制的延伸

developer.android.com/guide/app-c…

然而,国内的运用开发,尤其是多年的老产品,包含了许多的祖传代码。直接全方面修正需求很高的开发成本,甚至由于无百分百替代计划需求修正产品逻辑。除非是功用完全失效,不然做这类兼容对事务“有害无益”(即,消耗了资源但没有提高事务价值)。

而且,非SDK接口的约束通常会区别等级,随 TargetSdkVersion 的提高扩展约束规模。尤其是每一两年,运用商场或有关部门,都会要求活跃的运用有必要提高 TargetSdkVersion 才能上架或升级,就导致做相应的适配成为一件有必要重视的事情。

有一位技术大神 weishu,曾经在自己的博客中连载两篇分析如何打破约束,并开源了相关代码。

关于Android突破非SDK接口限制的延伸

一种绕过Android P对非SDK接口约束的简单办法
weishu.me/2018/06/07/…

另一种绕过 Android P以上非公开API约束的办法
weishu.me/2019/03/16/…

Github – FreeReflection
github.com/tiann/FreeR…

经过检查代码可知,目前所运用的计划,是经过“元反射”去反射被约束的接口,诈骗体系,假装是体系自己的调用以打破约束(究竟许多躲藏 API 仅仅不给三方运用调用,并不是功用失效)。

此外,博客和代码里还有修正内存的计划,改变内存变量值以打破约束。这个计划并没有被实际调用,可能是因为风险较高。
方针变量的内存的地址是经过其他变量的相对方位来确定的,体系升级或厂商定制后数据结构若产生改变,就可能导致未知错误。

当然,最坏的情况仍是后续体系升级,判别是否约束的逻辑产生改变,还需求重新适配。

技术细节弥补

博客里提到了 fn_caller_is_trusted 这个条件,但并没有给出这个变量的具体逻辑,这儿弥补下。

首要,fn_caller_is_trusted 是作为参数传进来的,GetMemberAction 办法调用办法 java_lang_Class.cc。

关于Android突破非SDK接口限制的延伸

java_lang_Class.cc 中的流程,Class_getDeclaredMethodInternal -> ShouldBlockAccessToMember -> hidden_api.h GetMemberAction

关于Android突破非SDK接口限制的延伸

IsCallerTrusted 是一个办法。经过调用栈解析(WalkStack),获取到当前办法的调用者 caller,并调用到 hidden_api.h 的 IsCallerTrusted。

关于Android突破非SDK接口限制的延伸

回到 hidden_api.h,如果 caller 的dex是体系的dex,那么就会放过,归于可信caller。

关于Android突破非SDK接口限制的延伸

关于Android突破非SDK接口限制的延伸

所以,当运用“元反射”去反射方针接口时,Class 所属的 dex 必然就是体系的 dex,然后绕过约束。