Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )(代

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )(代相关的知识,希望对你有一定的参考价值。

前言



在上一篇博客 【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | oat_file_assistant.cc 中涉及的 oat 文件生成流程 ) 中分析到 将 Dex 文件编译为 Oat 文件 , 最终在 oat_file_assistant.cc#Dex2Oat 函数中 , 调用了 exec_utils.cc#Exec 函数 , 在该函数中执行最后的转换操作 ;





一、exec_utils.cc#Exec 函数分析



在 exec_utils.cc#Exec 函数 中 , 调用了 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;

源码路径 : http://aospxref.com/android-8.0.0_r36/xref/art/runtime/exec_utils.cc#Exec





二、exec_utils.cc#ExecAndReturnCode 函数分析



在该函数中 , 先 fork 一个进程 ,

pid_t pid = fork();

使用 execve 函数 , 执行 Dex 文件编译为 Oat 文件操作 ;

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

exec_utils.cc#ExecAndReturnCode 函数源码 :

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

以上是关于Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )(代的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向ART 脱壳 ( InMemoryDexClassLoader 脱壳 | DexFile 构造函数及相关调用函数 | Android 源码中查找 native 函数 )

Android 逆向ART 脱壳 ( 修改 /art/runtime/dex_file.cc#OpenCommon 系统源码进行脱壳 )

Android 逆向ART 脱壳 ( InMemoryDexClassLoader 脱壳 | InMemoryDexClassLoader 类加载器脱壳点总结 )

Android 逆向ART 脱壳 ( InMemoryDexClassLoader 脱壳 | 加固厂商在 ART 下使用的两种类加载器 | InMemoryDexClassLoader 源码 )(代码

Android 逆向ART 脱壳 ( InMemoryDexClassLoader 脱壳 | dex_file.cc 中创建 DexFile 实例对象的相关函数分析 )

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段