当前位置: 首页 > web >正文

关于 dex2oat 以及 vdex、cdex、dex 格式转换

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

dex2oat

dex2oat 是 Android 系统中的一个核心工具,负责将应用中的 .dex(Dalvik Executable)字节码编译为本地机器代码(native code),以提高运行效率。它的全称是 DEX to OAT(Optimized Android Transport)。

dex2oat 的作用

word/media/image1.png

在 Android 系统中,Java/Kotlin 编写的应用在编译时会被转换为 .dex 文件。为了提高性能,Android 会将 .dex 文件进一步编译为 .oat 文件(或 .odex/.vdex 文件),以便设备可以直接执行本地代码而不是解释执行 .dex 字节码。

工作原理(简要流程)

输入:一个或多个 .dex 文件(通常来自 APK 中的 classes.dex)。

输出:生成 .oat(Optimized Android Executable)、.vdex(Verified DEX)和 .art(Android Runtime)文件。

过程:

  • 验证并优化 .dex。

  • 使用 AOT(Ahead-Of-Time)方式将 .dex 转为本地机器码。

  • 生成平台相关的可执行文件,用于加快应用启动速度。

编译模式:

  • AOT(Ahead-Of-Time):安装或开机前就编译好,提高运行速度。

  • JIT(Just-In-Time):运行时动态编译,节省空间但牺牲性能。

  • Hybrid(混合):Android 7.0+ 默认模式,结合 AOT 与 JIT。

执行时机

  • 第一次开机:系统会对预装的应用使用 dex2oat 编译。

  • App 安装时:根据编译策略(speed, quicken, interpret-only 等)选择是否编译。

  • 系统升级/补丁后:部分 DEX 文件会重新编译。

文件说明

  • .dex:Dalvik 字节码文件,APK 中的代码格式。

  • .oat / .odex:包含从 dex 编译来的 优化后的中间表示代码。

  • .vdex:包含验证后的 dex 和优化信息。

  • .art:Android Runtime 中的预编译执行数据

vdexExtractor

vdexExtractor 是一个用于从 .vdex 文件中提取 DEX 文件的工具,它由 Google 安全团队成员 anestisb 开发。它支持将 Android 9 及以后版本中引入的 CompactDex (cdex) 格式转换为标准的 DEX 格式,方便我们使用常规反编译工具(如 jadx、dex2jar等)进行分析。

开源地址:https://github.com/anestisb/vdexExtractor

编译 vdexExtractor

先把 vdexExtractor clone 到本地。

由于 是在 Windows 的 WSL 中编译,所有要转换换行符

cyrus@cyrus:/mnt/d/Python/anti-app/vdexExtractor$ ./tools/deodex/run.sh -i /mnt/d/Python/anti-app/frida_dex_dump/dumped_dex -o /mnt/d/Python/anti-app/frida_dex_dump/dumped_dex_out
/usr/bin/env: ‘bash\r’: No such file or directory

执行下面命令转换 .sh 文件中的换行符为 Unix 格式的换行符

dos2unix make.sh
dos2unix ./tools/deodex/run.sh
dos2unix ./tools/deodex/constants.sh

执行 make.sh 开始编译,报错如下:

cyrus@cyrus:/mnt/d/Python/anti-app/vdexExtractor$ ./make.sh
make: Entering directory '/mnt/d/Python/anti-app/vdexExtractor/src'
rm -f *.o
rm -f */*.o
rm -f vdexExtractor
make: Leaving directory '/mnt/d/Python/anti-app/vdexExtractor/src'
make: Entering directory '/mnt/d/Python/anti-app/vdexExtractor/src'
gcc -c -std=c11 -D_GNU_SOURCE -Wall -Wextra -Werror -DVERSION=\"dev-78f283b\" -c dex.c -o dex.o
gcc -c -std=c11 -D_GNU_SOURCE -Wall -Wextra -Werror -DVERSION=\"dev-78f283b\" -c dex_instruction.c -o dex_instruction.o
dex_instruction.c:655:43: error: argument 2 of type ‘u4[kMaxVarArgRegs]’ {aka ‘unsigned int[kMaxVarArgRegs]’} declared as a variable length array [-Werror=vla-parameter]655 | void dexInstr_getVarArgs(u2 *code_ptr, u4 arg[kMaxVarArgRegs]) {|                                        ~~~^~~~~~~~~~~~~~~~~~~
In file included from dex_instruction.c:23:
dex_instruction.h:278:32: note: previously declared as an ordinary array ‘u4[]’ {aka ‘unsigned int[]’}278 | void dexInstr_getVarArgs(u2 *, u4[]);|                                ^~~~
cc1: all warnings being treated as errors
make: *** [Makefile:56: dex_instruction.o] Error 1
make: Leaving directory '/mnt/d/Python/anti-app/vdexExtractor/src'
[-] build failed

改为通过 make 命令编译:

  • -Wno-error=vla-parameter:关闭 vla-parameter 警告(某些编译器会默认把这个警告当作错误)。

  • ${CFLAGS}:保留已有的 CFLAGS(确保不覆盖其他选项)。

make CFLAGS="${CFLAGS} -Wno-error=vla-parameter" -C src

参考:https://github.com/anestisb/vdexExtractor/issues/82

编译成功

cyrus@cyrus:/mnt/d/Python/anti-app/vdexExtractor$ make CFLAGS="${CFLAGS} -Wno-error=vla-parameter" -C src
make: Entering directory '/mnt/d/Python/anti-app/vdexExtractor/src'
cc -Wno-error=vla-parameter -c dex.c -o dex.o
cc -Wno-error=vla-parameter -c dex_instruction.c -o dex_instruction.o
cc -Wno-error=vla-parameter -c log.c -o log.o
cc -Wno-error=vla-parameter -c out_writer.c -o out_writer.o
cc -Wno-error=vla-parameter -c utils.c -o utils.o
cc -Wno-error=vla-parameter -c vdexExtractor.c -o vdexExtractor.o
cc -Wno-error=vla-parameter -c vdex_api.c -o vdex_api.o
cc -Wno-error=vla-parameter -c hashset/hashset.c -o hashset/hashset.o
cc -Wno-error=vla-parameter -c vdex/vdex_006.c -o vdex/vdex_006.o
cc -Wno-error=vla-parameter -c vdex/vdex_010.c -o vdex/vdex_010.o
cc -Wno-error=vla-parameter -c vdex/vdex_019.c -o vdex/vdex_019.o
cc -Wno-error=vla-parameter -c vdex/vdex_021.c -o vdex/vdex_021.o
cc -Wno-error=vla-parameter -c vdex/vdex_backend_006.c -o vdex/vdex_backend_006.o
cc -Wno-error=vla-parameter -c vdex/vdex_backend_010.c -o vdex/vdex_backend_010.o
cc -Wno-error=vla-parameter -c vdex/vdex_backend_019.c -o vdex/vdex_backend_019.o
cc -Wno-error=vla-parameter -c vdex/vdex_backend_021.c -o vdex/vdex_backend_021.o
cc -Wno-error=vla-parameter -c vdex/vdex_decompiler_006.c -o vdex/vdex_decompiler_006.o
cc -Wno-error=vla-parameter -c vdex/vdex_decompiler_010.c -o vdex/vdex_decompiler_010.o
cc -Wno-error=vla-parameter -c vdex/vdex_decompiler_019.c -o vdex/vdex_decompiler_019.o
cc -Wno-error=vla-parameter -c vdex/vdex_decompiler_021.c -o vdex/vdex_decompiler_021.o
cc  dex.o  dex_instruction.o  log.o  out_writer.o  utils.o  vdexExtractor.o  vdex_api.o  hashset/hashset.o  vdex/vdex_006.o  vdex/vdex_010.o  vdex/vdex_019.o  vdex/vdex_021.o  vdex/vdex_backend_006.o  vdex/vdex_backend_010.o  vdex/vdex_backend_019.o  vdex/vdex_backend_021.o  vdex/vdex_decompiler_006.o  vdex/vdex_decompiler_010.o  vdex/vdex_decompiler_019.o  vdex/vdex_decompiler_021.o -lm -lz -o vdexExtractor
cp vdexExtractor ../bin/vdexExtractor
make: Leaving directory '/mnt/d/Python/anti-app/vdexExtractor/src'

编译成功后可以看到 bin 目录下多了一个 vdexExtractor 文件

word/media/image2.png

vdexExtractor 的作用就是从 vdex 中抽取 cdex 文件。还需要 compact_dex_converter 把 cdex 转换成标准的 dex。

cdex

Android 9 引入 CompactDex(.cdex,magic 为 cdex001),是 DEX 的压缩优化版本。

优化后的 dex/cdex 通常存放在:

/data/app/package_name/oat/arm64/base.odex
/data/app/package_name/oat/arm64/base.vdex

在 Android 9(Pie)中,APP 的 .cdex 文件 是由 dex2oat 优化生成的,通常以 odex, vdex 或直接优化后的 .art 文件形式存在。

compact_dex_converter

下载 compact_dex_converter (把 CompactDexFile 转换为标准 Dex)

https://github.com/anestisb/vdexExtractor?#compact-dex-converter

word/media/image3.png

由于 constants.sh 中下载链接已经失效了。我们手动把下载的 compact_dex_converter 放到下面路径:

vdexExtractor\tools\deodex\hostTools\Linux\api-API_29\bin\compact_dex_converter

word/media/image4.png

注释掉 /tools/deodex/run.sh 中 deps_prepare_env “$apiLevel” 的方调用,去掉自动下载 compact_dex_converter

word/media/image5.png

vdex 转换 dex

执行 run.sh 开始转换

cyrus@cyrus:/mnt/d/Python/anti-app/vdexExtractor$ ./tools/deodex/run.sh -i ./test -o ./test
[INFO]: Processing 1 input Vdex files
[INFO]: 1 binaries have been successfully deodexed

cdex 转换 dex

通过 compact_dex_converter 把 cdex 转换 dex

./tools/deodex/hostTools/Linux/api-API_29/bin/compact_dex_converter -w ./test ./test/base.cdex

调用示例

进入 /data/app 目录下找到目标 app 的 oat 文件存放路径

wayne:/data/app # ls
com.android.chrome-b1d3YEy1eVrwwjPOa1oq5A==       com.iflytek.inputmethod-s1r9JFv0-eKNskzHyrh_vQ==
com.cyrus.example-uIsySv7lFm21qMVPnPJ-pw==        com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==
com.cyrus.example.plugin-YsXrxPvfWYdsWHxFKjcusw== com.tencent.mm-ql7ajyK9JqKXli5pgu88nw==
com.cyrus.example.test-R06ZNyf5doqJFOcZ6EaYHQ==   com.xingin.xhs-HeYr1dfB-rU7NjxJiLiDeg==

进入目标目录,找到 base.art base.odex base.vdex

wayne:/data/app # cd com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==
wayne:/data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ== # ls
base.apk lib oat
wayne:/data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ== # cd oat
wayne:/data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/oat # ls
arm64
wayne:/data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/oat # cd arm64/
wayne:/data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/oat/arm64 # ls
base.art base.odex base.vdex

拉取到本地

adb pull /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/oat/arm64 ./test

执行 run.sh 把 vdex 转换为 dex

./tools/deodex/run.sh -i ./test -o ./test

输出如下:

cyrus@cyrus:/mnt/d/Python/anti-app/vdexExtractor$ ./tools/deodex/run.sh -i ./test -o ./test
[INFO]: Processing 1 input Vdex files
[INFO]: 1 binaries have been successfully deodexed

转换完成后的 dex 文件

word/media/image6.png

拖入 jadx 能正常识别

word/media/image1.png

http://www.xdnf.cn/news/3975.html

相关文章:

  • VLA算法总结对比——RT1 / RT2 / Pi0 / Octo/ RDT / OpenVLA
  • 钩子函数和参数:Vue组件生命周期中的自定义逻辑
  • 2.3 向量组
  • Linux电源管理(6)_Generic PM之挂起功能
  • Ubuntu K8S(1.28.2) 节点/etc/kubernetes/manifests 不存在
  • n8n工作流自动化平台:生成图文并茂的分析报告之Merge节点详细说明
  • labelimg快捷键
  • DXFViewer进行中 : ->封装OpenGL -> 解析DXF直线
  • SpringMVC框架详解与实践指南
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.3 数据脱敏与安全(模糊处理/掩码技术)
  • 力扣119题解
  • 六、shell脚本--正则表达式:玩转文本匹配的“万能钥匙”
  • Java使用JDBC操作数据库
  • OpenCV进阶操作:图像直方图、直方图均衡化
  • 2.CFD 计算过程概述:Fluent在散热计算中的优势
  • 【Linux】linux入门——基本指令
  • Qt 信号槽机制底层原理学习
  • C++笔记之模板与可变参数模板
  • 动态链接库(DLL)
  • 网狐飞云娱乐三端源码深度实测:组件结构拆解与部署Bug复盘指南(附代码分析)
  • LeetCode 热题 100 17. 电话号码的字母组合
  • 分布式事物
  • VTK 系统架构
  • 【NLP】33. Pinecone + OpenAI :构建自定义语义搜索系统
  • 五一作业-day04
  • 解决跨域的4种方法
  • CRS 16 slot 设备硬件架构
  • 【RK3588嵌入式图形编程】-Cairo-Cairo图形库支持后端
  • 嵌入式Linux驱动学习
  • 哈希算法、搜索算法与二分查找算法在 C# 中的实现与应用