Android APP代码混淆proguard和加固

2024-02-24 05:32

本文主要是介绍Android APP代码混淆proguard和加固,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

七、第三方加固

大家请百度

这篇关于Android APP代码混淆proguard和加固的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741080

相关文章

利用c++判断水仙花数并输出示例代码

《利用c++判断水仙花数并输出示例代码》水仙花数是指一个三位数,其各位数字的立方和恰好等于该数本身,:本文主要介绍利用c++判断水仙花数并输出的相关资料,文中通过代码介绍的非常详细,需要的朋友可以... 以下是使用C++实现的相同逻辑代码:#include <IOStream>#include <vec

Java 接口定义变量的示例代码

《Java接口定义变量的示例代码》文章介绍了Java接口中的变量和方法,接口中的变量必须是publicstaticfinal的,用于定义常量,而方法默认是publicabstract的,必须由实现类... 在 Java 中,接口是一种抽象类型,用于定义类必须实现的方法。接口可以包含常量和方法,但不能包含实例

使用Redis实现会话管理的示例代码

《使用Redis实现会话管理的示例代码》文章介绍了如何使用Redis实现会话管理,包括会话的创建、读取、更新和删除操作,通过设置会话超时时间并重置,可以确保会话在用户持续活动期间不会过期,此外,展示了... 目录1. 会话管理的基本概念2. 使用Redis实现会话管理2.1 引入依赖2.2 会话管理基本操作

mybatis-plus分表实现案例(附示例代码)

《mybatis-plus分表实现案例(附示例代码)》MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生,:本文主要介绍my... 目录文档说明数据库水平分表思路1. 为什么要水平分表2. 核心设计要点3.基于数据库水平分表注意事项示例

Nginx服务器部署详细代码实例

《Nginx服务器部署详细代码实例》Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,:本文主要介绍Nginx服务器部署的相关资料,文中通过代码... 目录Nginx 服务器SSL/TLS 配置动态脚本反向代理总结Nginx 服务器Nginx是一个‌高性

HTML5的input标签的`type`属性值详解和代码示例

《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param