【Android 逆向】ART 函数抽取加壳 ( ART 下的函数抽取恢复时机 | 禁用 dex2oat 机制源码分析 )(二)

简介: 【Android 逆向】ART 函数抽取加壳 ( ART 下的函数抽取恢复时机 | 禁用 dex2oat 机制源码分析 )(二)

2、oat_file_assistant.cc#Dex2Oat 源码分析


在 /art/runtime/oat_file_assistant.cc#Dex2Oat 函数中 , 调用了 /art/runtime/exec_utils.cc#Exec 函数 ;


bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
                               std::string* error_msg) {
  Runtime* runtime = Runtime::Current();
  std::string image_location = ImageLocation();
  if (image_location.empty()) {
    *error_msg = "No image location found for Dex2Oat.";
    return false;
  }
  std::vector<std::string> argv;
  argv.push_back(runtime->GetCompilerExecutable());
  argv.push_back("--runtime-arg");
  argv.push_back("-classpath");
  argv.push_back("--runtime-arg");
  std::string class_path = runtime->GetClassPathString();
  if (class_path == "") {
    class_path = OatFile::kSpecialSharedLibrary;
  }
  argv.push_back(class_path);
  if (runtime->IsJavaDebuggable()) {
    argv.push_back("--debuggable");
  }
  runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
  if (!runtime->IsVerificationEnabled()) {
    argv.push_back("--compiler-filter=verify-none");
  }
  if (runtime->MustRelocateIfPossible()) {
    argv.push_back("--runtime-arg");
    argv.push_back("-Xrelocate");
  } else {
    argv.push_back("--runtime-arg");
    argv.push_back("-Xnorelocate");
  }
  if (!kIsTargetBuild) {
    argv.push_back("--host");
  }
  argv.push_back("--boot-image=" + image_location);
  std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
  argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
  argv.insert(argv.end(), args.begin(), args.end());
  std::string command_line(android::base::Join(argv, ' '));
  // ★ 核心跳转
  return Exec(argv, error_msg);
}


源码路径 : /art/runtime/oat_file_assistant.cc#Dex2Oat



3、exec_utils.cc#Exec 源码分析


在 /art/runtime/exec_utils.cc#Exec 函数中 , 调用了 /art/runtime/exec_utils.cc#ExecAndReturnCode 函数 ;


bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
  // ★ 核心跳转
  int status = ExecAndReturnCode(arg_vector, error_msg);
  if (status != 0) {
    const std::string command_line(android::base::Join(arg_vector, ' '));
    *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
                              command_line.c_str());
    return false;
  }
  return true;
}


源码路径 : /art/runtime/exec_utils.cc#Exec



4、exec_utils.cc#ExecAndReturnCode 源码分析


在 /art/runtime/exec_utils.cc#ExecAndReturnCode 函数中 , 调用了


execve(program, &args[0], envp);


函数 , 通过 hook 该 execve 函数 , 可以禁用 dex2oat ;


int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
  const std::string command_line(android::base::Join(arg_vector, ' '));
  CHECK_GE(arg_vector.size(), 1U) << command_line;
  // 将参数转换为字符指针。
  const char* program = arg_vector[0].c_str();
  std::vector<char*> args;
  for (size_t i = 0; i < arg_vector.size(); ++i) {
    const std::string& arg = arg_vector[i];
    char* arg_str = const_cast<char*>(arg.c_str());
    CHECK(arg_str != nullptr) << i;
    args.push_back(arg_str);
  }
  args.push_back(nullptr);
  // fork and exec
  pid_t pid = fork();
  if (pid == 0) {
    // fork和exec之间不允许分配
    // 更改流程组,这样我们就不会被ProcessManager收获
    setpgid(0, 0);
    // (b/30160149): 保护子进程不受对LD_LIBRARY_路径等的修改的影响。
    // 使用从创建运行时开始的环境快照。
    char** envp = (Runtime::Current() == nullptr) ? nullptr : Runtime::Current()->GetEnvSnapshot();
    if (envp == nullptr) {
      execv(program, &args[0]);
    } else {
      execve(program, &args[0], envp);
    }
    PLOG(ERROR) << "Failed to execve(" << command_line << ")";
    // _exit to avoid atexit handlers in child.
    _exit(1);
  } else {
    if (pid == -1) {
      *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
                                command_line.c_str(), strerror(errno));
      return -1;
    }
    // 等待子进程完成
    int status = -1;
    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
    if (got_pid != pid) {
      *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
                                "wanted %d, got %d: %s",
                                command_line.c_str(), pid, got_pid, strerror(errno));
      return -1;
    }
    if (WIFEXITED(status)) {
      return WEXITSTATUS(status);
    }
    return -1;
  }
}


源码路径 : /art/runtime/exec_utils.cc#ExecAndReturnCode


目录
相关文章
|
1月前
|
前端开发 编译器 Android开发
构建高效Android应用:探究Kotlin协程的异步处理机制
【4月更文挑战第2天】在现代移动应用开发中,提供流畅且响应迅速的用户体验是至关重要的。随着Android平台的发展,Kotlin语言凭借其简洁性和功能性编程的特点成为了主流选择之一。特别地,Kotlin协程作为一种新型的轻量级线程管理机制,为开发者提供了强大的异步处理能力,从而显著提升了应用程序的性能和响应速度。本文将深入探讨Kotlin协程在Android中的应用,分析其原理、实现以及如何通过协程优化应用性能。
|
4月前
|
存储 Java Android开发
Android系统升级的机制概要
Android系统升级的机制概要
46 0
|
4天前
|
Android开发
Android Loader机制
Android Loader机制
11 1
|
1月前
|
API 调度 Android开发
探索Android应用程序的后台运行机制
在移动应用开发中,了解和掌握Android应用程序的后台运行机制至关重要。本文将深入探讨Android平台上应用程序的后台运行原理及其影响因素,包括后台服务、广播接收器、JobScheduler等关键组件,以及如何有效管理后台任务以提升应用性能和用户体验。
20 3
|
9月前
|
Android开发
Android PackageManagerService源码分析和APK安装原理详解
Android PackageManagerService源码分析和APK安装原理详解
213 1
|
5月前
|
Android开发 容器
[Android]View的事件分发机制(源码解析)
[Android]View的事件分发机制(源码解析)
37 0
|
5月前
|
消息中间件 缓存 安全
android开发,使用kotlin学习消息机制Handler
android开发,使用kotlin学习消息机制Handler
97 0
|
5月前
|
安全 Android开发 Kotlin
android开发,使用kotlin学习Android权限机制
android开发,使用kotlin学习Android权限机制
43 0
|
8月前
|
Android开发 开发者
Android View 事件分发机制,看这一篇就够了(二)
Android View 事件分发机制,看这一篇就够了
|
8月前
|
Android开发
Android View 事件分发机制,看这一篇就够了(一)
Android View 事件分发机制,看这一篇就够了