fred-ye / summary

my blog
43 stars 9 forks source link

[Android][Security]采用ProGuard进行代码混淆 #16

Open fred-ye opened 10 years ago

fred-ye commented 10 years ago

当我们开发一款APP发布之后,用户一但获得apk文件,其实可以通过逆向工程(反编译)的方式获取我们APP中的代码和各种资源文件。资源文件泄露还好,代码却是一个APP的核心,更包含了一些商业机密。代码的安全性保护通常会采用代码混淆的方式。最近在项目中用到了这个,也是折腾了一两天,今天在此总结一下:

# Project target.
target=android-19
# Use proguard
proguard.config=proguard-project.txt
  • 接着便是重点,对ProGuard进行各种配置。在网上搜索,通常可以发现有很多ProGuard的配置模板,列举了一些比较common的配置。便很多时候需要根据自己项目的需要进行特殊的配置。直接总结我在一个项目中的配置,用代码说话。
# 混淆优化,通常设置为5次便可以了。
-optimizationpasses 5

#When not preverifing in a case-insensitive filing system, such as Windows. Because this tool unpacks your processed jars, you should then use:
#中文意思大概是 不会产生 a.class, A.class这种文件,因为某些系统,如windows是不区分大小写的
-dontusemixedcaseclassnames

#指定不去忽略非公共的库类。
-dontskipnonpubliclibraryclasses

#不预校验, 预校验和dex compiler 和the Dalvik VM相关。
-dontpreverify

#在执行过程中如有异常,输出更详细的堆栈信息。
-verbose

#The -optimizations option disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle. Note that the Dalvik VM also can't handle aggressive overloading (of static fields).
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#维护注释,通常我们代码中会用到注释的。
-keepattributes *Annotation*

#Keep classes that are referenced on the AndroidManifest
-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 com.android.vending.licensing.ILicensingService

#对于Android系统中会用到的native的方法的维护,由于native方法是由系统提供,不能混淆名称。
-keepclasseswithmembernames class * {
    native <methods>;
}

#对于自写义View的维护
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 对于代码中使用到的enum的维护
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#To keep parcelable classes (to serialize - deserialize objects to sent through Intents)
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

#代码中用到了泛型,一定要加上这个,否则会报类型转换错误
-keepattributes Signature
#如果使用到WebView和javaScript调用,加上这个。
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service

也不会出现类名混淆的情况,这是因为Android系统对这些在AndroidManifest.xml文件中配置的Activity,Service已经做了处理,默认就是不混淆。所以实际上,我们的配置文件proguard-project.txt中可以不写这些的。

参考:http://stackoverflow.com/questions/5068251/android-what-are-the-recommended-configurations-for-proguard 如果想查看混淆后的效果,可能用dex2jar来反编译打包好的apk,三步:

dex2jar的使用可参看这里,或者百度。这个比较简单,不表。