您的位置:首页 > 移动开发 > Android开发

Android APP代码混淆proguard和加固

2016-06-30 18:30 423 查看
Android APP代码混淆proguard和加固

    proguard官方网址:http://proguard.sourceforge.net/index.html#/manual/examples.html

 一、在gradle中开启:

Gradle项目(以及Android Studio)

在build.gradle中进行配置

android {

    buildTypes {

        release {  

           minifyEnabled true

            proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

            //proguardFile 'some-other-rules.txt'  配置单个文件这样

        }

    }

}

如上面代码所示,我们可以使用rminifyEnabled true开启,并且对其配置混淆配置,可以配置多个文件或单个文件。

android的sdk中已经为我们提供了两个默认的配置文件,我们可以拿过来进行使用,proguard-android.txt和proguard-android-optimize.txt。

二、proguard主要三部分功能

   缩减代码、优化代码、混淆代码。三部分功能都可以在配置文件里配置不启用此功能(其实还有预校验的功能不过android官方不建议开启)。

#Shrink Options

#不缩减代码

-dontshrink

#Optimization Options

#不优化代码

-dontoptimize

 

#Obfuscate Options 

#-不混淆输入的类文件 

-dontobfuscate 

 

 

三、用法

1.保留选项(配置不进行处理的内容)

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

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

-keepclasseswithmembers {class_specification} 保护指定的类和类的成员。

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

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

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

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

-keep用法区别

1)保留某个类名不被混淆

-keep public classcom.ebt.app.common.bean.Customer

2)保留类及其所有成员不被混淆

-keep public classcom.ebt.app.common.bean.Customer { *;}

或者

-keepclasseswithmembers class com.ebt.app.common.bean.Customer {

    <init>;#匹配所有构造函数

    <fields>;#匹配所有成员

    <methods>;#匹配所有方法

}

3)只保留类名及其部分成员不被混淆

-keep public classcom.ebt.app.common.bean.Customer { 

    static final<fields>;

    private void get*();

}

4)#保留包路径下所有的类及其属性和方法

-keep class com.ebt.app.sync.** { *;}

2.压缩

-dontshrink 不压缩输入的类文件

-printusage {filename}

-whyareyoukeeping {class_specification}

3.优化

-dontoptimize 不优化输入的类文件

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

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

4.混淆

-dontobfuscate 不混淆输入的类文件

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

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

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

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

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

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

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

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

后面的文件名,类名,或者包名等可以使用占位符代替

?表示一个字符

可以匹配多个字符,但是如果是一个类,不会匹配其前面的包名

* 可以匹配多个字符,会匹配前面的包名。

在android中在android Manifest文件中的activity,service,provider, receviter,等都不能进行混淆。一些在xml中配置的view也不能进行混淆,android提供的默认配置中都有。

5..缺省情况下,proguard 会混淆所有代码,但是下面几种情况不能改变类名和方法名。

a.我们用到反射的地方。

b.我们代码依赖于系统的接口,比如被系统代码调用的回调方法,这种情况最复杂。

c.在配置文件manifest中配置的。

6.对出现问题的类的处理。遇见一个及添加。

7.常见*的用法区别(一般情况下用不到,非必须了解)

修饰类、接口、枚举等时

*       matchesany part of a class name not containing the package separator. For example,"mypackage.*Test*" matches "mypackage.Test" and"mypackage.YourTestApplication", but not"mypackage.mysubpackage.MyTest". Or, more generally, "mypackage.*"matches all
classes in "mypackage", but not in its subpackages.

**     matchesany part of a class name, possibly containing any number of package separators.For example, "**.Test" matches all Test classes in all packagesexcept the root package. Or, "mypackage.**" matches all classes in"mypackage" and in its subpackages.

   修饰构造函数、成员变量、方法

Fields and methods are specified much likein Java, except that method argument lists don't contain argument names (justlike in other tools like javadoc and javap). The specifications can alsocontain the following catch-all wildcards:

<init>        matches any constructor.

<fields>    matches any field.

<methods>       matches any method.

*       matchesany field or method.

Note that the above wildcards don't havereturn types. Only the <init> wildcard has an argument list.

Fields and methods may also be specifiedusing regular expressions. Names can contain the following wildcards:

?       matchesany single character in a method name.

*       matchesany part of a method name.

Types in descriptors can contain thefollowing wildcards:

%      matchesany primitive type ("boolean", "int", etc, but not"void").

?       matchesany single character in a class name.

*       matchesany part of a class name not containing the package separator.

**     matchesany part of a class name, possibly containing any number of package separators.

***  matchesany type (primitive or non-primitive, array or non-array).

...     matchesany number of arguments of any type.

Note that the ?, *, and ** wildcards willnever match primitive types. Furthermore, only the *** wildcards will matcharray types of any dimension. For example, "** get*()" matches"java.lang.Object getObject()", but not "float getFloat()",nor "java.lang.Object[]
getObjects()".

Constructors can also be specified usingtheir short class names (without package) or using their full class names. Asin the Java language, the constructor specification has an argument list, butno return type.

The class access modifiers and class memberaccess modifiers are typically used to restrict wildcarded classes and classmembers. They specify that the corresponding access flags have to be set forthe member to match. A preceding ! specifies that the corresponding
access flagshould be unset.

Combining multiple flags is allowed (e.g.public static). It means that both access flags have to be set (e.g. public andstatic), except when they are conflicting, in which case at least one of themhas to be set (e.g. at least public or protected).

ProGuard supports the additional modifierssynthetic, bridge, and varargs, which may be set by compilers.

四、Proguard的输出文件及reTrace跟踪

 混淆之后,会给我们输出一些文件,在gradle方式下是在<project_dir>/build/proguard/目录下,ant是在<project_dir>/bin/proguard目录,eclipse构建在<project_dir>/proguard目录像。

分别有以下文件:

+ dump.txt 描述apk文件中所有类文件间的内部结构。

+ mapping.txt 列出了原始的类,方法,和字段名与混淆后代码之间的映射。

+ seeds.txt 列出了未被混淆的类和成员

+ usage.txt 列出了从apk中删除的代码

当我们发布的release版本的程序出现bug时,可以通过以上文件(特别时mapping.txt)文件找到错误原始的位置,进行bug修改。同时,可能一开始的proguard配置有错误,也可以通过错误日志,根据这些文件,找到哪些文件不应该混淆,从而修改proguard的配置。

    注意:重新release编译后,这些文件会被覆盖,所以没吃发布程序,最好都保存一份配置文件。

调试Proguard混淆后的程序

上面说了输出的几个文件,我们在改bug时可以使用,通过mapping.txt,通过映射关系找到对应的类,方法,字段等。

ProGuard 提供了命令行和 GUI 工具来还原混淆后的代码,可以将一个被混淆过的堆栈跟踪信息还原成一个可读的信息。

该工具位于  <android-sdk>/tools/proguard/bin/ 目录下。

里面的 proguardgui.bat 为 GUI 工具,

1) 运行 proguardgui.bat

2) 从左边的菜单选择  “ReTrace”

3) 在上面的 mapping 文件中选择你的 mapping 文件 ,在下面输入框输入要还原的代码

4) 点击 “ReTrace!” 按钮

命令行:window下时retrace.bat,linux和mac是retrace.sh,在<sdk_root>/tools/proguard/文件夹下。语法为:

    retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

例如:

retrace.bat -verbose mapping.txt obfuscated_trace.txt

如果你没有指定<stacktrace_file>,retrace工具会从标准输入读取。

   

五、其他关于Proguard的问题

1.开启optimization导致的问题。有时候为了在release版本中去除log打印,配置

-assumenosideeffects class android.util.Log {

public static boolean isLoggable(java.lang.String, int);

public static int v(...);

public static int i(...);

public static int w(...);

public static int d(...);

public static int e(...);

}

此时必须开启优化,但是这样可能会引入更大的问题:http://www.itnose.net/detail/6043297.html而在我的项目中则打包都成功不了,提示说Tencent微博SDK引用的httpclient出问题,找不到父类。结论是:要是你不是proguard高手,就关闭优化吧。

2proguarnd后反编译代码,使用一些工具还能看到真身的影子,如:http://www.tuicool.com/articles/vUB3EnM
-keepattributes SourceFile,LineNumberTable

表示的是java文件的各种文件属性,如果这个被keep了,果断去掉。

3.中文的各个参数的解释,准确性本人不能把握http://www.2cto.com/kf/201604/497739.html

六、美团Android资源混淆保护实践

 网址:http://tech.meituan.com/mt-android-resource-obfuscation.html

七、第三方加固

大家请百度
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息