我爱编程

反编译与代码混淆

2018-04-17  本文已影响0人  SlideException

出处:https://blog.csdn.net/guolin_blog/article/details/49738023

反编译代码

要想将APK文件中的代码反编译出来,我们需要用到以下两款工具:

dex2jar 这个工具用于将dex文件转换成jar文件 

下载地址:http://sourceforge.net/projects/dex2jar/files/

jd-gui 这个工具用于将jar文件转换成java代码 

下载地址:http://jd.benow.ca/

其中我们要用到的是d2j-dex2jar.bat这个文件,然后我们将Demo.apk文件也进行解压,如果不知道怎么直接解压的可以先将文件重命名成Demo.zip,然后用解压软件打开。解压之后你会发现里面有一个classes.dex文件,我们将它拷贝到dex2jar解压后的目录下,并在cmd中也进入到同样的目录,然后执行:

d2j-dex2jar classes.dex

没有报任何错误,这就说明我们已经转换成功了。现在观察dex2jar目录

可以看到,classes-dex2jar.jar这个文件就是我们借助工具之后成功转换出来的jar文件了。但是对于我们而言,jar文件也不是可读的,因此这里还需要再借助一下jd-gui这个工具来将jar文件转换成java代码。 

下面就很简单了,使用jd-gui工具打开classes-dex2jar.jar这个文件

反编译资源

要想将APK文件中的资源反编译出来,又要用到另外一个工具了:

apktool 这个工具用于最大幅度地还原APK文件中的9-patch图片、布局、字符串等等一系列的资源。 

下载地址:http://ibotpeaches.github.io/Apktool/install/

关于这个工具的下载我还要再补充几句,我们需要的就是apktool.bat和apktool.jar这两个文件。目前apktool.jar的最新版本是2.0.3,这里我就下载最新的了,然后将apktool_2.0.3.jar重命名成apktool.jar,并将它们放到同一个文件夹下就可以了

接下来的工作就很简单了,我们将Demo.apk拷贝到和这两个文件同样的目录当中,然后cmd也进入到这个目录下,并在cmd中执行如下命令:

apktool d Demo.apk

其中d是decode的意思,表示我们要对Demo.apk这个文件进行解码。那除了这个基本用法之外,我们还可以再加上一些附加参数来控制decode的更多行为:

-f 如果目标文件夹已存在,则强制删除现有文件夹(默认如果目标文件夹已存在,则解码失败)。

-o 指定解码目标文件夹的名称(默认使用APK文件的名字来命名目标文件夹)。

-s 不反编译dex文件,也就是说classes.dex文件会被保留(默认会将dex文件解码成smali文件)。

-r 不反编译资源文件,也就是说resources.arsc文件会被保留(默认会将resources.arsc解码成具体的资源文件)。

代码混淆

在Android Studio当中混淆APK实在是太简单了,借助SDK中自带的Proguard工具,只需要修改build.gradle中的一行配置即可。可以看到,现在build.gradle中minifyEnabled的值是false,这里我们只需要把值改成true,打出来的APK包就会是混淆过的了。如下所示:

release {    minifyEnabled true

proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'}

proguard-rules.pro文件中关键字描述

关键字    描述

keep    保留类和类中的成员,防止它们被混淆或移除。

keepnames    保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。

keepclassmembers    只保留类中的成员,防止它们被混淆或移除。

keepclassmembernames    只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。

keepclasseswithmembers    保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

keepclasseswithmembernames    保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

通配符    描述

<field>    匹配类中的所有字段

<method>    匹配类中的所有方法

<init>    匹配类中的所有构造函数

*    匹配任意长度字符,但不含包名分隔符(.)。比如说我们的完整类名是com.example.test.MyActivity,使用com.*,或者com.exmaple.*都是无法匹配的,因为*无法匹配包名中的分隔符,正确的匹配方式是com.exmaple.*.*,或者com.exmaple.test.*,这些都是可以的。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。

**    匹配任意长度字符,并且包含包名分隔符(.)。比如proguard-android.txt中使用的-dontwarn android.support.**就可以匹配android.support包下的所有内容,包括任意长度的子包。

***    匹配任意参数类型。比如void set*(***)就能匹配任意传入的参数类型,*** get*()就能匹配任意返回值的类型。

…    匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。

上一篇 下一篇

猜你喜欢

热点阅读