【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | BaseDexClassLoader 构造函数 | DexPathList 构造函数及后续调用 )

简介: 【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | BaseDexClassLoader 构造函数 | DexPathList 构造函数及后续调用 )

文章目录

一、BaseDexClassLoader 构造函数

二、DexPathList 构造函数

三、DexPathList.makeInMemoryDexElements 函数





一、BaseDexClassLoader 构造函数


在上一篇博客 【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | 加固厂商在 ART 下使用的两种类加载器 | InMemoryDexClassLoader 源码 ) 分析到 , 在 InMemoryDexClassLoader 类加载器中 , 调用了父类 BaseDexClassLoader 的 2 22 个参数的构造函数 ;


BaseDexClassLoader 构造函数如下 , 在该构造函数中创建了 DexPathList 对象 , 并赋值给了 pathList 成员 ;



BaseDexClassLoader 构造函数源码 :


/**
 * 用于各种基于dex的数据库之间的通用功能的基类
 * {@link ClassLoader}实现。
 */
public class BaseDexClassLoader extends ClassLoader {
  private final DexPathList pathList;
  /**
  * 构造一个实例。
  * 
  * dexFile 必须是完整dexFile的内存表示形式。
  * 
  * @param dexFiles 包含类的内存中dex文件数组。
  * @param parent 父类加载器
  * 
  * @隐藏
  */
    public BaseDexClassLoader(ByteBuffer[] dexFiles, ClassLoader parent) {
        // TODO 我们应该支持给它一个库搜索路径。
        super(parent);
        // ★ 核心跳转
        this.pathList = new DexPathList(this, dexFiles);
    }
}


源码路径 : /libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java






二、DexPathList 构造函数


在 DexPathList 构造函数中 , 调用了 makeInMemoryDexElements 方法创建 DEX 相关的 Element 元素 ;


/**
 * 一对条目列表,与{@code ClassLoader}关联。
 * 其中一个列表是索引/资源路径—通常提及
 * 作为“类路径”—列表和其他名称目录
 * 包含本机代码库。类路径条目可以是以下任一项:
 * 一个{@code.jar}或{@code.zip}文件,其中包含一个可选的
 * 顶级{@code classes.dex}文件以及任意资源,
 * 或者是一个普通的{@code.dex}文件(不可能与
 * 资源)。
 * 
 * <p>此类还包含使用这些列表进行查找的方法
 * 课程和资源</p>
 */
/*package*/ final class DexPathList {
  /**
  * 构造一个实例。
  * 
  * @param definingContext 任何尚未解析的
  * 应该定义类
  * 
  * @param dexFiles 包含我们应该从中加载类的dex文件的字节缓冲区。
  */
    public DexPathList(ClassLoader definingContext, ByteBuffer[] dexFiles) {
        if (definingContext == null) {
            throw new NullPointerException("definingContext == null");
        }
        if (dexFiles == null) {
            throw new NullPointerException("dexFiles == null");
        }
        if (Arrays.stream(dexFiles).anyMatch(v -> v == null)) {
            throw new NullPointerException("dexFiles contains a null Buffer!");
        }
        this.definingContext = definingContext;
        // TODO It might be useful to let in-memory dex-paths have native libraries.
        this.nativeLibraryDirectories = Collections.emptyList();
        this.systemNativeLibraryDirectories =
                splitPaths(System.getProperty("java.library.path"), true);
        this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);
        ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
  // ★ 核心跳转
        this.dexElements = makeInMemoryDexElements(dexFiles, suppressedExceptions);
        if (suppressedExceptions.size() > 0) {
            this.dexElementsSuppressedExceptions =
                    suppressedExceptions.toArray(new IOException[suppressedExceptions.size()]);
        } else {
            dexElementsSuppressedExceptions = null;
        }
    }
}


源码路径 : /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java






三、DexPathList.makeInMemoryDexElements 函数


在 makeInMemoryDexElements 方法中 , 根据内存中的字节数组数据 , 获取 DexFile , 将内存数据传入了 DexFile 的构造函数 ;


注意 : 传入 DexFile 构造函数的数据是 ByteBuffer buf 类型数据 ;


 

// ★ 核心跳转
    DexFile dex = new DexFile(buf);


DexPathList.makeInMemoryDexElements 函数源码 :


/*package*/ final class DexPathList {
  private static Element[] makeInMemoryDexElements(ByteBuffer[] dexFiles,
    List<IOException> suppressedExceptions) {
  Element[] elements = new Element[dexFiles.length];
  int elementPos = 0;
  for (ByteBuffer buf : dexFiles) {
    try {
    // ★ 核心跳转
    DexFile dex = new DexFile(buf);
    elements[elementPos++] = new Element(dex);
    } catch (IOException suppressed) {
    System.logE("Unable to load dex file: " + buf, suppressed);
    suppressedExceptions.add(suppressed);
    }
  }
  if (elementPos != elements.length) {
    elements = Arrays.copyOf(elements, elementPos);
  }
  return elements;
  }
}



目录
相关文章
|
4月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【7月更文挑战第28天】在Android开发中,掌握底层机制至关重要。从Dalvik到ART, Android通过采用AOT编译在应用安装时预编译字节码至机器码,显著提升了执行效率。ART还优化了垃圾回收,减少内存占用及停顿。为了优化性能,可减少DEX文件数量、优化代码结构利用内联等技术、合理管理内存避免泄漏,并使用ART提供的调试工具。
119 7
|
2月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【9月更文挑战第12天】在Android开发领域,深入了解其底层机制对提升应用性能至关重要。本文详述了从早期Dalvik虚拟机到现今Android Runtime(ART)的演变过程,揭示了ART通过预编译技术实现更快启动速度和更高执行效率的奥秘。文中还介绍了ART的编译器与运行时环境,并提出了减少DEX文件数量、优化代码结构及合理管理内存等多种性能优化策略。通过掌握这些知识,开发者可以从全新的角度提升应用性能。
65 11
|
移动开发 Java Android开发
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
1757 0
uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
|
JavaScript 前端开发 Android开发
JS(Javascript)调用Android原生方法三步走
JS(Javascript)调用Android原生方法三步走
582 0
|
XML 存储 数据库
Android 逆向笔记 —— ARSC 文件格式解析
Android 逆向笔记 —— ARSC 文件格式解析
Android 逆向笔记 —— ARSC 文件格式解析
|
Android开发
Android Studio中添加Flutter模板直接调用
Android Studio中添加Flutter模板直接调用
204 0
Android Studio中添加Flutter模板直接调用
|
存储 安全 IDE
android studio 输出apk过程,apk中的文件格式(bsh文件,dex文件),JVM、DVM、ART的区别,IOS与安卓的区别,ART和Dalvi
android studio 输出apk过程,apk中的文件格式(bsh文件,dex文件),JVM、DVM、ART的区别,IOS与安卓的区别,ART和Dalvi
266 0
android studio 输出apk过程,apk中的文件格式(bsh文件,dex文件),JVM、DVM、ART的区别,IOS与安卓的区别,ART和Dalvi
|
Java 编译器 API
Android使用NDK(从java调用本地函数'JNI')
Android使用NDK(从java调用本地函数'JNI')
235 0
Android使用NDK(从java调用本地函数'JNI')
|
JavaScript Android开发 iOS开发
html通过js调用ios或android代码
html通过js调用ios或android代码
70 0
|
Android开发
Android实现调用系统相机录像及实现录音
Android实现调用系统相机录像及实现录音
677 0