在学习开发Android过程中,使用过几次反编译,现在就把反编译时查找到的资料做一个整理与总结。要明确一个概念:反编译也只是学习的一个手段,我们要正确认识反编译。
背景铺垫
首先把apk文件的结构做一个介绍,apk包其实是一个zip文件,可以直接进行解压,解压后,结构如下图所示:

![]()
具体的介绍如下:
![]()
![]()

我常用的方法
我在平时最常用的方法是使用dex2jar与jd-gui来反编译apk,这样可以看到基本的代码实现,具体步骤如下:
1,解压apk文件
网上有方法是先把.apk后缀改为.zip,然后解压,其实.apk也是zip的一种,可以直接进行解压。
2,把解压后的classes.dex文件复制到dex2jar文件夹下
3,打开命令提示符,进入dex2jar文件夹,在命令行下运行dex2jar classes.dex
4,在dex2jar文件夹下生成文件classes.dex.dex2jar.jar
5,使用jd-gui来打开所生成的classes.dex.dex2jar.jar文件,效果如下图所示:

![]()
基本能看到绝大部分的代码实现,具有一定的参考意义。
对上面方法的补充
上面这种方法操作简单,对源代码查看方便,但是却不能看到布局文件,即xml文件,下面这种方法可以把apk包中的xml文件进行反编译,配合第一种方法,更好地理解代码。
需要使用的工具:AXMLPrinter2.jar
1,把所需要转换查看的xml文件拷贝到该工具所在目录下,如AndroidManifest.xml
2,在命令行下输入命令:java -jar AXMLPrinter2.jar AndroidManifest.xml -> AndroidManifest.txt
3,在工具所在目录下即可生成xml布局文件的反编译版本,效果足够参考了
理解起来有难度,但熟悉之后更方便的反编译
接下来介绍一种反编译方法,这种方法我不常用,只是了解。
通过这种方法可以得到一个apk文件的总体表现(以这种方法定义的形式)。结果是把java源文件转换为了一种smali文件(就是这种文件不好看)。值的一提的是,这种方法所得到的xml文件更加可理解。而且,这种方法可以实现反编译后再编译回去。
工具:apktool1.5.1.tar.bz2 与 apktool-install-windows-r05-ibot.tar.bz2
步骤:
1,把这两个工具解压到一个目录下,一共有三个文件
2,把需要反编译处理的apk文件拷贝到同一个目录下
3,命令行进入该目录,输入命令:
apktool d ***.apk savedir
就可以把***.apk文件反编译到savedir目录下(该目录之前无需手动创建)
4,所得内容如下图所示:
5,在这个基础上,你可以对文件进行修改,然后可以在把它打包回去。命令如下:
apktool b savedir
6,结果如下图所示:
7,可以发现多了两个文件夹,build与dist,build文件夹下存放的是重新生成apk时的过渡性文件,而dist文件夹下存放的是重新打包生成的apk文件
据说生成的java源文件更好看
这种方式是把classes.dex文件反编译成一种ddx文件,这种文件在我看来和smali文件一样难懂,不过网上有对于这种文件格式的解释,配合查看或许效果最佳(我还没试过,不敢乱说)。
工具:ddx1.25.jar
步骤:
1,命令行下进入ddx1.25.jar所在目录
2,把classes.dex文件拷贝到同一目录下
3,创建一文件夹存放反编译文件(必须事先存在这样一个文件夹)
4,输入命令:
java -jar ddx1.25.jar -o -D -r -d 文件夹 classes.dex
5,得到ddx源码
网上有这种格式文件的阅读帮助,需要的同学自己b或g去吧!
最最最方便的方法
这种方法的确最方便,直接安装一个软件,然后就可以右击需要反编译的文件,直接反编译,也可以右击一个文件夹,再编译回apk。
工具名:APK+Dex文件反编译及回编译工具v1.7.2正式版(防误杀).rar
需要的同学自己下吧!这个工具的使用说明写得也详细,就不在这里说了。
要注意一点,这些都只是工具,我们使用它们只是去学习罢了。
补充
刚写完反编译apk,就看到一篇博客,写得是如何预防反编译,现copy在下(有意思)!
作为Android应用开发者,不得不面对一个尴尬的局面,就是自己辛辛苦苦开发的应用可以被别人很轻易的就反编译出来。
Google似乎也发现了这个问题,从SDK2.3开始我们可以看到在android-sdk-windows\tools\下面多了一个proguard文件夹
proguard是一个java代码混淆的工具,通过proguard,别人即使反编译你的apk包,也只会看到一些让人很难看懂的代码,从而达到保护代码的作用。
下面具体说一说怎么样让SDK2.3下的proguard.cfg文件起作用,先来看看android-sdk-windows\tools\lib\proguard.cfg的内容:
- -optimizationpasses 5
- -dontusemixedcaseclassnames
- -dontskipnonpubliclibraryclasses
- -dontpreverify
- -verbose
- -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-
- -keep public class * extends android.app.Activity
- -keep public class * extends android.app.Application
- -keep public class * extends android.app.Service
- -keep public class * extends android.content.BroadcastReceiver
- -keep public class * extends android.content.ContentProvider
- -keep public class * extends android.app.backup.BackupAgentHelper
- -keep public class * extends android.preference.Preference
- -keep public class com.android.vending.licensing.ILicensingService
-
- -keepclasseswithmembernames class * {
- native <methods>;
- }
-
- -keepclasseswithmembernames class * {
- public <init>(android.content.Context, android.util.AttributeSet);
- }
-
- -keepclasseswithmembernames class * {
- public <init>(android.content.Context, android.util.AttributeSet, int);
- }
-
- -keepclassmembers enum * {
- public static **[] values();
- public static ** valueOf(java.lang.String);
- }
-
- -keep class * implements android.os.Parcelable {
- public static final android.os.Parcelable$Creator *;
- }
从脚本中可以看到,混淆中保留了继承自Activity、Service、Application、BroadcastReceiver、ContentProvider等基本组件以及com.android.vending.licensing.ILicensingService,
并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考<proguard_path>/examples中的例子及注释。)
让proguard.cfg起作用的做法很简单,就是在eclipse自动生成的default.properties文件中加上一句“proguard.config=proguard.cfg”就可以了
完整的default.properties文件应该如下:
- # This file is automatically generated by Android Tools.
- # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
- #
- # This file must be checked in Version Control Systems.
- #
- # To customize properties used by the Ant build system use,
- # "build.properties", and override values to adapt the script to your
- # project structure.
-
- # Project target.
- target=android-9
- proguard.config=proguard.cfg
大功告成,正常的编译签名后就可以防止代码被反编译了。反编译经过代码混淆的apk得到的代码应该类似于下面的效果,是很难看懂的:
