首页 > 其他分享 >绕过链接器命名空间限制访问libart.so

绕过链接器命名空间限制访问libart.so

时间:2023-01-03 00:22:05浏览次数:56  
标签:空间 so 命名 libart runtime 链接 加载

还是以通过dlopen获取libart.so句柄为出发点,由于android 7.0之后的链接器命名空间限制包括libart.so的一些私有库被限制访问。

应用进程类加载器的命名空间初始化

在应用程序对应的可执行文件app_process根据/system/etc/ld.config.{api}.txt配置文件初始化命名空间之后,每当应用程序创建一个类加载器classloader并调用System.loadLibrary加载so库时都会创建一个与此类加载器对应的命名空间(name为classloader-namespace)。从源码角度分析一下这个过程,System.loadLibrary函数最后会调用OpenNativeLibrary函数。

OpenNativeLibrary

System.loadLibrary()-->nativeLoad()-->Runtime.c::Runtime_nativeLoad()-->JVM_NativeLoad()-->Openjdkjvm.cc::JVM_NativeLoad()-->java_vm_ext.cc::LoadNativeLibrary()-->native_loader.cpp::OpenNativeLibrary(),也就是java层的System.loadLibrary()最终会调用libnativeloader.so的OpenNativeLibrary函数。

  • OpenNativeLibrary先判断classloader类加载器是否为空,如果为空直接调用dlopen或者android_dlopen_ext加载库文件
  • 如果判断classloader类加载器不为空,并且classloader类加载器没有对应的命名空间(第一次调用System.loadLibrary)就调用LibraryNamespaces::Create创建新的命名空间。

LibraryNamespaces::Create

  • 先调用android_create_namespace创建一个名称为classloader-namespace的命名空间。

  • 调用android_linker_namespace设置新创建的命名空间链接到default和runtime等命名空间。

  • 设置链接到default命名空间的共享库为system_exposed_libraries,设置链接到runtime命名空间的共享库为runtime_exposed_libraries。

查看system_exposed_libraries的值等于system_public_libraries,而system_public_libraries的值为/system/etc/public.libraries.txt配置文件中所有的库名称。所以新创建的类加载器命名空间链接到default命名空间并设置的共享库存放在/system/etc/public.libraries.txt配置文件中。

查看runtime_exposed_libraries的值等于kRuntimePublicLibraries,而kRuntimePublicLibraries中只包含了libicuuc.so和libicui18n.so。所以新创建的类加载器命名空间链接到runtime命名空间并设置的共享库为kRuntimePublicLibraries。

libart.so加载runtime命名空间的过程

app进程都是从zygote进程fork的,zygote进程会调用AndroidRuntime::start做一些初始化其中就会调用libnativehelper.so中的JniInvocationImpl::Init函数加载libart.so文件。

AndroidRuntime::start

libart加载到runtime

查看/system/etc/ld.config.29.txt文件发现default空间会链接到runtime空间中并设置共享库包含libnativehelper.so,所以当app_process加载libnativehelper.so失败时会通过runtime命名空间加载。当app_process进程调用AndroidRuntime::start函数并进一步调用libnativehelper.so中的JniInvocationImpl::Init函数,JniInvocationImpl::Init函数通过dlopen加载libart.so文件。因为dlopen调用者libnativehelper.so被加载到了runtime命名空间中,所以其调用dlopen加载libart.so也会加载到runtime命名空间中。

绕过链接器命名空间限制访问libart.so

查看/system/etc/ld.config.29.txt文件system标签下的runtime命名空间发现其库搜索路径为/apex/com.android.runtime/lib(64),而libart.so就在此目录中。所以app_process在初始化命名空间后加载libart.so时会将此其加载到runtime命名空间中。当app应用程序创建类加载器时在第一次调用Sytem.loadLibrary时会创建一个classloader-namespace命名空间,此命名空间会链接到default和runtime等命名空间中,其中链接到default命名空间中的共享库保存在/system/etc/public.libraries.txt配置文件中,链接到runtime命名空间中的共享库保存在kRuntimePublicLibraries中。而kRuntimePublicLibraries中对于android 10_0.0_r7这个版本而言只有libicuuc.so和libicui18n.so这两个库,并没有libart.so所以调用dlopen是没有权限在runtime命名空间中搜索加载libart.so的。

因为kRuntimePublicLibraries中对于android 10_0.0_r7这个版本而言只有libicuuc.so和libicui18n.so这两个库,那么说在dlopen是可以有权限在runtime命名空间中搜索加载这连个库并返回对应的handle的。native中调用lopen("libicuuc.so", RTLD_NOW);确实可以获取到对应的handle。

网上的帖子有的人说将libart.so加入到public.libraries.txt中就可以通过dlopen得到libart.so的handle是不对的,因为此文件中保存的类加载器命名空间链接到default命名空间中共享库列表并不是链接到runtime命名空间的共享库列表。你设置public.libraries.txt中加入libart.so当无法在类加载器中加载libart.so时会去default命名空间中搜索加载此库,但libart.so是被加载到runtime命名空间中并不在default空间中,所以还是找不到。正确的做法是在kRuntimePublicLibraries中加入libart.so并重新编译源码。

当然还有其他很多方法可以绕过,本文只是从类加载器命名空间初始化的角度分析。例如可以通过直接修改相关命名空间策略源码,或者修改/system/etc/ld.config.29.txt文件中runtime命名空间namespace.runtime.isolated = false也就是非严格隔离,这样其就可以通过dlopen并传入绝对路径加载libart.so。

参考:
https://www.jianshu.com/p/1672b52548ce
http://zjh.wiki/2020-09-07-libart-so.html
https://blog.seeflower.dev/archives/79/
https://www.52pojie.cn/thread-948942-1-1.html

标签:空间,so,命名,libart,runtime,链接,加载
From: https://www.cnblogs.com/revercc/p/17020902.html

相关文章

  • SEO:对于网站快照出现以前的历史快照,但是此链接不存在怎么办?
    查看网站网页快照,有时候会出现很久远的网页快照,且打开是404,此种情况,大大影响网站的用户体验等。我们可以使用死链提交工具进行主动申请删除历史不存在的快照链接即可。步......
  • 注入——AddressOfEntryPoint入口点注入
    通过修改进程入口点,进行Shellcode注入。1、首先使用CreateProcess函数创建进程,并且将参数填写为CREATE_SUSPENDED这代表新进程的主线程被挂起了2、然后定位AddressOfEntr......
  • S2 - Lesson 9 - The cold welcome
    WordswelcomeacoldwelcomewelcomeyouwelcometoBJyouarewelcome. crowdalargecrowdofpeoplecrowded拥挤 handminutehandhourhandsecondhand......
  • 使用lambda表达式实现sort的自定义排序
    使用lambda表达式实现sort的自定义排序(C++andJava)首先大致讲一下什么是lambda表达式你也可以将它就当做是匿名函数,lambda表达式其实就是匿名函数演化出的一种语法系统......
  • c#基于socket编程实现简单多人聊天程序
    首先直接上代码链接,欢迎修改与指正:​​https://github.com/yinyoupoet/chatRoomTest​​​代码、可运行程序、详细设计文档、使用说明等都在里面啦然后再上图你们感受下:......
  • 微服务技术链接汇总
    Spring官网:​​https://spring.io/projects​​SpringCloud专栏SpringCloud官网:​​​https://spring.io/projects/spring-cloud​​重点关注:SpringCloud中文网-官方......
  • S2 - Lesson 8 - The best and the worst
    Words competitioncompeterace neat pathneatpathsthepathtothesuccess woodenwood pool    ContentThebestandtheworstJoeSande......
  • Spring Security 源码分析(四):Spring Social实现微信社交登录
    前言在上一章Spring-Security源码分析三-Spring-Social社交登录过程中,我们已经实现了使用​​SpringSocial​​​+​​Security​​的QQ社交登录。本章我们将实现微信的社......
  • 干货|机器学习基石精选文章链接
    下面这部分内容列出了机器学习基石的精选文章。包括什么时候机器能够学习?为什么机器能够学习?机器如何进行学习?机器如何更好地学习?四个方面。如果你对我的文章和内......
  • Springboot 整合 Dubbo/ZooKeeper 详解 SOA 案例
    一、为啥整合Dubbo实现SOADubbo不单单只是高性能的RPC调用框架,更是SOA服务治理的一种方案。核心:1.远程通信,向本地调用一样调用远程方法。2.集群容错3.服务自动发......