您当前的位置: 首页 >  ar

韩曙亮

暂无认证

  • 1浏览

    0关注

    1068博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | oat_file_assistant.cc 中涉及的 oat 文件生成流程 )

韩曙亮 发布时间:2021-12-15 15:14:17 ,浏览量:1

文章目录
  • 前言
  • 一、dalvik_system_DexFile.cc#DexFile_openDexFileNative 函数分析
  • 二、oat_file_manager.cc#OpenDexFilesFromOat 函数分析
  • 三、oat_file_assistant.cc#MakeUpToDate 函数分析
  • 四、oat_file_assistant.cc#GenerateOatFileNoChecks 函数分析
  • 五、oat_file_assistant.cc#Dex2Oat 函数分析

前言

在上一篇博客 【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 ) 中 , 分析了 ART 虚拟机下 DexClassLoader 类加载器加载 dex 文件的 Java 层流程 , 与 Dalvik 虚拟机下基本一致 , 从 native 层开始不一致 , 本篇博客开始分析 native 层的类加载流程 ;

一、dalvik_system_DexFile.cc#DexFile_openDexFileNative 函数分析

在下面的 DexFile_openDexFileNative 方法中 ,

jstring javaSourceName 参数是要加载的 dex 文件路径 ,

下面调用的 OpenDexFilesFromOat 函数 , 是生成 oat 文件的关键流程入口 ;

  dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
                                                               class_loader,
                                                               dex_elements,
                                                               /*out*/ &oat_file,
                                                               /*out*/ &error_msgs);

dalvik_system_DexFile.cc#DexFile_openDexFileNative 源码 :

// TODO(calin): clean up the unused parameters (here and in libcore).
static jobject DexFile_openDexFileNative(JNIEnv* env,
                                         jclass,
                                         jstring javaSourceName,
                                         jstring javaOutputName ATTRIBUTE_UNUSED,
                                         jint flags ATTRIBUTE_UNUSED,
                                         jobject class_loader,
                                         jobjectArray dex_elements) {
  ScopedUtfChars sourceName(env, javaSourceName);
  if (sourceName.c_str() == nullptr) {
    return 0;
  }

  Runtime* const runtime = Runtime::Current();
  ClassLinker* linker = runtime->GetClassLinker();
  std::vector dex_files;
  std::vector error_msgs;

  // OAT 文件
  const OatFile* oat_file = nullptr;

  // ★ 核心跳转 
  dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
                                                               class_loader,
                                                               dex_elements,
                                                               /*out*/ &oat_file,
                                                               /*out*/ &error_msgs);

  if (!dex_files.empty()) {
    jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);
    if (array == nullptr) {
      ScopedObjectAccess soa(env);
      for (auto& dex_file : dex_files) {
        if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
          dex_file.release();
        }
      }
    }
    return array;
  } else {
    ScopedObjectAccess soa(env);
    CHECK(!error_msgs.empty());
    // The most important message is at the end. So set up nesting by going forward, which will
    // wrap the existing exception as a cause for the following one.
    auto it = error_msgs.begin();
    auto itEnd = error_msgs.end();
    for ( ; it != itEnd; ++it) {
      ThrowWrappedIOException("%s", it->c_str());
    }

    return nullptr;
  }
}

源码路径 : /art/runtime/native/dalvik_system_DexFile.cc#DexFile_openDexFileNative

二、oat_file_manager.cc#OpenDexFilesFromOat 函数分析

先声明 oat 文件对象 ,

  // 声明 OatFile 对象
  const OatFile* source_oat_file = nullptr;

然后判断是否有生成 oat 文件 , 如果是第一次调用 , 肯定没有生成 oat 文件 ,

!oat_file_assistant.IsUpToDate()

如果没有生成 oat 文件 , 则执行

oat_file_assistant.MakeUpToDate(/*profile_changed*/false, /*out*/ &error_msg)

方法 , 开始生成 oat 文件 ;

oat_file_manager.cc#OpenDexFilesFromOat 函数源码 :

std::vector OatFileManager::OpenDexFilesFromOat(
    const char* dex_location,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector* error_msgs) {
  ScopedTrace trace(__FUNCTION__);
  CHECK(dex_location != nullptr);
  CHECK(error_msgs != nullptr);

  // 验证我们没有持有mutator锁,如果我们必须生成或重新定位oat文件,这可能会导致GC饥饿。
  Thread* const self = Thread::Current();
  Locks::mutator_lock_->AssertNotHeld(self);
  Runtime* const runtime = Runtime::Current();

  OatFileAssistant oat_file_assistant(dex_location,
                                      kRuntimeISA,
                                      !runtime->IsAotCompiler());

  // 锁定目标oat位置以避免生成和加载oat文件。
  std::string error_msg;
  if (!oat_file_assistant.Lock(/*out*/&error_msg)) {
    // Don't worry too much if this fails. If it does fail, it's unlikely we
    // can generate an oat file anyway.
    VLOG(class_linker)             
关注
打赏
1663594092
查看更多评论
0.0549s