ProGuard之——代码混淆

来源:转载

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/49622317

1. 混淆器的选择

ProGuard


下载地址:http://proguard.sourceforge.net/index.html#downloads.html

2. 优化策略

因为公司项目都是 SSH 或者 SSJ 框架,涉及到非常多的配置文件,所以

a.  必须保留实现Action类中的公有的,友好的,私有的属性和公有的方法。

b.  因为配置文件中的类名是一个完整的类名,如果经过处理后就有可能找不到这个类。

c.  类中的属性是jsp页面所需要的,如果经过处理jsp页面就无法得到action中的数据。

所以混淆器的配置需要根据 工程使用的技术、标准的编码规范以及pro配置编写人员对工程的深入理解,否则极易导致工程无法正常运行。

ProGuard混淆时运行proguard.jar,并读取配置文件 ***.pro

ProGuardUI 图形化界面不能完全满足需要,需要单独配置 pro文件,但通过图形界面配置可以很方便的查看配置内容。如图:


3. 命令

java -jar ProGuard4.8/lib/proguard.jar @path/TrueCMS.pro

4. 为混淆器增加内存

使用 proguard进行混淆时,若项目比较大,经常会报 OutOfMemory错误,则需要增加混淆器的内存

java -Xms256m -Xmx512m -jar proguardgui.jarconfiguration.pro
注意:要在ProGuard目录的bin下运行这些命令

5.参数简介

参数

-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} 设置源文件中给定的字符串常量

6.详细说明

A.     综述

这是一个不应该在开源社区出现的东西,但它的的确确是一个开源的项目,正像它的名字一样,Proguard,即Program Guard(程序卫士),它代表了开源的相对面--代码保护。

经过几天的摸索,终于对Proguard应用于实际项目有一些不成熟的见解。

上面提过,对于Web工程,公司都是用了SSH/SSJ框架,这类框架中所有action/service/dao/domain以及包结构都固定写死在对应的配置文件中,这使得Proguard发挥的空间仅限于 service/dao内的方法、各部分的通用工具方法及util工具类,Proguard灵活配置的优势便显现出来了。

B.    使用说明
1.在Eclipse中选中需要混淆的工程,右键Exprot->选择jar文件导出备用
2. 打开 proguard4.8/lib 目录下的proguardgui.jar,在input/output 选项中增加输入文件,找到刚才导出的jar文件并确定,然后增加输出文件。

3.在  中增加工程lib文件夹下所有的jar包,以及java jre


4.Shrinking(压缩)中不设置任何配置 如图


 
5.Obfuscation如下图配置


其中 jss.txt 是我们提供给proguard 进行混淆的字符串,若为空,ProGuard会按小写英文字母a,b,c,d….顺序混淆。

6.Optimization如图配置


7.Information 如图配置


Target中选择当前jdk版本

8.在Process选项中选择, 将配置保存成 **.pro文件

9.打开pro文件


在配置后加入

-keep class WebRoot.WEB-INFO.lib.* ---不混淆lib文件夹中所有jar包-keep class * extends cn.com.trueway.platform.** { public <methods>;} #不混淆继承于platform的所有类
其他配置请根据实际情况进行添加
10.配置完成后在ProGuradUI中——>——>加载配置文件,——>

即开始混淆,混淆完的文件会根据配置文件输出到指定位置。
也可以使用命令行完成上述动作,且执行效率会有质的飞跃。
命令为:

(java -Xms256m -Xmx512m –jar D:/proguard4.8/lib/[email protected]:/ rm.pro)

7. 注意要点

A.在产品的开发过程中,应养成良好的代码习惯,将可重复利用的代码都封装成私有方法或工具类,便于代码维护及代码混淆的效果。
B.    工程比较大时,请使用命令行方式混淆,效率会提高10倍以上。
C.通配符:' ?“为任意单个字符,‘*’的任意数量的字符(不包扩分隔符),“**”为任意数量的字符,‘%’对于任何原始类型,“***”为任何类型,和“…“为任意数量的参数。
D.    虽然ProGuard声称支持war包,但遗憾的是混淆完的war包会丢失所有class,所以一定需要war包的情况下需要先对jar包混淆,再将jar包内的class替换到war包内,可正常运行,未出现异常。
E.配置文件中如下配置一定不能颠倒顺序,否则会无法生成outjar。
-injars 'D:/bak/pg/in/rm.jar'
-outjars 'D:/bak/pg/in/rmout.jar'
F.需要注意web.xml中配置的filter, listener等需要被skip掉。
G.ProGuardUI 可以看做是一个配置文件生成器,而不适合做混淆动作。
H.一个完整的配置例子:

*************************************************************************************************************************************************************************************

-injars 'D:/bak/pg/in/rm.jar'-outjars 'D:/bak/pg/in/rmout.jar'-libraryjars 'D:/eclipse_v34/jdk/jdk1.5.0_11/jre/lib/rt.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/FastInfoset-1.2.7.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/XmlSchema-1.4.5.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/abdera-core-0.4.0-incubating.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/abdera-extensions-json-0.4.0-incubating.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/abdera-extensions-main-0.4.0-incubating.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/abdera-i18n-0.4.0-incubating.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/abdera-parser-0.4.0-incubating.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/activation.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/ant-1.6.5.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/antlr-2.7.7.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/aopalliance-1.0.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/asm-2.2.3.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/aspectjrt.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/aspectjweaver.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/aspriseTIFF.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/axiom-api-1.2.7.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/axiom-impl-1.2.7.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/baseframework.jar'-libraryjars 'D:/workspace/rm/WebRoot/WEB-INF/lib/bcprov-jdk15-1.43.jar' . . .-dontskipnonpubliclibraryclassmembers-target 1.5-dontshrink-dontoptimize-useuniqueclassmembernames-keeppackagenames-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod-keepparameternames-dontpreverify-dontwarn-ignorewarnings-keep class WebRoot.WEB-INFO.lib.*-keep class * extends cn.com.trueway.platform.** { public <methods>;}-keep class * extends org.springframework.orm.hibernate3.support.HibernateDaoSupport { public <methods>;}-keep class **.model.** { public private protected <fields>; public <methods>;}-keep class cn.com.trueway.resourceAllocation.application.domain.* { public private protected <fields>; public <methods>;}-keep class **.service.impl.* { public <methods>;}-keep class cn.com.trueway.platform.** { public private protected <fields>; public <methods>;}-keep class cn.com.trueway.resourceInterface.service.** { public private protected <fields>; public <methods>;}-keep class **.po.* { public private protected <fields>; public <methods>;}-keep class cn.com.trueway.sso.* { public private protected <fields>; public <methods>;}-keep class cn.com.trueway.startup.AdminFilter { public private protected <fields>; public <methods>;}# Keep names - Native method names. Keep all native class/method names.-keepclasseswithmembers,allowshrinking class * { native <methods>;}# Keep names - _class method names. Keep all .class method names. This may be# useful for libraries that will be obfuscated again with different obfuscators.-keepclassmembers,allowshrinking class * { java.lang.Class class$(java.lang.String); java.lang.Class class$(java.lang.String,boolean);}# Remove - System method calls. Remove all invocations of System# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.System { public static long currentTimeMillis(); static java.lang.Class getCallerClass(); public static int identityHashCode(java.lang.Object); public static java.lang.SecurityManager getSecurityManager(); public static java.util.Properties getProperties(); public static java.lang.String getProperty(java.lang.String); public static java.lang.String getenv(java.lang.String); public static java.lang.String mapLibraryName(java.lang.String); public static java.lang.String getProperty(java.lang.String,java.lang.String);}# Remove - Math method calls. Remove all invocations of Math# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.Math { public static double sin(double); public static double cos(double); public static double tan(double); public static double asin(double); public static double acos(double); public static double atan(double); public static double toRadians(double); public static double toDegrees(double); public static double exp(double); public static double log(double); public static double log10(double); public static double sqrt(double); public static double cbrt(double); public static double IEEEremainder(double,double); public static double ceil(double); public static double floor(double); public static double rint(double); public static double atan2(double,double); public static double pow(double,double); public static int round(float); public static long round(double); public static double random(); public static int abs(int); public static long abs(long); public static float abs(float); public static double abs(double); public static int max(int,int); public static long max(long,long); public static float max(float,float); public static double max(double,double); public static int min(int,int); public static long min(long,long); public static float min(float,float); public static double min(double,double); public static double ulp(double); public static float ulp(float); public static double signum(double); public static float signum(float); public static double sinh(double); public static double cosh(double); public static double tanh(double); public static double hypot(double,double); public static double expm1(double); public static double log1p(double);}# Remove - Number method calls. Remove all invocations of Number# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.* extends java.lang.Number { public static java.lang.String toString(byte); public static java.lang.Byte valueOf(byte); public static byte parseByte(java.lang.String); public static byte parseByte(java.lang.String,int); public static java.lang.Byte valueOf(java.lang.String,int); public static java.lang.Byte valueOf(java.lang.String); public static java.lang.Byte decode(java.lang.String); public int compareTo(java.lang.Byte); public static java.lang.String toString(short); public static short parseShort(java.lang.String); public static short parseShort(java.lang.String,int); public static java.lang.Short valueOf(java.lang.String,int); public static java.lang.Short valueOf(java.lang.String); public static java.lang.Short valueOf(short); public static java.lang.Short decode(java.lang.String); public static short reverseBytes(short); public int compareTo(java.lang.Short); public static java.lang.String toString(int,int); public static java.lang.String toHexString(int); public static java.lang.String toOctalString(int); public static java.lang.String toBinaryString(int); public static java.lang.String toString(int); public static int parseInt(java.lang.String,int); public static int parseInt(java.lang.String); public static java.lang.Integer valueOf(java.lang.String,int); public static java.lang.Integer valueOf(java.lang.String); public static java.lang.Integer valueOf(int); public static java.lang.Integer getInteger(java.lang.String); public static java.lang.Integer getInteger(java.lang.String,int); public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer); public static java.lang.Integer decode(java.lang.String); public static int highestOneBit(int); public static int lowestOneBit(int); public static int numberOfLeadingZeros(int); public static int numberOfTrailingZeros(int); public static int bitCount(int); public static int rotateLeft(int,int); public static int rotateRight(int,int); public static int reverse(int); public static int signum(int); public static int reverseBytes(int); public int compareTo(java.lang.Integer); public static java.lang.String toString(long,int); public static java.lang.String toHexString(long); public static java.lang.String toOctalString(long); public static java.lang.String toBinaryString(long); public static java.lang.String toString(long); public static long parseLong(java.lang.String,int); public static long parseLong(java.lang.String); public static java.lang.Long valueOf(java.lang.String,int); public static java.lang.Long valueOf(java.lang.String); public static java.lang.Long valueOf(long); public static java.lang.Long decode(java.lang.String); public static java.lang.Long getLong(java.lang.String); public static java.lang.Long getLong(java.lang.String,long); public static java.lang.Long getLong(java.lang.String,java.lang.Long); public static long highestOneBit(long); public static long lowestOneBit(long); public static int numberOfLeadingZeros(long); public static int numberOfTrailingZeros(long); public static int bitCount(long); public static long rotateLeft(long,int); public static long rotateRight(long,int); public static long reverse(long); public static int signum(long); public static long reverseBytes(long); public int compareTo(java.lang.Long); public static java.lang.String toString(float); public static java.lang.String toHexString(float); public static java.lang.Float valueOf(java.lang.String); public static java.lang.Float valueOf(float); public static float parseFloat(java.lang.String); public static boolean isNaN(float); public static boolean isInfinite(float); public static int floatToIntBits(float); public static int floatToRawIntBits(float); public static float intBitsToFloat(int); public static int compare(float,float); public boolean isNaN(); public boolean isInfinite(); public int compareTo(java.lang.Float); public static java.lang.String toString(double); public static java.lang.String toHexString(double); public static java.lang.Double valueOf(java.lang.String); public static java.lang.Double valueOf(double); public static double parseDouble(java.lang.String); public static boolean isNaN(double); public static boolean isInfinite(double); public static long doubleToLongBits(double); public static long doubleToRawLongBits(double); public static double longBitsToDouble(long); public static int compare(double,double); public boolean isNaN(); public boolean isInfinite(); public int compareTo(java.lang.Double); public <init>(byte); public <init>(short); public <init>(int); public <init>(long); public <init>(float); public <init>(double); public <init>(java.lang.String); public byte byteValue(); public short shortValue(); public int intValue(); public long longValue(); public float floatValue(); public double doubleValue(); public int compareTo(java.lang.Object); public boolean equals(java.lang.Object); public int hashCode(); public java.lang.String toString();}# Remove - String method calls. Remove all invocations of String# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.String { public <init>(); public <init>(byte[]); public <init>(byte[],int); public <init>(byte[],int,int); public <init>(byte[],int,int,int); public <init>(byte[],int,int,java.lang.String); public <init>(byte[],java.lang.String); public <init>(char[]); public <init>(char[],int,int); public <init>(java.lang.String); public <init>(java.lang.StringBuffer); public static java.lang.String copyValueOf(char[]); public static java.lang.String copyValueOf(char[],int,int); public static java.lang.String valueOf(boolean); public static java.lang.String valueOf(char); public static java.lang.String valueOf(char[]); public static java.lang.String valueOf(char[],int,int); public static java.lang.String valueOf(double); public static java.lang.String valueOf(float); public static java.lang.String valueOf(int); public static java.lang.String valueOf(java.lang.Object); public static java.lang.String valueOf(long); public boolean contentEquals(java.lang.StringBuffer); public boolean endsWith(java.lang.String); public boolean equalsIgnoreCase(java.lang.String); public boolean equals(java.lang.Object); public boolean matches(java.lang.String); public boolean regionMatches(boolean,int,java.lang.String,int,int); public boolean regionMatches(int,java.lang.String,int,int); public boolean startsWith(java.lang.String); public boolean startsWith(java.lang.String,int); public byte[] getBytes(); public byte[] getBytes(java.lang.String); public char charAt(int); public char[] toCharArray(); public int compareToIgnoreCase(java.lang.String); public int compareTo(java.lang.Object); public int compareTo(java.lang.String); public int hashCode(); public int indexOf(int); public int indexOf(int,int); public int indexOf(java.lang.String); public int indexOf(java.lang.String,int); public int lastIndexOf(int); public int lastIndexOf(int,int); public int lastIndexOf(java.lang.String); public int lastIndexOf(java.lang.String,int); public int length(); public java.lang.CharSequence subSequence(int,int); public java.lang.String concat(java.lang.String); public java.lang.String replaceAll(java.lang.String,java.lang.String); public java.lang.String replace(char,char); public java.lang.String replaceFirst(java.lang.String,java.lang.String); public java.lang.String[] split(java.lang.String); public java.lang.String[] split(java.lang.String,int); public java.lang.String substring(int); public java.lang.String substring(int,int); public java.lang.String toLowerCase(); public java.lang.String toLowerCase(java.util.Locale); public java.lang.String toString(); public java.lang.String toUpperCase(); public java.lang.String toUpperCase(java.util.Locale); public java.lang.String trim();}# Remove - StringBuffer method calls. Remove all invocations of StringBuffer# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.StringBuffer { public <init>(); public <init>(int); public <init>(java.lang.String); public <init>(java.lang.CharSequence); public java.lang.String toString(); public char charAt(int); public int capacity(); public int codePointAt(int); public int codePointBefore(int); public int indexOf(java.lang.String,int); public int lastIndexOf(java.lang.String); public int lastIndexOf(java.lang.String,int); public int length(); public java.lang.String substring(int); public java.lang.String substring(int,int);}# Remove - StringBuilder method calls. Remove all invocations of StringBuilder# methods without side effects whose return values are not used.-assumenosideeffects public class java.lang.StringBuilder { public <init>(); public <init>(int); public <init>(java.lang.String); public <init>(java.lang.CharSequence); public java.lang.String toString(); public char charAt(int); public int capacity(); public int codePointAt(int); public int codePointBefore(int); public int indexOf(java.lang.String,int); public int lastIndexOf(java.lang.String); public int lastIndexOf(java.lang.String,int); public int length(); public java.lang.String substring(int); public java.lang.String substring(int,int);}


分享给朋友:
您可能感兴趣的文章:
随机阅读: