Android 混淆配置

Android 混淆的一些记录

前言

对Android上混淆的一些记录

混淆的作用

混淆会将 app 源码的类和变量变成 a.b 这种无意义的代号,一方面可以减少app 体积,另一方便可以一定程度上保护app不会被恶意修改以及窃取源码

如何开启混淆

build.gradle中 使用 minifyEnabled 将其设置成 true 就可以开启混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

android {

buildTypes {
release {
// 添加此行代码,可以在release包下打印log,上线的时候一定要改成false
debuggable false
// 打开混淆
minifyEnabled true
// Zipalign优化
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
// 前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,
// 后一个文件是自己的定义混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

默认中有两个 混淆文件 proguard-android.txtproguard-rules.pro, 后一个就在工程中,前一个其实是在sdk 下,完整的路基在 /Users/jhy/Library/Android/sdk/tools/proguard/proguard-android.txt,这个是我电脑下的路劲

混淆规则

有时候,debug 的程序没问题,但是release 混淆过后就出问题了,原因就是因为,我们把一些本不该混淆的类或者方法混淆了,导致程序找不到类或者方法,混淆规则,就是告知程序哪些类或者方法不需要混淆,android 上使用的混淆工具是 ProGuard,android sdk 很贴心的已经帮助我们集成了 ProGuard

官网的说明介绍:ProGuard是最流行的Java字节码优化器。它使Java和Android应用程序的体积缩小了90%,速度提高了20%。ProGuard还通过混淆类,字段和方法的名称,为逆向工程提供了最小的保护。

这个博客已经说得很不错了Android 代码混淆规则

混淆模板

下面是默认的一些

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

#===================================================================================================
# 对于一些基本指令的添加
#===================================================================================================

# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5

# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames

# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses

# 这句话能够使我们的项目混淆后产生映射文件
# 包含有类名->混淆后类名的映射关系
-verbose

# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers

# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify

# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses

# 避免混淆泛型
-keepattributes Signature

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable

# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*


#===================================================================================================
# Android开发中一些需要保留的公共部分
#===================================================================================================

# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService


# 保留AndroidX 下面的类
-keep class com.google.android.material.** {;}
-keep class androidx.** {;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**

# 保留support下的所有类及其内部类
-keep class android.support.** {*;}

# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

# 保留R下面的资源
-keep class **.R$* {*;}

# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}

# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}

# 保留枚举类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

# 保留我们自定义控件(继承自View)不被混淆
-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);
}

# 保留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;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
void *(**On*Event);
void *(**On*Listener);
}

# webView处理,项目中没有使用到webView忽略即可
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-keepclassmembers class * extends android.webkit.webViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.webViewClient {
public void *(android.webkit.webView, jav.lang.String);
}
-keepclassmembers class com.lieyunwang.finance.activity.InfoNewDetailActivity.InJavaScriptLocalObj{
public *;
}
-keepattributes *JavascriptInterface*

-keepclassmembers class * {
public <init> (org.json.JSONObject);
}

-keep public class com.xxx.xxx.R$*{
public static final int *;
}


# Tablayout反射修改下划线宽度导致的tabtrip空指针问题 - 需要可打开
#-keep class android.support.design.widget.TabLayout{*;}

#(可选)避免Log打印输出
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
public static *** w(...);
}

自定义混淆文件

build.gradle使用 consumerProguardFiles 可以自定义混淆文件,在原来的 proguard-rules.pro 同级目录下,加入.pro结尾的文件即可

1
2
3
4
5
6
7
8
9
10
11
12
android {
buildTypes {
release {
consumerProguardFiles file('.').listFiles(new FilenameFilter() {
@Override
boolean accept(File file, String s) {
return s.endsWith('.pro')
}
})
}
}
}

参考

Android安全攻防战,反编译与混淆技术完全解析(下)