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

相关文章

Java中有什么工具可以进行代码反编译详解

《Java中有什么工具可以进行代码反编译详解》:本文主要介绍Java中有什么工具可以进行代码反编译的相关资,料,包括JD-GUI、CFR、Procyon、Fernflower、Javap、Byte... 目录1.JD-GUI2.CFR3.Procyon Decompiler4.Fernflower5.Jav

javaScript在表单提交时获取表单数据的示例代码

《javaScript在表单提交时获取表单数据的示例代码》本文介绍了五种在JavaScript中获取表单数据的方法:使用FormData对象、手动提取表单数据、使用querySelector获取单个字... 方法 1:使用 FormData 对象FormData 是一个方便的内置对象,用于获取表单中的键值

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干