发现问题

项目需求的缘故,需要参考合作方系统里某个系统应用的编写,作为挑选技术方案的参考。但对方的代码并不对我们开放,且沟通成本非常高。如果我们恰巧有系统的root权限,那么最快的方法就是反编译这个应用了。

以GE11项目 /system/app/HwCarresmanagerCar 目录下的座舱管家为例,进到这个目录会发现有 HwCarresmanagerCar.apk 文件和 oat lib 文件夹。

使用 adb pull 将他们拉取到电脑上(需要root权限),再用熟悉的apk反编译工具将EasterEgg.apk反编译。你会发现反编译出来的内容除了resources资源目录以外对应代码的sources目录下只有可怜的两个文件:

代码去哪儿了呢?

分析问题

我们打开oat/arm64目录,发现两个文件:HwCarresmanagerCar.odex, HwCarresmanagerCar.vdex

关于这两个文件格式和他们的作用如下:

Odex文件是早期Android版本中用于存储应用程序优化后的机器码的文件格式,而Vdex文件是Android 8.0及更高版本中引入的新格式,用于存储预优化信息,帮助ART在设备上进行更好的优化。 Vdex文件的引入使得ART在应用程序执行时可以更灵活和高效地进行优化,从而提高应用程序的性能。

而这台车机的系统版本为 Android10,所以代码应该在 HwCarresmanagerCar.vdex 文件里。

一般的反编译工具例如 apktool, jadx, d2j, JavaDecompiler 是针对没有经过优化的原始字节码dex文件进行反编译的,遇到odex/vdex这种机器码格式就无能为力了。

解决问题

万能的 GitHub 提供了解决方案:vdexExtractor

按照README的指引,我clone代码到~/GitHub/Utilities/vdexExtractor/并编译,然后在~/temp/.../oat/arm64目录执行

~/GitHub/Utilities/vdexExtractor/bin/vdexExtractor -i *.vdex -o ./out

成功了!

兴冲冲地打开out目录一看,傻眼了—— dex文件没有出现,取而代之的是三个cdex格式的文件

好在贴心的开发者已经给出了解释和解决方案

转换工具目前支持到 Android-29 也就是 Android 10,根据开发者的描述可以使用项目/tools/deodex目录下的脚本进行一键转换。但我执行后报缺少共享库liblzma.so

找到issues里有专门讨论cdex格式转换的单子 ,根据讨论内容发现可以直接使用静态编译的单文件工具compact_dex_converters直接对cdex文件进行转换。

推断是动态库版本的compact_dex_converters在我的电脑上缺少依赖才导致执行失败,所以我单独下载了静态编译的版本的工具

执行成功:

将依次转换完成的三个 .cdex.new 重命名为 .dex 文件。

后续的工作就很简单了,使用dex2jar工具将dex文件转换为jar文件,使用JavaDecompiler工具打开就可以看到源码了。

image-dcompile.png

其他的反编译方法可以参考这个链接