Android Apk 文件反编译和重新打包的过程分析

学习的方式有很多种,Read the fucking source code 绝对不失为最佳的方式。除了阅读 Android SDK 的源码,还能通过反编译 APK 的方式,阅读他人开发的应用源码。本文就来聊聊在 Mac 环境下如何借助第三方工具反编译 APK 压缩文件(通过爱加密、360加固等手段处理的 APK 文件除外),阅读源码、修改源码并重新打包成一个新的 APK 安装文件。

准备工具


本文描述的反编译手段需要借助三个工具,分别是:apktool、dex2jar 和 jd-gui,下面我一一介绍下他们的下载及配置过程。

apktool

  1. 打开 apktool 脚本链接网页,右键存储为一个命名为 apktool 的文件,记得不要添加任何格式后缀;

  2. 打开 apktool.jar 下载链接,下载最新版本,下载完成之后重命名为 apktool.jar;

  3. 打开命令行工具,使用 cp 命令将前面两步下载的 apktool 脚本文件和 apktool.jar 文件复制到 PC 的 /usr/local/bin 目录下 (复制前的文件至此可以删除),如:

    1
    sudo cp apktool apktool.jar /usr/local/bin
  4. 使用 chmod 命令为上一步复制过去的两个文件添加可执行权限,如:

    1
    chmod +x apktool apktool.jar
  5. 操作至此,便可以在任一路径下使用 apktool 命令了。现在,你就可以使用 apktool -version 命令检查以上过程是否配置正确。

有关 apktool 工具的详细信息,可以参考官网介绍:A tool for reverse engineering Android apk files

dex2jar

  1. 你可以从 softpedia 或者 sourceforge 网站找到 dex2jar 的 Mac 版下载链接,并解压缩;

  2. 同样使用 chmod 命令修改 sh 文件的用户权限,如:

    1
    chmod a+x *.sh

jd-gui

softpedia 或者 http://jd.benow.ca/ 网站下载并解压缩即可,里面的 JD-GUI 文件便是阅读 jar 包的应用程序。

反编译 apk 资源文件


apk 文件就是一个压缩文件,通过解压缩工具便可以打开并解压缩。但是里面的资源文件,除了 drawable 图片资源,其他都是经过编译处理的二进制文件,什么也看不出来。

而使用 apktool 工具可以直接从 apk 文件中反编译出诸如 AndroidManifest.xml 、layout、strings 等资源文件,可以直接修改,供再次打包。如:

1
apktool d example.apk

反编译 java 源码文件


解压缩 apk 文件,可以看到 classes.dex 源码文件,可能不止一个。通过 dex2jar 工具可以将其转化为 jar 文件,并使用 jd-gui 工具打开并阅读应用源码。

第一步,dex2jar 操作,得到 classes-dex2jar.jar 文件。注意 d2j-dex2jar.sh 和 classes.dex 文件的路径,按需修改:

1
sh d2j-dex2jar.sh classes.dex

第二步,使用 jd-gui 打开 classes-dex2jar.jar 文件,便可以看到目标应用所用到的第三方 library 和 开发源码,如:

如果对方开发人员在工程中开启了混淆功能,将会增加你的阅读难度,不过仔细分析,也能找到一些蛛丝马迹,给予你一些“灵感”。

当然,也可以直接针对 apk 文件使用 dex2jar 命令获取 jar 文件,减少上述 apk 文件解压缩的这一步骤,如:

1
sh d2j-dex2jar.sh example.apk

重新打包 apk 安装文件


学会如何反编译 apk 文件后,我们还可以修改 apk 文件中的内容,比如应用名称、桌面图标,甚至是 Java 源码等,然后使用 apktool 工具重新打包,产生一个新的 apk 安装文件。

这里以修改应用名称和桌面图标为例,看看如何重新打包 apk 文件并安装至手机上。(此处仅供学习参考,勿作恶!)

第一步,使用前文介绍的反编译 apk 资源文件的方式得到反编译后的文件夹,打开 AndroidManifest.xml 文件,找到 application 标签的 label 和 icon 属性。这样,我们就知道在哪里修改对应的资源文件了;

第二步,找到对应的 drawable 图标文件和 strings 字符串资源,比如 ic_launcher.png 和 app_name,替换图标并修改字符串内容;

第三步,使用 apktool b files 命令编译打包,这里的 files 对应第一步反编译 apk 文件时得到的应用文件夹。执行完毕,便会得到一个新的 apk 文件;

注意:此时得到的 apk 文件是没有没有经过签名的,使用 adb install 命令安装时会得到一个失败提示:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]。

第四步,生成自己的签名文件。你可以选择使用 Android Studio -> Build -> Next -> Create New… 可视化操作界面生成一个新的签名文件,也可以直接使用 keytool 工具直接在终端工具上生成,如:

1
keytool -genkey -keystore example.keystore -keyalg RSA -validity 10000 -alias example

第五步,使用 jarsigner 工具为 apk 文件签名,签名过后得到的 apk 文件便可以使用 adb install 命令安装至连接到 PC 的安卓设备上了。签名命令如下:

1
jarsigner -verbose -keystore example.keystore -signedjar example-signed.apk example.apk example

注意:如果签名过后的 apk 文件依旧安装失败,可以试试在签名命令上加上 -digestalg SHA1 -sigalg MD5withRSA -tsa 参数。当然这里我在测试时没有添加该参数,但也能正常安装。

修改资源文件并重新打包还是比较简单的,但是修改 java 源码再重新打包就比较复杂了,特别是在改动较大的情况下。「鸿洋」大神有一篇文章,描述了如何反编译 apk 并为其添加启动页广告的过程,当然也没有涉及到原开发人员的 Java 源代码改动,详情可参考: Android 反编译初探 应用是如何被注入广告的