Android代码混淆方法,Android 代码混淆零基础入门
内容提要
本篇文章主要有三个部分,让读者读完后能自己写规则混淆项目
对Android代码怎么开启混淆做一个简单的介绍。
对混淆规则做一个简单介绍;
在混淆过后Crash日志反推代码工具retrace.bat、可视化反推工具GUI说明。
对混淆的一个简单介绍:
Android SDK 自带了混淆工具Proguard。它位于SDK根目录\tools\proguard下面。如果开启了混淆,Proguard默认情况下会对所有代码,包括第三方包都进行混淆,可是有些代码或者第三方包是不能混淆的,这就需要我们手动编写混淆规则来保持不能被混淆的部分。
混淆有几个作用:
【优化】它能优化java的字节码,使程序运行更快;
【压缩】最直观的就是减少App大小,在混淆过程中它会找出未被使用过的类和类成员并删除他们;
【混淆】这个功能使我们的java代码中的类、函数、变量名随机变成无意义的代号形如:a,b,c...之类的,即使我们的APP即使被反编译,也不容易理解了。
上面这几个功能都是默认打开的,要关闭他们只需配置规则:
-dontshrink :关闭压缩;
-dontoptimize:关闭优化;
-dontobfuscate:关闭混淆。
写在开始之前:
本编使用Android Studio工具作为开发环境,Eclipse类似;
Android Studio新建项目时会在项目根目录下自动生成一个混淆配置文件:
proguard-rules.pro;【Eclipse 下面的文件名为:proguard.cfg或者proguard.txt】里面的内容规则都是一样的;
1.现在开始混淆:
第一步:开启混淆,编辑项目配置文件build.gradle(Module: app)
*** minifyEnabled true;这个选项的意思为开启混淆;
*** proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro';//配置文件**
'proguard-android.txt' 是AndroidStudio默认自动导入的规则,这个文件位于Android SDK根目录\tools\proguard\proguard-android.txt。这里面是一些比较常规的不能被混淆的代码规则。'proguard-rules.pro'是针对我们自己的项目需要特别定义混淆规则,它位于项目根目录下面,里面的内容需要我们自己编写
zipAlignEnabled true 这个在打包时需要设置为true,能优化我们的java字节码,提高运行效率;
build.gradle编辑完成后如下图所示:(表示发布的release包,会按照指定规则来进行混淆)
android {
compileSdkVersion 23
buildToolsVersion "24.0.1"
defaultConfig {
}
buildTypes {
release { //主要看这部分:
zipAlignEnabled true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
....
}
第二步:现在就可以开始编辑自己的规则了
下面是一个比较简单的proguard-rules.pro文件内容,做完这些就可以打包发布版本了
1.png
将混淆过的APK反编译,你会发现里面的代码变成了a、b、c之类的没有意义的代号了,而且APK也变小了。
2.重点来了【规则介绍】
现在对混淆规则做一个介绍:
先来看一看Android studio 默认包含的规则文件(proguard-android.txt 文件)里面的类容,我们选出几个重点说明:
#混淆时不生成大小写混合的类名
-dontusemixedcaseclassnames
#不忽略非公共的类库
-dontskipnonpubliclibraryclasses
#混淆过程中打印详细信息
-verbose
#关闭优化
-dontoptimize
#不预校验
-dontpreverify
# Annotation注释不能混淆
-keepattributes *Annotation*
#对于NDK开发 本地的native方法不能被混淆
-keepclasseswithmembernames class * {
native ;
}
#保持View的子类里面的set、get方法不被混淆(*代替任意字符)
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
#保持Activity子类里面的参数类型为View的方法不被混淆,如被XML里面应用的onClick方法
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#保持枚举类型values()、以及valueOf(java.lang.String)成员不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#保持实现Parcelable接口的类里面的Creator成员不被混淆
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
#保持R类静态成员不被混淆
-keepclassmembers class **.R$* {
public static ;
}
#不警告support包中不使用的引用
-dontwarn android.support.**
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
#保持使用了Keep注解的方法以及类不被混淆
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
#保持使用了Keep注解的成员域以及类不被混淆
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep (...);
}
上面默认的规则中指示了些需要保持不能别混淆的代码,包括:
继承至Android组件(Activity, Service...)的类。
自定义控件,继承至View的类(被xml文件引用到的,名字已经固定了的)
enum 枚举
实现了 android.os.Parcelable 接口的
Android R文件
数据库驱动...
Android support 包等
Android 的注释不能混淆
-keepattributes *Annotation*
对于NDK开发 本地的native方法不能被混淆
-keepclasseswithmembernames class * { native ; }
对于特定的项目还有很多不能被混淆的,需要我们自己写规则来指示,将在下面来说明:
对一些符号做一些说明
现在来看一下需要我们自己编写的proguard-rules.pro:
#压缩级别0-7,Android一般为5(对代码迭代优化的次数)
-optimizationpasses 5
#不使用大小写混合类名
-dontusemixedcaseclassnames
#混淆时记录日志
-verbose
#不警告org.greenrobot.greendao.database包及其子包里面未应用的应用
-dontwarn org.greenrobot.greendao.database.**
-dontwarn rx.**
-dontwarn org.codehaus.jackson.**
......
#保持jackson包以及其子包的类和类成员不被混淆
-keep class org.codehaus.jackson.** {*;}
#--------重要说明-------
#-keep class 类名 {*;}
#-keepclassmembers class 类名{*;}
#一个*表示保持了该包下的类名不被混淆;
# -keep class org.codehaus.jackson.*
#二个**表示保持该包以及它包含的所有子包下的类名不被混淆
# -keep class org.codehaus.jackson.**
#------------------------
#保持类名、类里面的方法和变量不被混淆
-keep class org.codehaus.jackson.** {*;}
#不混淆类ClassTwoOne的类名以及类里面的public成员和方法
#public 可以换成其他java属性如private、public static 、final等
#还可以使表示构造方法、表示方法、表示成员,
#这些前面也可以加public等java属性限定
-keep class com.dev.demo.two.ClassTwoOne {
public *;
}
#不混淆类名,以及里面的构造函数
-keep class com.dev.demo.ClassOne {
public ();
}
#不混淆类名,以及参数为int 的构造函数
-keep class com.dev.demo.two.ClassTwoTwo {
public (int);
}
#不混淆类的public修饰的方法,和private修饰的变量
-keepclassmembers class com.dev.demo.two.ClassTwoThree {
public ;
private ;
}
#不混淆内部类,需要用$修饰
#不混淆内部类ClassTwoTwoInner以及里面的全部成员
-keep class com.dev.demo.two.ClassTwoTwo$ClassTwoTwoInner{*;}
......
对一些规则的解释:
-keepattributes {name} 保护给定的属性不被混淆,
如:-keepattributes *Annotation*
-dontwarn {name} 不要警告指定库中找不到的引用。混淆在默认情况下会检查每个库的引用是否正确,但是有些第三方库里面会有用不到的类,有些没有正确引用,所以需要对第三方库取消警告 否则会报错,而且有可能混淆时间会很长。
如:-dontwarn org.codehaus.jackson.**
-keep {Modifier} {class_specification} 保留指定的类名、类成员不被混淆
-keepclassmembers {modifier} {class_specification} 保留指定的类成员不被混淆
-keepclasseswithmembers {class_specification} 保留指定的类名、类成员不被混淆
-keepnames {class_specification} 保留指定的类名、类成员的名称不被混淆
-keepclasseswithmembernames {class_specification} 保留指定的类名、类成员名称不被混淆(如果存在的话)
3.混淆后根据Crash崩溃日志反推代码
成功打包后会在目录*** app\build\outputs\mapping\release ***下生成几个文件:
2.png
说明:
dump.txt 混淆后类的内部结构说明;
mapping.txt 混淆前与混淆后名称对应关系;
seeds.txt 经过了一系列keep语句的保持,没有被混淆的类,成员的名称列表文件。
usage.txt 经过压缩后被删除的没有使用的代码,方法...等的名称的列表文件
retrace工具:
混淆反推工具为retrace.sh(Mac平台)或者retrace.bat(Windows平台)
该工具在sdk根目录\tools\proguard\bin\retrace.sh
(Windows平台类似);
命令格式:
*** ./retrace.sh [mapping.txt目录] [崩溃日历目录]
(Windows平台:retrace.bat [mapping.txt目录] [崩溃日历目录]) ***
第一步:保存Crash日志如下:截取日志保存为txt文件如:bug.txt。
03-21 03:09:32.389: E/AndroidRuntime(3582): FATAL EXCEPTION: main
03-21 03:09:32.389: E/AndroidRuntime(3582): Process: com.dev.demo, PID: 3582
03-21 03:09:32.389: E/AndroidRuntime(3582): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
03-21 03:09:32.389: E/AndroidRuntime(3582): at com.dev.demo.two.b.b(Unknown Source)
03-21 03:09:32.389: E/AndroidRuntime(3582): at com.dev.demo.a.a.printTest(Unknown Source)
03-21 03:09:32.389: E/AndroidRuntime(3582): at com.dev.demo.MainActivity.i(Unknown Source)
03-21 03:09:32.389: E/AndroidRuntime(3582): at com.dev.demo.MainActivity.a(Unknown Source)
03-21 03:09:32.389: E/AndroidRuntime(3582): at com.dev.demo.MainActivity$1.onClick(Unknown Source)
第二步:删掉Crash日志中03-21 03:09:32.389: E/AndroidRuntime(3582):部分,否则无法反推还原。删除后如下:
FATAL EXCEPTION: main
Process: com.dev.demo, PID: 3582
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at com.dev.demo.two.b.b(Unknown Source)
at com.dev.demo.a.a.printTest(Unknown Source)
at com.dev.demo.MainActivity.i(Unknown Source)
at com.dev.demo.MainActivity.a(Unknown Source)
at com.dev.demo.MainActivity$1.onClick(Unknown Source)
第三步:打开命令窗口输入命令:如:*** ./retrace.sh mapping.txt bug.txt ***
如下:
3.png
按确认后得到结果如下:
FATAL EXCEPTION: main
Process: com.dev.demo, PID: 3582
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at com.dev.demo.two.ClassTwoThree.void test()(Unknown Source)
at com.dev.demo.one.ClassOneOne.void printTest()(Unknown Source)
at com.dev.demo.MainActivity.void printWifi()(Unknown Source)
at com.dev.demo.MainActivity.void access$000(com.dev.demo.MainActivity)(Unknown Source)
at com.dev.demo.MainActivity$1.void onClick(android.view.View)(Unknown Source) ```
除了有retrace.sh工具外还有可视化工具,和retrace.sh同目录下proguardgui.sh,这是一块Progurad的可视化工具:
(Windows平台类似)
![4.png](http://upload-images.jianshu.io/upload_images/3589324-f0d492d9da432138.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>有时为了Crash日志更容易定位可以在规则里面添加:
-keepattributes SourceFile, LineNumberTable
**这样Crash日志里面就能保留类名称 和行号了**
**好了,所有终于完了,希望能帮助到你!谢谢!**
***
Android代码混淆方法,Android 代码混淆零基础入门相关推荐
- python代码大全和用法用量_python零基础入门命令方式汇总大全,快速恶补你的Python基础...
原标题:python零基础入门命令方式汇总大全,快速恶补你的Python基础 无意中浏览到这篇来自大牛的分享,总结的很全面,我重新排版下放在这里,希望能帮助到大家.在此十分感谢原作者! 在开始之前还是 ...
- 《C#零基础入门之百识百例》(九十一)预处理器指令 -- 代码示例
C#零基础入门 预处理器指令 -- 代码示例 前言 一,预处理器指令 1.1 概念 1.2 常用预处理指令 1.3 语法规则 二,声明指令 2.1 声明指令概念 2.2 代码示例 三,条件编译指令 3 ...
- 零基础入门深度学习 | 第二章:线性单元和梯度下降
北京 | 高性能计算之GPU CUDA课程11月24-26日3天密集学习 快速带你晋级阅读全文> 无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作 ...
- 零基础入门深度学习(2) - 线性单元和梯度下降
python深度学习大全 原文地址:https://www.zybuluo.com/hanbingtao/note/448086 往期回顾 在上一篇文章中,我们已经学会了编写一个简单的感知器,并用它来 ...
- android 自动补全方法,Android零基础入门|自动完成文本框AutoCompleteTextView
原标题:Android零基础入门|自动完成文本框AutoCompleteTextView 上一期学习的Spinner的使用,掌握的怎么样?本期一起来学习AutoCompleteTextView的使用. ...
- android生命周期方法,Android零基础入门|Activity状态和生命周期方法
原标题:Android零基础入门|Activity状态和生命周期方法 前面两期我们学习了Activity的创建和注册.以及启动和关闭,也学会了重写onCraete方法,这些知识在实际开发中远远不够,还 ...
- 基于hadoop的商品推荐系统_[零基础入门推荐系统(1)]基于用户和基于物品的协同过滤方法(python代码实现)...
1. 前言: 为什么会有该系列? 最近,打算写<零基础入门推荐系统>系列,为了系统地介绍推荐系统知识,以及加强基础的实践能力. 该系列将结合一些书籍,比如项亮的<推荐系统实践> ...
- Android Studio新手–下载安装配置–零基础入门–基本使用–调试技能–构建项目基础–使用AS应对常规应用开发
转自:http://blog.csdn.net/yanbober/article/details/45306483 目标:Android Studio新手–>下载安装配置–>零基础入门–& ...
- android 表格控件点击事件,Android零基础入门|RecyclerView点击事件处理
原标题:Android零基础入门|RecyclerView点击事件处理 前面两期学习了RecyclerView的简单使用,并为其item添加了分割线.在实际运用中,无论是List还是Grid效果,基本 ...
- android arrayadapter自定义,Android零基础入门|自定义ArrayAdapter
原标题:Android零基础入门|自定义ArrayAdapter ListView用起来还是比较简单的,也是Android应用程序中最重要的一个组件,但其他ListView可以随你所愿,能够完成很多想 ...
最新文章
- QT中Widget去除系统提供工具以及系统默认边框
- 【VS开发】模态对话框和非模态对话框
- Error: Could not find or load main class org.apache.tez.dag.app.DAGAppMaster
- 【渝粤题库】国家开放大学2021春2096经济法学题目
- Web程序中将Cell华表的修改 保存到数据库或服务器端文件夹内
- AWT_Swing_初始化(Java)
- warning: initialization from incompatible pointer type error, forbidden解决
- 关于vue项目的文件组织
- 实现一个定时任务管理器
- 微信 android应用签名生成工具,GitHub - feinoah/WeChatSignature: 改进版本的微信应用签名生成工具,再也不用输入包名了!...
- 外卖优惠券cps系统每日领团饿了么外卖券CPS系统公众号小程序源码
- 浅谈大数据平台架构设计
- 【C++】栈的应用:逆波兰式的实现
- SQL 中国人--ZGR
- 张欲莎-老公,不要停。。。
- 达摩院用128张GPU烧出“中文版GPT-3”,我试了下,这文风不是开往幼儿园的车…...
- Vue+TS+子组件回调父组件的方法
- 【PyTorch教程】制作数据集的标签(label)
- 中国纺织服装企业有哪些 纺织服装企业查询
- 智力题(每日更新-转载记录niuke网)
热门文章
- List和Set以及Map的选用
- 数据结构实验之栈七:出栈序列判定
- ubuntu下动态链接库的编译和使用实例
- 130 秒揭秘 EDAS 3.0 如何平滑应对突发流量高峰,为您的业务保驾护航
- Apache Cassandra 在 Facebook 的应用
- 手把手教程:用Python开发一个自然语言处理模型,并用Flask进行部署
- 企业如何采用机器学习
- 华为云云原生首次在太空验证,提升“天算星座“卫星计算精度
- 观测云品牌正式亮相,携手通信院共推国内可观测性概念与技术发展!
- 重塑APM标杆,博睿数据战略升级助力企业数字化转型