首页
社区
课程
招聘
5
[原创] 一个通用的纯 Java 安卓隐藏 API 限制绕过方案
发表于: 2021-4-24 20:49 14048

[原创] 一个通用的纯 Java 安卓隐藏 API 限制绕过方案

2021-4-24 20:49
14048

文章同时发表在我个人博客上。转载请务必注明出处。

 

目录

背景

2018年发布的 Android P 中引入了对隐藏API的限制,这对整个Android生态来说当然是一件好事,但也严重限制了以往我们通过反射等手段实现的“黑科技”(如插件化等),所以开发者们纷纷寻找手段绕过这个限制。比如 Canyie 就曾经提出了两个绕过方法,其中一个便是几乎完美的双重反射(即“元反射”,现在来看叫“套娃反射”比较好);而在即将发布的Android R中把这个方法封杀了。

旧方法

这是 Canyie 在其博客上^1提到的安卓隐藏 API 的问题。博客上还提出了一个看似可行的解决方案:设置类的 classloadernull 成为 BootClassPath 中的类以解除限制。此法看似可行,然并非万全:

  1. 首先在有隐藏 API 限制的情况下修改自己的 classloader 非常困难(但是仍可行)
  2. 类是否有隐藏 API 限制是由其在加载时候就设置好的 Domain 决定,所以在加载类之后再修改 classloader 就没有用了。
  3. 利用 DexFile 加载一个没有 classloader 的类可以(甚至可以通过 base64 加载一个预制在 java 字符串中的 dex 文件),但是 DexFile 已经 deprecated 掉,并且在不日加入豪华隐藏 API 列表^2
  4. 谷歌方面已经开始着手不信任 classloadernull 的类了^6

柳暗

这样看来,纯 Java 绕过隐藏 API 似乎没戏了。只能通过 native 代码,用魔法绕过 dlopen 限制来 dlsymlibart.so 中的 _ZN3artL32VMRuntime_setHiddenApiExemptionsEP7_JNIEnvP7_jclassP13_jobjectArray 来设置允许隐藏 API 了。

花明

等等。

 

我们好像还有一个非常适合玩魔法的 Java 自带的 API:Unsafe!
这个魔法类顾名思义,是非常不安全的:它可以纯 Java 读写内存!也就是说,有了这个东西,我们就可以读写类中的任意数据成员了!甚至如果拿到 native 指针,还能直接读指针指向的内存内容。那么我们是不是可以藉此来读取类的隐藏函数?答案是肯定的。

 

但是,ART 中的函数不是存在一个 Java 数组中乖乖等着给你拿的。ART 的模型是 Java 代码中的重要类和 native 代码中的一个类相互 mirror:即共享同一块内存。所以在 Java 中读写这些 Java 类对象的成员相当于同时修改对应的 native 对象成员。一些常见的类就是 ClassMethodField 等。于是为了方便 native 代码访问这些对象,这些类的成员很多都不是以 Java 对象形式存在,而是以 native 指针形式存在。比如一个 Class 对应的 Java 结构如下^3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public final class Class {
    private transient ClassLoader classLoader;
    private transient Class componentType;
    private transient Object dexCache;
    private transient ClassExt extData;
    private transient Object[] ifTable;
    private transient Classsuper T> superClass;
    private transient Object vtable;
    private transient long iFields;
    private transient long methods;
    private transient long sFields;
    private transient int accessFlags;
    private transient int classFlags;
    //还有其他成员,这里就写了
}

可以看到有很多 long 成员,这些就是 native 指针了。很可惜,我们想要的 methods 就是以指针形式存在的,而且指针对应的是 ArtMethod 的 native 对象,并非一个对应到 Java 的 mirror 的 Method。感兴趣的小伙伴可以看看 Executable 的实现,其中有一个 long 成员是 artMethod 对应的就是这个东西。

 

那么我们需要把这个 methods 指针对应的 artMethod 给一个一个枚举出来,并且想办法把他们转换为 Java 可以用的 Executable (用 Executable 是这个包含 ConstructorMethod)。

提取 ArtMethod

要理解这个指针到底存了啥,我们就要回到 native 代码^4


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-4-24 20:52 被yujincheng08编辑 ,原因:
收藏
免费 5
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-1-13 12:32
GODGDK
为你点赞~
2022-1-4 15:30
xhyeax
为你点赞~
2021-12-15 21:06
ydshk
为你点赞~
2021-5-2 10:32
mb_goxyneyf
为你点赞~
2021-4-30 18:11
最新回复 (11)
雪    币: 136
活跃值: (1212)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不懂
2021-4-25 00:32
0
雪    币: 13
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
没有验证,感觉思路很厉害
2021-4-25 10:15
0
雪    币: 1867
活跃值: (4113)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
老板们对新版本的Android研究得挺即时的啊
2021-4-25 14:14
0
雪    币: 477
活跃值: (1412)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这个么
https://zhuanlan.zhihu.com/p/364884283
2021-4-25 14:31
0
雪    币: 208
活跃值: (387)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mb_foyotena 这个么 https://zhuanlan.zhihu.com/p/364884283
很明显是参考了我的方法(发贴日期也在我博客后),但是却写死了 offset。虽然 offset 写死问题不大,但是其搜索 artmethod 大小不稳。实际上随便选两个必然相连的方法就行。
2021-4-25 19:07
0
雪    币: 477
活跃值: (1412)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

   

最后于 2021-4-26 14:18 被mb_foyotena编辑 ,原因:
2021-4-26 13:55
0
雪    币: 0
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好文要顶
2021-4-26 14:50
0
雪    币: 122
活跃值: (561)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
很牛逼的思路
2021-4-26 18:22
0
雪    币: 2286
活跃值: (1240)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
收藏就是学到 mark
2021-4-27 10:33
0
雪    币: 2090
活跃值: (3948)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太麻烦,没必要
用DexFile类加载的任何dex文件,只要父ClassLoader为空,则会认为来自BootClassLoader加载
可以绕过任何反射限制,比这个方法简单得多
2021-4-29 15:00
0
雪    币: 208
活跃值: (387)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
lhxdiao 太麻烦,没必要 用DexFile类加载的任何dex文件,只要父ClassLoader为空,则会认为来自BootClassLoader加载 可以绕过任何反射限制,比这个方法简单得多

你真的有认真看我的文章吗?你看看我旧方法小节的第三点?谷歌开始不再信任 classloader 为 null 的类了:https://android-review.googlesource.com/c/platform/art/+/1664304。而 dexfile 也要被加入隐藏 api 列表中:https://android-review.googlesource.com/c/platform/libcore/+/1666599。甚至pthread 开新线程也即将被堵。

最后于 2021-4-29 15:22 被yujincheng08编辑 ,原因:
2021-4-29 15:19
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册