Android APK代码混淆和资源文件混淆

APK的混淆分为资源混淆与代码混淆.一般大部分都使用两者结合.尤其是目前主流的应用.

其中的优点:

防止被恶意破解逆向分析

减少apk体积,也是瘦身的方法

代码可阅读性降低

其中的缺点:

调试不方便(可以配置mapping变得方便)

测试不充分,可能导致部分功能不能使用(比如注解相关等)

混淆前(这儿偷个懒直接用工具反编译看):

混淆后:

如何使用代码混淆:

1.直接在build.gradle文件中配置即可.如图:

图片有了,文件也找到了,接下来了呢?

buildTypes {

        debug {

// 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)

pseudoLocalesEnabledtrue

// 显示Log

buildConfigField"boolean","LOG_DEBUG","true"

//混淆

minifyEnabledfalse

//Zipalign优化

zipAlignEnabledtrue

// 移除无用的resource文件

shrinkResourcestrue

//加载默认混淆配置文件

proguardFilesgetDefaultProguardFile('proguard-Android.txt'),'proguard-rules.pro'

//签名

            signingConfig signingConfigs.debug

        }

        release {

// 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)

pseudoLocalesEnabledtrue

// 不显示Log

buildConfigField"boolean","LOG_DEBUG","false"

//混淆

minifyEnabledtrue

//Zipalign优化

zipAlignEnabledtrue

// 移除无用的resource文件

shrinkResourcestrue

//加载默认混淆配置文件

proguardFilesgetDefaultProguardFile('proguard-Android.txt'),'proguard-rules.pro'

//签名

            signingConfig signingConfigs.relealse

        }

    }

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

经过这样的配置过后呢,可以发现gradle是加载了一个混淆的配置文件(proguard-Android.txt,这个文件的位置和build.gradle同级),根据混淆配置文件的规则进行混淆的.为什么要混淆配置呢?因为有些东西是不能混淆的,比如jni调用,本身就是根据包名去调用的,如果混淆了就会NotFoundMethod了.所以这个规则就是自定义的了.

如何自定义:

-libraryjars class_path//应用的依赖包,如Android-support-v4 

-keep [,modifier,...] class_specification//这里的keep就是保持的意思,意味着不混淆某些类

-keepclassmembers [,modifier,...] class_specification//同样的保持,不混淆类的成员 

-keepclasseswithmembers [,modifier,...] class_specification//不混淆类及其成员 

-keepnames class_specification//不混淆类及其成员名 

-keepclassmembernames class_specification//不混淆类的成员名 

-keepclasseswithmembernames class_specification//不混淆类及其成员名 

-assumenosideeffects class_specification//假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等 

-dontwarn [class_filter]//不提示warnning

1

2

3

4

5

6

7

8

9

接下来看了语法可能有点蒙了,这些只是了解就可以了,一般有通用的.

比如:

# Add project specific ProGuard rules here.

# By default, the flags in this file are appended to flags specified

# in D:\Android\sdk/tools/proguard/proguard-android.txt

# You can edit the include path and order by changing the proguardFiles

# directive in build.gradle.

#

# For more details, see

#  http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# 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 *;

#}

-optimizationpasses5

-dontusemixedcaseclassnames

-dontskipnonpubliclibraryclasses

-dontpreverify

-verbose

-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

# 系统类不需要混淆

-keepattributes *Annotation*

-keepclass * extends java.lang.annotation.Annotation { *;}

-keepattributesSignature

-keep publicclass * extends android.app.Fragment

-keep publicclass * extends android.app.Activity

-keep publicclass * extends android.app.Application

-keep publicclass * extends android.app.Service

-keep publicclass * extends android.content.BroadcastReceiver

-keep publicclass * extends android.content.ContentProvider

-keep publicclass * extends android.app.backup.BackupAgentHelper

-keep publicclass * extends android.preference.Preference

-keep publicclass * extends android.support.v4.**

-keep publicclass * extends android.support.v7.**

-dontwarn com.alipay.android.phone.mrpc.core**

-keepclass com.alipay.android.phone.mrpc.core.**{*;}

-dontwarn com.alipay.apmobilesecuritysdk.face**

-keepclass com.alipay.apmobilesecuritysdk.face.**{*;}

#  百度导航的不需要混淆

#-dontwarn com.baidu.navisdk.comapi.tts.ttsplayer**

#-keep class com.baidu.navisdk.**{*;}

#  Jpush不需要混淆

-dontwarn cn.jpush**

-keepclass cn.jpush.** { *;}#Jpush

# XUtils工具不需要混淆

-dontwarn com.lidroid**

-keepclass com.lidroid.**{*;}#ViewInject

# 自定义控件不需要混淆

-keepclass com.cheweishi.android.widget.** {*;}#CustomView

-dontwarn com.sinovoice**

-keepclass com.sinovoice.** { *;}

# 百度地图相关不需要混淆

-dontwarn com.baidu**

-keepclass com.baidu.** { *;}

-keepclass vi.com.gdi.bgl.android.**{*;}

#-dontwarn demo.Pinyin4jAppletDemo**

#-keep class demo.Pinyin4jAppletDemo{*;}

# volley工具不需要混淆

-dontwarn com.android.volley.toolbox**

-keepclass com.android.volley.toolbox{*;}

# gson工具不需要混淆

-dontwarn com.google.gson**

-keepclass com.google.gson.**{*;}

#-dontwarn com.nineoldandroids.**

#-keep class com.nineoldandroids.**{*;}

-dontwarn org.apache.http**

-keepclass org.apache.http.**{*;}

-dontwarn com.handmark.pulltorefresh**

-keepclass com.handmark.pulltorefresh.**{*;}

-dontwarn com.squareup.picasso**

-keepclass com.squareup.picasso.**{*;}

-dontwarn com.cheweishi.android.entity**

-keepclass com.cheweishi.android.entity.**{*;}

-keepclass com.cheweishi.android.response.BaseResponse

-keep publicclass com.android.vending.licensing.ILicensingService

-printmapping mapping.txt#混淆后文件映射

#-keep public class com.cheweishi.android.R$*{

#    public static final int *;

#}

-keepclasseswithmembernamesclass * {

    native ;

}

-keepclasseswithmembernamesclass * {

public (android.content.Context, android.util.AttributeSet);

}

-keepclasseswithmembernamesclass * {

public (android.content.Context, android.util.AttributeSet, int);

}

-keepclassmembers enum * {

    public static **[] values();

public static ** valueOf(java.lang.String);

}

-keepclass * implements android.os.Parcelable {

public static final android.os.Parcelable$Creator*;

}

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

当你混淆后你会发现一些错误日志全是a.b.c.d()等,根本不知道具体错误在哪儿,这就是混淆后调试的确定,竟然提供了混淆肯定就可以还原啦,google早就考虑到了.那我要怎么还原呢?

1.cmd进入sdk/tools/proguard/bin目录。

2.将混淆后的日志和上文提到的mapping文件放入此目录中。

3.执行命令:retrace.bat mapping.txt XXX.txt

未还原前:

还原后:

这下有没有觉得比较好调试了,这下你比较关心如何线上的产品如何查看呢?一般(友盟)提供了mapping文件管理的,所以混淆规则的文件(proguard-Android.txt)的生成是非常有必要的.

资源混淆:

资源混淆是可以解决apk瘦身,主要就是压缩了资源文件及修改了文件名字及映射关系.看看效果吧.

资源混淆前:

资源混淆后:

关于资源混淆有很多种解决方案,首先我们可以看看最早美团提出来的(美团资源保护实战,这里就不做具体的分析):

1.首先介绍了打包的过程,是通过appt对资源进行记录.

2.了解原理后,可以通过修改源码在资源文件映射的时候修改文件名字及映射路径

3.美团仅仅是提供了修改的思路,并未将混淆的函数公开

其实通过这样修改aapt,然后再Linux编译出来的aapt(可以编译分为Linux或者windows,以windows为例)替换置SDK目录下/build-tools/aapt.exe,然后使用对应版本编译即可.当然这样的做法虽然可以实现,但是非常麻烦(依赖编译过程,依赖编译源码…),比如aapt升级等

再看看微信开源的git(AndResGuard),大致原理将资源文件通过7zip进行压缩后重新映射然后打包成apk并对其签名.

对比:

如果你还需要对apk瘦身,你可以将编译前无用资源给删除.具体可使用gradle提供的Lint.

如何使用:

然后build后会在projectName\app\build\outputs\lint-results.xml,该Lint可以检测语法以及无用资源,然后写一个工具就可以删除了.这里也可以推荐大家使用:lintAutoCleaner,该工具选择对应的lint-results.xml文件就可以自动删除并备份了,非常人性化.

你可能感兴趣的:(Android APK代码混淆和资源文件混淆)