Android APK代碼混淆與資源混淆詳解,你確定不看?


APK的混淆分為資源混淆與代碼混淆.一般大部分都使用兩者結合.尤其是目前主流的應用.

其中的優點:

  • 防止被惡意破解逆向分析
  • 減少apk體積,也是瘦身的方法
  • 代碼可閱讀性降低

其中的缺點:

  • 調試不方便(可以配置mapping變得方便)
  • 測試不充分,可能導致部分功能不能使用(比如注解相關等)

混淆前(這兒偷個懶直接用工具反編譯看):

這里寫圖片描述

混淆后:

這里寫圖片描述

如何使用代碼混淆:

1.直接在build.gradle文件中配置即可.如圖: 
這里寫圖片描述 
圖片有了,文件也找到了,接下來了呢?

buildTypes {
        debug {
            // 如果沒有提供混淆規則文件,則設置默認的混淆規則文件(SDK/tools/proguard/proguard-android.txt) pseudoLocalesEnabled true // 顯示Log buildConfigField "boolean", "LOG_DEBUG", "true" //混淆 minifyEnabled false //Zipalign優化 zipAlignEnabled true // 移除無用的resource文件 shrinkResources true //加載默認混淆配置文件 proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro' //簽名 signingConfig signingConfigs.debug } release { // 如果沒有提供混淆規則文件,則設置默認的混淆規則文件(SDK/tools/proguard/proguard-android.txt) pseudoLocalesEnabled true // 不顯示Log buildConfigField "boolean", "LOG_DEBUG", "false" //混淆 minifyEnabled true //Zipalign優化 zipAlignEnabled true // 移除無用的resource文件 shrinkResources true //加載默認混淆配置文件 proguardFiles getDefaultProguardFile('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
  • 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
  • 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 *; #} -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 系統類不需要混淆 -keepattributes *Annotation* -keep class * extends java.lang.annotation.Annotation { *; } -keepattributes Signature -keep public class * extends android.app.Fragment -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 * extends android.support.v4.** -keep public class * extends android.support.v7.** -dontwarn com.alipay.android.phone.mrpc.core** -keep class com.alipay.android.phone.mrpc.core.**{*;} -dontwarn com.alipay.apmobilesecuritysdk.face** -keep class com.alipay.apmobilesecuritysdk.face.**{*;} # 百度導航的不需要混淆 #-dontwarn com.baidu.navisdk.comapi.tts.ttsplayer** #-keep class com.baidu.navisdk.**{*;} # Jpush不需要混淆 -dontwarn cn.jpush** -keep class cn.jpush.** { *; }#Jpush # XUtils工具不需要混淆 -dontwarn com.lidroid** -keep class com.lidroid.**{*;}#ViewInject # 自定義控件不需要混淆 -keep class com.cheweishi.android.widget.** {*;}#CustomView -dontwarn com.sinovoice** -keep class com.sinovoice.** { *; } # 百度地圖相關不需要混淆 -dontwarn com.baidu** -keep class com.baidu.** { *; } -keep class vi.com.gdi.bgl.android.**{*;} #-dontwarn demo.Pinyin4jAppletDemo** #-keep class demo.Pinyin4jAppletDemo{*;} # volley工具不需要混淆 -dontwarn com.android.volley.toolbox** -keep class com.android.volley.toolbox{*;} # gson工具不需要混淆 -dontwarn com.google.gson** -keep class com.google.gson.**{*;} #-dontwarn com.nineoldandroids.** #-keep class com.nineoldandroids.**{*;} -dontwarn org.apache.http** -keep class org.apache.http.**{*;} -dontwarn com.handmark.pulltorefresh** -keep class com.handmark.pulltorefresh.**{*;} -dontwarn com.squareup.picasso** -keep class com.squareup.picasso.**{*;} -dontwarn com.cheweishi.android.entity** -keep class com.cheweishi.android.entity.**{*;} -keep class com.cheweishi.android.response.BaseResponse -keep public class com.android.vending.licensing.ILicensingService -printmapping mapping.txt #混淆后文件映射 #-keep public class com.cheweishi.android.R$*{ # public static final int *; #} -keepclasseswithmembernames class * { native <methods>; } -keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * 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
  • 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文件就可以自動刪除並備份了,非常人性化.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM