/ 技术

Proguard混淆

这里仅仅说Android的混淆,其他平台基本相同。

不同的IDE有不同的配置方法

Android Studio的配置略有差异,可以参考前文

混淆的大致原理就是rename class(所以混淆的过程比较慢),混淆的初衷,并不是为了不让人看源码,毕竟java的虚拟机机制就决定了,源码肯定是可以反编译出来的;其主要目的是让反编译后的代码“难以”看懂。

例如打开一个混淆后输出的mapping文件,可以看到:

(某代码片段,请无视。)

这样一来,反编译后的代码里面,基本就是a.b.c(d.e)这种代码(也许原来只是Util.isNetworkAvailable(context)),大大增加了阅读难度;也就达到了防止反编译的目的。

但经常会误伤,因为是rename,所以对name敏感(依赖name)的方法或者库就会无法正常工作。例如反射,例如JNI的接口class(依赖class name来找context object),例如GSON这些常用工具库。

解决办法就是修改proguard的配置文件,将这些敏感class置为例外。

常用方法如下:

  • 排除指定类A
-keepclassmembers class com.xxx.xxx.A { *; }
  • 将类A的子类全部排除
-keepclassmembers class * extends com.xxx.xxx.A { *; }
  • 将包P内的class全部排除
-keep public class com.xxx.P.* { *; }
  • 将包P内的class及subclass全部排除
-keep public class com.xxx.P.** { *; }

注意***的差别;

注意最后的{ *; },用法很多,可以指定仅排除public/protected,如:

{ public protected *;}

当然还可以直接更直接一些:

{ <fields>; <methods>; }

如果是使用Gson的话,还可以直接如下使用方式来避免混淆问题:

@SerializedName("data")
ArrayList<Object> data;

另外可以通过

-printmapping mapping.txt
```来输出mapping,基本这些就够用了。记录一下。

---

其实proguard当然不仅仅可以混淆,[官网](http://proguard.sourceforge.net/)介绍:
>ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. ***It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions.*** It renames the remaining classes, fields, and methods using short meaningless names. Finally, it preverifies the processed code for Java 6 or higher, or for Java Micro Edition.

---

BTW,既然说到了混淆,那就顺便提一下反编译神器[dex2jar](https://code.google.com/p/dex2jar/)吧,简单好用,方便自测混淆是否成功~