Android反编译odex然后重新打包
最近不知道怎么回事,突然把我那刷了氧OS的root了,然后就开始好奇起来氢OS所带有的那些本地化的东西,比如通话录音就是典型的一个之一。其中也做了很多的尝试,XDA上有人说把/system/build.prop里面的"persist.sys.oem.region"的值改成“CN”,我尝试了一下确实可以,但是有的APP出现了崩溃卡死的问题,我发现改了后设置里面系统版本变成了氢OS,然后三大金刚键都变成了又返回在右边了,短信默认的都出现了氢的卡片效果,电话设置里面也有了通话录音,一切都成了氢OS的样子,但是副作用是好多的第三方APP出新了不能运行崩溃等各种问题。
于是又把build.prop改成了原本的样子,然后开始了反编译的探索之旅,于是就有了这篇博客,好多中文的博客写的都过时了,真的是好几天各种挖坑填坑爬坑的结果。本文的反编译是在Android7.1.1环境下在mac操作系统下操作的
好了废话说完了,一些概念诸如为什么有odex,odex之于apk里面的dex,下面开始正文
修改这种系统预装的app然后再打包理论上需要经过以下步骤
odex -> smali files -> dex -> jar -> modify smali files -> dex -> apk(包括class.dex的apk)
一开始我就是按照这个步骤来的,因为odex依赖的系统版本比较高,好多中文博客介绍的都是过时的工具,导致中间遇到了太多太多的坑。因为我弄的这个apk是控制电话接通后的童话的那个逻辑的,所以每次弄好了还要把apk复制到手机里面,然后再复制到/system/priv-app里面,然后改权限,还要保存之前的备份等的东西然后再重启手机,再拨打电话尝试,所以操作步骤极其繁琐。应该有更好的方法,只不过目前还懒的去发现。
- odex -> smali files: 这一步是使用的smali工具,我用的是baksmali-2.2.1.jar,其基本的命令为
java -jar baksmali-2.2.1.jar deodex OPInCallUI.odex -b ./framework/arm64/boot.oat -o OPInCallUI deodex参数,指定要操作的文件名为“OPInCallUI.odex” -b参数,指定bootclasspath,也就是要把手机rom的/system/framework里面的文件直接拷贝到电脑上的当前工作目录 -o参数,指定输出的smali文件的目录
- smali files -> dex: 这一步用的还是smali工具,不过jar文件变了,为smali-2.2.1.jar,使用的基本命令为
java -jar smali-2.2.1.jar assemble OPInCallUI -o classes_o.dex assemble参数,指定smali files的文件夹所在 -o参数,指定输出的文件名为“classes_o.dex”
- dex -> jar: 这一步用的是dex2jar工具,使用的基本命令为
./dex2jar-2.0/d2j-dex2jar.sh classes_o.dex -o classes_o.jar 意思是把“classes_o.dex”转成“classes_o.jar”
- modify smali files: 这一步使用的工具主要会有不同,但是JD-GUI是少不了的,它能直接查看jar里面的class文件所对应的源代码,有了源码,看一些逻辑就方便了太多了啊。
jclasslib是查看java字节码的一个工具。其实这个地方基本用不到看java的字节码,而主要看smali(即Dalvik opcodes)文件 。
smali文件用普通的文本编辑器查看修改就可以了,但是需要先了解一下基本的语句,这是对照表。其实第2和第3步的主要目的就是看java的源码,帮助更好的理解,如果你感觉看smali跟看java是一样的,那就可以省略2和3步了 - modify smali files -> dex: 这一步是使用的还是smali工具,不过要用smali-2.2.1.jar,其基本的命令为
java -jar smali-2.2.1.jar assemble OPInCallUI -o classes.dex
- dex -> apk(包括class.dex的apk): 把第五步生成的classes.dex用压缩工具放在在手机"/system/priv-app/OPIncallUI"提取的OPInCallUI.apk里。这里我比较推荐BetterZip,可以去编辑压缩文件,制作压缩文件的时候还可以排除.DS_Store的影响。
- 把修改后的apk放回到"/system/priv-app/"里面,重启手机测试一下吧
注意:
- boot.oat依赖的时候要拷贝全面,要不然就会报错
Error occurred while loading class path files. Aborting.
org.jf.dexlib2.analysis.ClassPathResolver$ResolveException: Error while loading oat file ./boot.oat
具体的有篇文章,介绍了boot.oat和boot.art等的关系。初探boot.art与boot.oat
- 减少中间环节,我查过各种资料后总结出来流程应该是这个样子的
odex -> smali files -> dex -> jar -> modify jar -> dex -> apk(包括class.dex的apk)
后来发现这个坑实在是太深了,有的时候用低版本的baksmali的时候就会报大量的错误
org.jf.dexlib2.analysis.AnalysisException: Could not resolve the method in class Ljava/lang/reflect/Method;
以此顺延下去,肯定打包的程序不能运行了。
然后步骤多了出错的地方就更多了,定位起问题来就更麻烦了。
- 安利一个Google的工具吧android-classyshark,用来查看apk的包资源,类方法名等的工具,简直利器。再加一个插件intellij-java2smali,很方便的把java转成smali查看
其实这次反编译的初衷来源于想让我的一加3T手机的氧OS能够像氢一样拥有通话录音的功能。然后经历的种种,还受oos-call-recording项目的影响,还问了厚脸皮的问了作者原理。现在我也自建了一个项目,会上传我微改的系统的APP,使氧OS的系统APP拥有氢OS的功能,而又不失去氧OS更新快的特点。项目的地址为https://github.com/ysk666666/OxygenOS-SystemAppModified