写点什么

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

作者:XCG00
  • 2023-09-23
    北京
  • 本文字数:1165 字

    阅读完需:约 4 分钟

从 Android9 开始,系统开始针对非 SDK 接口做限制。

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



https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces?hl=zh-cn#results-of-keeping-non-sdk

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

而且,非 SDK 接口的限制通常会区分等级,随 TargetSdkVersion 的提升扩大限制范围。尤其是每一两年,应用市场或有关部门,都会要求活跃的应用必须提升 TargetSdkVersion 才能上架或升级,就导致做相应的适配成为一件必须关注的事情。

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



一种绕过 Android P 对非 SDK 接口限制的简单方法https://weishu.me/2018/06/07/free-reflection-above-android-p/

另一种绕过 Android P 以上非公开 API 限制的办法https://weishu.me/2019/03/16/another-free-reflection-above-android-p/

Github - FreeReflectionhttps://github.com/tiann/FreeReflection

通过查看代码可知,目前所使用的方案,是通过“元反射”去反射被限制的接口,欺骗系统,假装是系统自己的调用以突破限制(毕竟很多隐藏 API 只是不给三方应用调用,并不是功能失效)。

此外,博客和代码里还有修改内存的方案,改变内存变量值以突破限制。这个方案并没有被实际调用,可能是因为风险较高。目标变量的内存的地址是通过其他变量的相对位置来锁定的,系统升级或厂商定制后数据结构若发生改变,就可能导致未知错误。

当然,最坏的情况还是后续系统升级,判断是否限制的逻辑发生改变,还需要重新适配。

技术细节补充

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

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



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



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



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




所以,当使用“元反射”去反射目标接口时,Class 所属的 dex 必然就是系统的 dex,从而绕过限制。

发布于: 刚刚阅读数: 5
用户头像

XCG00

关注

Everything is a game. 2017-12-21 加入

公zh【hey6771】

评论

发布
暂无评论
关于Android突破非SDK接口限制的延伸_android_XCG00_InfoQ写作社区