-
-
[原创]改一个参数即可绕过 Android N 的私有 API 链接限制
-
发表于:
2017-5-26 14:28
14797
-
[原创]改一个参数即可绕过 Android N 的私有 API 链接限制
从 Android N 开始,对 NDK 调用私有 API 的行为做了限制。在 Android 7.0 行为变更中明确提到:
通常使用私有 API 的做法是,使用 dlopen 加载 API 所在的动态库,然后通过 dlsym 获取函数地址并调用之。例如如下代码通过不被 NDK 推荐的方式,解析私有函数 JNI_GetCreatedJavaVMs 获取 jvm 实例:
Android N 对此的处理方式是,使用 classloader-namespace 限制了 dlopen 参数允许加载的路径。对于 NDK 公开可用的链接库 (如 libandroid, libc, libcamera2ndk, libdl, libGLES, libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++, libvulkan, libz 等),以及 apk 自带的 libs 下的共享对象,可以自由地加载。但尝试 dlopen 其他路径的文件则会返回 null 并在 logcat 中打印类似这样的错误:
为了兼容性,在应用的 target API level 小于 24 时,linker 输出一个警告并弹出 toast。
如果 target API level 为 Android N 甚至更高版本,那么 dlopen 将返回 null,并可能抛出 java.lang.UnsatisfiedLinkError:
Android 的链接器源码在 platform/bionic/linker/linker.cpp 实现。执行 C 标准库的 dlopen 函数时,在内部函数 load_library 中加入了对链接库合法性的判断:
https://android.googlesource.com/platform/bionic/+/master/linker/linker.cpp#1210
小于 API Level 24 时允许加载的“灰名单”如下:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课