Android应用反编译
概述
上一篇“利用smali代码注入修改Android应用”中我们介绍了反编译Android应用,修改smali代码并重新打包。在这一篇中深入介绍一下反编译Android应用,本文重点放在如何反编译Android应用,以及将字节码反编译为.class文件,进一步反编译为.java文件,并用工具分析查看。
在学习工作过程中经常会碰到一些问题,需要获取Android应用的更多信息,对程序员来说,如果手头有应用的源代码,自然一切都好说,但是如果没有源代码呢,这个时候就可以通过反编译获取更多的信息,分析应用的代码和逻辑,甚至可以修改已有应用的资源文件和代码,输出log,随意添加代码和资源文件,重新打包签名,将其变成“山寨”的应用等。
Android SDK在生成.apk应用时将应用的资源文件和Java文件分开处理,因此接下来我们也分成“反编译资源文件”、“反编译Java文件”两部分来介绍反编译方法和步骤。
首先看看.apk安装包的内部格式,其实.apk是一种.zip格式的压缩包,直接用压缩软件就可以打开查看。以下是用压缩软件打开巴士管家应用安装包后的截图:
Assets文件夹原封不动存放着应用源代码assets文件夹下的文件夹和文件;
Com文件夹是新的SDK在生成apk文件时创建的,以巴士管家客户端来看,其中存放着databinding相关的二进制文件,和一些第三方SDK的签名文件。更多作用待续。
lib文件夹存放着源代码的.so库,如果源代码.so库支持多种CPU架构,那就会有多个子文件夹;
res文件夹下存放在各种资源文件和图片,.png,.jpeg,.xml等,包括布局文件也在其中。.xml文件是编译后存放的,如果直接用文本编辑器打开,看到的会是乱码。
META-INF文件夹比较特殊,是打包时由工具自动生成的,反编译不需要关心其中内容。我们还是来看看其中的内容:
其中文件的主要作用之一是校验应用的签名信息,可以通过其中的信息校验程序是否是原生的,或是他人反编译后重新生成的。如果apk文件被人篡改,那在第二次安装时系统会检测出apk文件的签名和已 安装的应用文件签名不一致,从而无法继续安装。豌豆荚的洗白白功能也是利用apk安装包这个特性,检测应用是原版还是山寨。各大应用市场能鉴别某款应用是不是山寨的应用,也是靠这个文件夹下的文件。
AndroidManifest.xml存放着源代码对应的AndroidManifest.xml文件,作用不再赘述。当然,也是经过编译的。
Classes.dex文件主要存放经过编译的.java文件,也就是Java虚拟机的字节码文件,可以直接在Java虚拟机上运行。
Resources类根据资源ID来查到资源名称,这是因为资源ID与资源名称的对应关系是由打包在APK里面的resources.arsc文件中的,如R.layout.activity_main这样的ID与实际布局文件activity_main.xml的对应关系。
反编译用到的工具
ApkTool2.2.jar
https://ibotpeaches.github.io/Apktool/
AXMLPrinter2.jar
https://github.com/rednaga/axmlprinter/releases
Dex2jar-0.0.9.9
https://github.com/pxb1988/dex2jar
Jd-GUI-0.3.6.exe
https://github.com/java-decompiler/jd-gui
反编译资源文件
assets、lib下的文件,.so文件,图片等资源不需要反编译(.so文件如有需求另述)
.xml文件可用apktool或者AXMLPrinter,两种工具反编译,结果是一样的:
此时app-release文件夹下存放着已反编译的xml文件,可以直接用文本编辑器打开。
使用AXMLPrinter2反编译二进制的.xml文件
此种方式不用apktool,仅使用AXMLPrinter2反编译二进制的.xml文件,生成文本格式的.xml文件。
直接解压.apk文件,用AXMLPrinter工具反编译.xml文件:
看看生成的AndroidMainfest.out.xml文件:
反编译Java文件
(附:上一篇“利用smali代码注入修改Android应用”中我们利用apktool反编译apk文件,生成smali格式的代码,本文不再赘述,只讲述如何反编译.dex文件)
解压.apk文件,提取.dex文件
反编译.dex生成.jar文件
利用jd-gui反编译.class,预览生成的.java文件
需要注意的是,jd-gui只是尽其可能将.class文件反编译为.java文件,限于代码和字节码之间语法差异,以及反编译工具及水平等限制,反编译出来的代码往往和源代码之间有较大差异,甚至是完全错误的。例如下面这个for循环:
明显是有问题的,应该是像下面这样的:
小技巧及总结:
1, Apktool可重新打包生成.apk、利用签名文件为.apk进行二次签名;
2, Apktool可反编译资源文件(assets/、lib/、com/、图片、xml布局文件),反编译生成smali文件;
3, 分析复杂的java业务逻辑,可以先利用dex2jar、jd-gui反编译查看java代码;分析完成后,可按需要修改.class对应smali文件,再使用apktool重新打包签名;