[转]利用Ant与Proguard混淆

来源:互联网 发布:js 不停刷新 编辑:程序博客网 时间:2024/05/18 00:42

[转]利用Ant与Proguard混淆
2013-3-11阅读6921 评论1

 当前的web项目有引用到子工程项目,而且多个子工程项目也有引用到其它的工程项目,现要求利用Ant自动将web项目打包成war包,其中引用到的子工程项目需打成jar包,而且必须是混淆后的jar包。其中混淆代码的工具选择了开源的Proguard(http://proguard.sourceforge.net/),可以运行proguard自带的proguardgui.jar(图形化用户界面)生成proguard配置文件。

ProGuard是一个免费的java类文件压缩,优化,混淆器.它探测并删除没有使用的类,字段,方法和属性.它删除没有用的说明并使用字节码得到最大优化.它使用无意义的名字来重命名类,字段和方法.

ProGuard的使用是为了:

1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用.
2.创建的程序和程序库很难使用反向工程.
3.所以它能删除来自源文件中的没有调用的代码
4.充分利用java6的快速加载的优点来提前检测和返回java6中存在的类文件.

参数:

-include {filename} 从给定的文件中读取配置参数

-basedirectory {directoryname} 指定基础目录为以后相对的档案名称

-injars {class_path} 指定要处理的应用程序jar,war,ear和目录

-outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称

-libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件

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

-dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。

保留选项
-keep {Modifier} {class_specification} 保护指定的类文件和类的成员

-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好

-keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。

-keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)

-keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)

-keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)

-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件

压缩
-dontshrink 不压缩输入的类文件

-printusage {filename}

-whyareyoukeeping {class_specification}

优化
-dontoptimize 不优化输入的类文件

-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用

-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员

混淆
-dontobfuscate 不混淆输入的类文件

-printmapping {filename}

-applymapping {filename} 重用映射增加混淆

-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称

-overloadaggressively 混淆时应用侵入式重载

-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆

-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中

-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中

-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名

-keepattributes {attribute_name,…} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

-renamesourcefileattribute {string} 设置源文件中给定的字符串常量

因为我们开发的是struts2+spring+openjpa的架构的项目,所有需要很详细的配置,其中proguard需要的injars,outjars还有其它的一些libraryjars在Ant的build.xml文件以参数形式加入。
proguard.pro文件具体内容:

-libraryjars

-printmapping proguard.map

-overloadaggressively
-defaultpackage ”

-flattenpackagehierarchy ”

-dontusemixedcaseclassnames

-keeppackagenames

-allowaccessmodification
-dontoptimize

因为项目中使用到了jpa的Annotation注解,需要保留这个属性

-keepattributes Annotation

Keep web listener-class,自己编写的web listener,不能混淆,不然启动服务的时候会报错

-keep public class com.test.mylistener {
public protected *;
}

Keep jpa dao, 自身编写的一些dao接口不能混淆,而且如果是有被spring管理的dao, 也应该不进行混淆

-keep public class com.test.dao.* {
public protected *;
}

其中jpa dao中使用到的一些重要接口也能进行混淆

-keep public class com.test.persistence.core.QueryLiteral {
public protected *;
}
-keep public class com.test.persistence.JpaDao {
public protected *;
}

Keep beans managed by spring framework,spring管理的bean不进行混淆

-keep public class com.test.provider.* {
public protected *;
}

Keep Network interface

-keep public class com.test.loader.Network {
public protected *;
}

Keep entity classes extends java.io.Serializable

保留jpa中使用到的所有实体类,不进行混淆

-keep public class * implements java.io.Serializable{
public protected private *;
}

-keep public class com.test.entity.* {
public protected private *;
}

Keep - Applications. Keep all application classes, along with their ‘main’ methods.

-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}

Keep names - Native method names. Keep all native class/method names.

-keepclasseswithmembers,allowshrinking class * {
native ;
}

proguard和build.xml文件具体目录结构:
server工程
-src目录
-build目录
-proguard目录
-dictionaries 主要存放混淆时需要用到字典文件,可以使用官网下载到的proguard.zip包中dictionaries的两个文件(dictionaries/compact.txt,dictionaries/shakespeare.txt)
-lib 存放proguard.jar包,这是混淆中使用到的最主要的一个jar包(下载到的proguard.zip中)
-proguard.pro 主要的混淆配置文件
-build.xml

结合文件形式来配置
ANDROID代码混淆的实践

  1. 基本配置

eclipse下建立android工程,就会生成proguard.cfg和project.properties,在后面的文件追加proguard.config=proguard.cfg即可让前面的配置文件在export时生效。默认的那个文件有一些内容,这里给一个更通用点的。

—————Begin: proguard configuration common for all Android apps ———-

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/,!class/merging/
-keepattributes Annotation
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

以下两个命令配合让类的路径给删除了

-allowaccessmodification
-repackageclasses ”

记录生成的日志数据,在proguard目录下

-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt

异常都可以忽略就打开

-dontwarn

-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
-dontnote com.android.vending.licensing.ILicensingService

-keepnames class * implements java.io.Serializable

Explicitly preserve all serialization members. The Serializable interface

is only a marker interface, so it wouldn’t save them.

-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

Preserve all native method names and the names of their classes.

-keepclasseswithmembernames class * {
native ;
}

-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet, int);
}

Preserve static fields of inner classes of R classes that might be accessed

through introspection.

-keepclassmembers class *.R$ {
public static ;
}

Preserve the special static methods that are required in all enumeration classes.

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

如果你的工程是对外提供方法调用就打开

-keep public class * {

public protected *;

}

—————End: proguard configuration common for all Android apps ———-

  1. 解决export打包的报错

这个时候export提示“conversion to Dalvik format failed with error 1”错误,网上说法有好多种,最后我还是把proguard从4.4升级到4.8就解决了。官方地址是http://proguard.sourceforge.net。上面的配置文件参数可以在这里查阅。
升级办法很简单,就是把android sdk目录下的tool/proguard目录覆盖一下即可。
3. 打包出来的程序如何调试

一旦打包出来,就不能用eclipse的logcat去看了,这里可以用android sdk中ddms.bat的tool来看,一用就发现和logcat其实还是一个东西,就是多了个设备的选择。
4. 使用 gson 需要的配置

当Gson用到了泛型就会有报错,这个真给郁闷了半天,提示“Missing type parameter”。最后找到一个资料给了一个解决办法,参考:http://stackoverflow.com/questions/8129040/proguard-missing-type-parameter。
另外我又用到了JsonObject,提交的Object里面的members居然被改成了a。所以上面给的东西还不够,还要加上

用到自己拼接的JsonObject

-keep class com.google.gson.JsonObject { *; }

我个人建议减少这些依赖包混淆带来的麻烦,干脆都全部保留不混淆。例如
-keep class com.badlogic.* { ; }
-keep class * implements com.badlogic.gdx.utils.Json*
-keep class com.google.* { ; }

  1. 使用libgdx需要的配置

参考http://code.google.com/p/libgdx-users/wiki/Ant
6. 验证打包效果

我是利用了apktool的反编译工具,把打包文件又解压了看了一下,如果包路径、类名、变量名、方法名这些变化和你期望一致,那就OK了。命令:
apktool.bat d xxx.apk destdir

总结

这个东西用起来也不是很简单,特别是你程序用到的高级特性多,就更容易出问题。另外proguard的参数看起来确实也有点不好理解,打包过程慢,测试也比较浪费时间。东西虽好,但真不是那么容易上手。

0 0
原创粉丝点击