Android 混淆机制详解
前言
混淆是增加逆向工程和破解的难度,防止App知识产权被窃取的一个有力手段,高级的代码混淆甚至可以有效地保护存储在客户端的密钥,同时混淆也有很多要注意的地方。
从广义上讲,Android 中的混淆包括三种类型
- java 代码的混淆
- Native (C & C++) 代码的混淆
- 资源文件的混淆
java 代码的混淆
java 代码的混淆在Android 中是最为常见的一种混淆方式,一般依赖于Proguard
或者 DexGuard
工具,其中Progurad 是免费且开源的,DexGuard 是付费的。
Proguard 的特性
在Android 中使用 Proguard
,它不仅仅为我们提供代码混淆的功能,事实上Proguard
主要提供了4个功能特性
- 压缩:java源代码通常被编译为字节码,虽然字节码比源代码更简洁,但它本身依然会包含很多无用的代码,Proguard 的压缩功能通过分析字节码,能够检测并移除没有使用到的类,字段,方法和属性。
- 优化:优化Java 字节码,同时移除没有使用到的指令。
- 混淆:使用无意义的简短字母组合对类名,字段名、和方法名进行重命名。
- 预检验:对上述处理后的代码进行预检验(Android 不需要此项)
buildTypes {release {minifyEnabled true //true 表示进行Proguard 混淆proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}
其中,proguard-android.txt
是 Proguard 默认的混淆配置文件,位于Androdi SDK 的 tools/proguard 目录中,该文件是对Proguard 基本的配置,几乎是每个App 都要用到的配置,当然这个默认文件的配置是远远不够的。我们需要自身App 的特殊性增加或者减少相关的配置。
proguard-rules.pro 文件的编写
混淆文件的规则可以大致分为三种类型:
公共的混淆规则:每个App 都通用的,主要是对Proguard 的基本配置,以及Android SDK 中 API 设置的规则,例如Avtivity 、Parcelable 等。
App 特有的混淆规则:根据App自身的特点进行设置,例如某些类会被反射调用,如果被混淆,那么反射就找不到了。
- 第三方函数库或者SDK 的混淆规则:如果App 引入了第三方开源库或者SDK ,那么需要查看这些函数库或者SDK 的使用说明,将需要去混淆的地方加上去。
下面是一个比较完整的 proguard-rules.pro
文件的内容
#代码混淆的压缩比例,取值范围在0-7之间,默认为5
-optimizationpasses 5
#混淆时不使用大小写混合的方式,这样混淆后都是小写字母的组合
-dontusemixedcaseclassnames
#混淆时不做预校验,在Android 中一般不需要预校验,这样可以加快混淆的速度
-dontpreverify
#混淆时记录日志,同时会生成映射文件,
#Android Studio 中,生成的默认映射文件是
‘build/outputs/mapping/release/mapping.txt’
-verbose
#指定生成的映射文件的路劲和名称(生成原类名和混淆后的类名的映射文件)
-printmapping proguardMapping.txt
#指定混淆是采用的算法 ,参数是Google 官方推荐的过滤器算法
-optimizations !code/simplification/cast,!field/*,!class/merging/*
#如果项目中使用到注解,需要保护注解属性
-keepattributes *Annotation*
#不混淆泛型
-keepattributes Signature
#保留代码行号,这在混淆后代码运行中抛出异常信息时,有利于定位出错的代码
-keepattributes SourceFile,LineNumberTable
#保持 Android SDK 相关API 类不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * extends android.app.Fragment
-keep public class * extends android.view.View
#如果引用了v4或者v7包
-keep class android.support.** {*;}
#保持 native 方法不被混淆
-keepclasseswithmembernames class * { native <methods>;
}
#保留R类
-keep class **.R$* { *;
}
#保持自定义控件类不被混淆
-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);
}
#保持自定义控件不被混淆
-keep public class * extends android.view.View{*** get*();void set*(***);public <init>(android.content.Context);public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);
}
#保持 Activity 中参数是View 类型的函数,
#保证在 layout XML 文件中配置的 onClick 属性的值能够正常调用到
-keepclassmembers class * extends android.app.Activity{public void *(android.view.View);
}
#保持枚举 enum类不被混淆 如果混淆报错,
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 序列化类相关方法和字段不被混淆
-keepclassmembers class * implements java.io.Serializable {static final long serialVersionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectInputStream);java.lang.Object writeReplace();java.lang.Object readResolve();
}
#对于待有回调函数 onXXEvent 的,不能被混淆
-keepclassmembers class * { void *(**On*Event);
}
1.保留实体类和成员不被混淆
对于实体类,要保留它们的set
和get
方法,对于boolean 型的get 方法,有人喜欢命名为isXXX
的方式,所以不要遗漏了。
这是保留一个类和其成员不被混淆
一种好的做法是把所有实体都放在一个包下进行管理,这样只写一次混淆就够了(如下)。避免以后在别的包中新增的实体而忘记保留,代码在混淆后因为找不到相应的实体类而崩溃。
Android 混淆机制详解相关推荐
- Android学习笔记——Android 签名机制详解
Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...
- 【Android签名机制详解】二:Android V1、V2、V3、V4签名方案
前言 书接上回[Android签名机制详解]一:密码学入门,在了解了消息摘要.非对称加密.数字签名.数字证书的基本概念后,我们趁热打铁.直奔主题,讲解签名在Android中的实际应用. 基础知识 An ...
- Android Intent机制详解
什么是Intent Intent 是一个将要执行的动作的抽象描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯.比如说调用startActivity()来启动一 ...
- Android 消息机制详解(Android P)
前言 Android 消息机制,一直都是 Android 应用框架层非常重要的一部分,想更加优雅的进行 Android 开发,我想了解消息机制是非常必要的一个过程,此前也分析过很多次 Handler ...
- Android事件机制详解
转自:http://www.codeceo.com/article/android-event.html 1概述 在Android平台上,主要用到两种通信机制,即Binder机制和事件机制,前者用于跨 ...
- Android 广播机制详解
一.广播的简介 首先,当我们一听到广播这个词时.就可以想到小学是教室的广播.不错Android中的广播机制与我们生活中的广播是有异曲同工之妙的.Android中的发送广播也就像广播室播广播,可以让很多 ...
- Android消息机制详解
*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 Android消息机制 这一定是一个被写烂了的专题吧.那本媛也来凑一个热闹吧.哈哈 这篇博客将会涉及以下内容: 消息机制概述 UM ...
- Android运行机制详解
Android应用程序是用Java语言写的,通过aapt工具把应用程序所需要的任何数据.资源文件打包成apk文件,这个文件是一个将应用安装到手机上的一个载体. 每个android应用程序存在于不同的世 ...
- (转)Android IPC机制详解
o IBinder接口 IBinder接口是对跨进程的对象的抽象.普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口.IBinder接口可以指向本地对象,也可以指 ...
最新文章
- Ext.ux.form.SearchField使用方法
- DVWA安装——一个菜鸟的入门教程
- 捉虫记 C++转java Java中equals和==的区别
- OSChina 周六乱弹 —— 买楼出一块钱,你们出么?
- java ipv6校验_java - IPv6地址验证和规范化[关闭] - 堆栈内存溢出
- 【多线程基础】- 多个线程顺序打印ABC
- Ajax — 大事件项目(第三天)
- 解决idea 中web项目无法正常显示的问题
- scrapy ip地址 tcp time out_TCP的运作流程(一)——“三次握手”
- CSS z-index属性
- Linux C语言在用户态实现一个低时延通知(eventfd)+轮询(无锁队列ring)机制的消息队列
- channelinactive触发后不关闭channel_golang chan 最详细原理剖析,全面源码分析!看完不可能不懂的!...
- 鸿蒙形容欣欣向荣发展,形容发展迅速的12个成语
- 【将金令】炒白银,切忌!切忌!
- tortoisegit 小乌龟的使用
- ReadHub源码阅读笔记(一)
- NCB:神经元线粒体应激记忆可通过mtDNA水平升高跨代遗传
- 求解立方根 java
- 2020到2021计算机试题,2020广东计算机一级考试试题和答案【2021年整理】-20210715002405.docx-原创力文档...
- 图像处理函数详解——imadjust