Android 逆向-反编译
最近由于机缘巧合接触到了 Android 逆向相关的事情,经过一番探索,对其有了更深刻地认识,过程中遇到了了一些坑,或者一些有用的经验,分享并记录分析一下。在整个过程中使用的工具有:
反编译:dex2jar、CFR、jd-gui、
脱壳:VirtualApp、Xposed installer、FDex2
其他:IDA、VSCode、Total commander
接下来咱们以两个具体情景,讲解整个逆向(静态代码分析)的流程,去分析两个 Apk 中相关页面的加密算法。
在开发安卓应用的过程中,我们平时写得最多的代码就是 Java(以及Kotlin),我们的逻辑也都在这一块,如果我们需要对应 apk 中代码逻辑,能直接看到这样的代码当然是最好不过的。要对相关 apk 中的代码逻辑进行分析,那么第一步便是需要对 apk 进行反编译,从而得到可以进行阅读理解的代码。
Apk的打包流程
我们先对 安卓的打包流程进行一个简单的了解,从而明白.java文件 是一步步成为 apk中的一部分的,在生成 apk 的过程中主要包含以下流程,括号中代表使用的工具:
1、打包资源文件,生成R.java文件 (aapt)
2、处理aidl文件,生成相应的.java文件 (aidl)
3、编译项目源代码,生成class文件 (javac)
4、转换所有的class文件,生成classes.dex文件 (dx)
5、编译过的资源和.dex文件都会被apkbuilder工具打包到最终的.apk文件中。 (apkbuilder)
6、对APK文件进行签名 (jarsigner)
7、对签名后的APK文件进行对齐处理 (zipalign)
主要流程参考这两张图:
https://developer.android.com/images/tools/studio/build-process_2x.png
反编译流程
在 apk的打包流程的步骤为:*(资源/aidl等)-> .java->.calss->.dex->.apk,反编译只需要对每个步骤反向进行。
.apk->.dex
安卓安装包本质上是一个压缩文件,只需要对齐进行解压即可(Mac默认解压apk是)
解压获得以下文件:
1 | ├── AndroidManifest.xml |
从目录结构得到两个.dex文件,这是由于在单个dex文件引用的方法总数不能超过65536(为什么?因为dex文件中的方法个数采用原生类型short来索引,而short是4个字节,4个字节最大数据存储量是65536),多数 app 超过了这一限制。
.dex->.class
这里我们需要利用工具 dex2jar
d2j-dex2jar: Convert .dex file to .class files (zipped as jar)
执行:
1 | sh /XXX/dex2jar-2.0/d2j-dex2jar.sh classes.dex |
生成 classes-dex2jar.jar, 这个 jar 就是从classes.dex反编译出来的 .class集合。得到了这份 .jar我们已经可以开始使用 jd-gui进行查看了,这里吐槽一下jd-gui的搜索功能,搜索功能有限,纯字符串搜索是有问题的(或许是我版本不对),可以在 File/Save all sources 将所有反编译好的文件进行保存,然后利用其他工具(例如VsCode)进行搜索。
再看上面的代码,有一部分是 字节码,工具未能将它正常反编译,为什么呢?相关解释在
https://www.zhihu.com/question/50140866
这里推荐使用 CFR,执行:
1 | java -jar /xxx/cfr-0.151.jar /xxx/classes-dex2jar.jar --outputdir /xxx/java |
CFR对于 jd-gui 有更好的支持,那还要 jd-gui 干什么呢?在我看来 jd-gui 有一个最大的好处就是能像IDE那样可以点进进入方法内部,所以推荐两则结合起来使用。
.so 反编译
在追溯逻辑的过程中,可能会遇到有 native 方法,如下:
1 | public native int dataFromNative(byte[] param, int paramInt1, int paramInt2); |
相关逻辑写在 c/c++文件中,最终把打在.so库中,这时候就需要宇宙第一反汇编分析工具 IDA了,我们在 apk 解压后的 lib 中找到对应的 .so 文件(这里可能需要一点耐心,lib中大多是第三方的,可以很好通过 so 文件名找到开发者的 so文件),利用 IDA F5 插件查看 汇编代码的伪代码。以字节某 SDK中的某段代码为例:
可以看到对应的逻辑,这时候就考验水平的时候了……
当然,IDA 是一个强大的工具,关于IDA的使用绝对不是通过查看一两篇博文就能熟练使用的,可以去查看
《IDA Pro权威指南》
总结
1、当然上述流程只针对”正常App”,但在实际的 App 不会这样轻易的被反编译,App 可能还进行了加固,那我需要对其进行脱壳才能实现正确的反编译,这一内容放在另一章节再进行讲解。
2、反编译整个流程,如果没有加固,一般操作是:解压->class2jar 进行转jar->CFR/jx-gui 反编译class,如果对逆向还有更多的操作还可以使用 apk_tool。相关流程已经在github 有开源的脚本了TTDeDroid,有兴趣的同学可以去看看,但是我感觉有些复杂,我自己也写了一个脚本apk2dex2jar2class2java.sh