一 基础知识
1 使用的比较多的反编译工具主要有
a)apktook用来获取资源文件, 查看布局文件和资源文件
指令 apktool d –f 目标apk。
b)dex2jar用来获取源码文件,将apk反编译成jar文件(classes.dex转化为.jar文件)
指令 dex2jar classes.dex (本人用的是dex2jar-2.0,操作方法类似)。
c)jd-gui 用来查看源码文件, 查看classes.dex 转化成的.jar文件。
2 为了防止反编译,加入混淆。需要配置这三个参数。
3 proguard-android.txt、proguard-project.txt和proguard-android-optimize.txt三个混淆配置文件的区别。
proguard-project.txt 针对一般Java工程的。
proguard-android.txt 针对android工程的,添加了一些针对android的proguard代码。包含了对android四大组件,
pacelable,jni,注解等的处理,但是关闭了optimization过程。
proguard-android-optimize.txt和 proguard-android.txt的不同就是增加了optimization过程。
4 mapping.txt、dump.txt、seeds.txt、 usage.txt四个文件作用与区别
mapping.txt文件,列出了源代码与混淆后的类,方法和属性名字之间的映射。这个文件对于在构建之后得到的bug
报告是有用的,因为它把混淆的堆栈跟踪信息反翻译为源代码中的类,方法和成员名字。一定要记得打包时apk与
相应map.txt保存在一起。发生错误时,用来 还原函数栈信息。
dump.txt,描述.apk包中所有class文件的内部结构
seeds.txt, 列出那些未混淆的类和成员。
usage.txt,列出从.apk中剥离的代码。
二 混淆过程
1 shrink(压缩)过程:检测并移除多余的类,fields(字段),方法,attributes(属性)。
2 optimization(优化)过程,分析并优化方法的字节码。
3 obfuscation(混淆)过程,用有一些很短的没有具体意义的名字(比如a,b,c)来代替经过压缩和优化过程
后,还剩下的类、方法和fields。这样就可以让其他人更难去反编译了。
4 preverify(预校验)过程,为类添加一些预校验信息,在Java Macro Edition和Java 6及以上版本是必须的。
三 混淆语法
混淆的语法比较多,这里就挑少量常用的介绍下,具体可以去 Proguard 官网查看。1 -dontshrink 不需要压缩
2 -dontoptimize 不需要优化
3 -libraryjars class_path 应用的依赖包,如Android-support-v4
4 -keep [,modifier,...] class_specification 这里的keep就是保持的意思,意味着不混淆某些类
例子:-keepclass com.mytest.bean.* 类名不混淆,里面成员会混淆
-keepclass com.mytest.entity.*{ *; } 类名不混淆,里面成员不会混淆
5 -keepclassmembers [,modifier,...] class_specification 不混淆类的成员
例子:-keepclassmembersclass com.mytest.utils.*{*;}
6 -keepclasseswithmembers [,modifier,...]class_specification 不混淆类及其成员
7 -keepnames class_specification 不混淆类及其成员名
8 -keepclassmembernames class_specification 不混淆类的成员名
例子:- keepclassmembernames classcom.mytest.utils.*{*;}
9 -keepclasseswithmembernamesclass_specification 不混淆类及其成员名
例子:- keepclassmembernames classcom.mytest.utils.*{*;}
10 -dontwarn [class_filter]不提示warnning
四 混淆基本原则
1 jni方法不可混淆
2 反射用到的类不混淆,否则反射可能出现问题
3 AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆
4 Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常
5 使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
6)使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
7)有用到WEBView的JS调用也需要保证写的接口方法不混淆
五 第三方库混淆原则
第三方库有混淆方案的,直接拷贝过来使用就行了,没有的话,则可以不用混淆。
六 资源混淆
这里有一遍关于资源混淆的博客,可以去看看,https://github.com/shwenzhang/AndResGuard
下面我只是列出我自己经过资源混淆前和混淆后的效果。
1 混淆前的反编译出来的资源文件
2 添加混淆之后,再反编译出来的资源文件
7 写在最后,下面都是参考过的文章
http://blog.csdn.net/qq_23547831/article/details/51581491
http://blog.csdn.net/jt_ontheway/article/details/50778501
http://proguard.sourceforge.net
8 附上一段混淆代码
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native ;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static ;
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep (...);
}