安卓 代碼混淆

下面我們將分別介紹代碼混淆資源文件混淆具體實踐。
- 代碼混淆-Progurd
下面來總結以下混淆代碼的步驟:
  1. 在android studio的android項目中找到module的gradle配置文件,添加proguard配置
buildTypes { debug { buildConfigField "boolean", "LOG_DEBUG", "true" minifyEnabled false zipAlignEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug } release { buildConfigField "boolean", "LOG_DEBUG", "false" minifyEnabled true zipAlignEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.relealse } }
  1. 找到項目中的proguard-rules.pro文件,該文件就是我們的混淆配置文件
3.編寫proguard-rules.pro文件,添加混淆配置
(1)proguard混淆語法
-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
(2)混淆原則
jni方法不可混淆反射用到的類不混淆(否則反射可能出現問題)AndroidMainfest中的類不混淆,四大組件和Application的子類和Framework層下所有的類默認不會進行混淆Parcelable的子類和Creator靜態成員變量不混淆,否則會產生android.os.BadParcelableException異常使用GSON、fastjson等框架時,所寫的JSON對象類不混淆,否則無法將JSON解析成對應的對象使用第三方開源庫或者引用其他第三方的SDK包時,需要在混淆文件中加入對應的混淆規則有用到WEBView的JS調用也需要保證寫的接口方法不混淆
(3)第三方庫的混淆原則
一般的第三方庫都有自身的混淆方案,可直接引用其自身的混淆配置即可若無混淆配置,一般的可配置不混淆第三方庫
(4)最後帖上我們項目中實際的混淆方案
# Glide圖片庫的混淆處理-keep public class * implements com.bumptech.glide.module.GlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *;}-optimizationpasses 5-dontusemixedcaseclassnames-dontskipnonpubliclibraryclasses-dontpreverify-verbose-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*# 高德地圖混淆腳本-keep class com.android.support.**{ *; }-keep interface android.support.v4.app.**{ *; }-keep public class * extends android.support.v4.**-keep public class * extends android.app.Fragment-dontwarn com.amap.api.**-dontwarn com.a.a.**-dontwarn com.autonavi.**-keep class com.amap.api.** {*;}-keep class com.autonavi.** {*;}-keep class com.a.a.** {*;}# Gson混淆腳本-keep class com.google.gson.stream.** {*;}-keep class com.youyou.uuelectric.renter.Network.user.** {*;}# butterknife混淆腳本-dontwarn butterknife.internal.**-keep class **$$ViewInjector { *; }-keepnames class * { @butterknife.InjectView *;}# -------------系統類不需要混淆 ---------------------------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.**-keep public class com.android.vending.licensing.ILicensingService-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 *;}# --------- 忽略異常提示 ---------------------dontwarn butterknife.internal.**-dontwarn com.alipay.**-dontwarn com.mikepenz.**-dontwarn org.apache.**-dontwarn com.amap.**-dontwarn com.android.volley.**-dontwarn com.rey.**-dontwarn com.testin.**-dontwarn jp.wasabeef.**# ---------- 保持代碼 ---------------keep class com.youyou.uuelectric.renter.Utils.** {*;}-keep class it.neokree.** {*;}-keep class org.apache.** {*;}-keep class com.iflytek.** {*;}-keep class com.google.protobuf.** { *; }-keep class com.youyou.uuelectric.renter.pay.** {*;}# ---------------- eventbus避免混淆 -------------keepclassmembers class ** { public void onEvent*(**); void onEvent*(**);}# --------------- 友盟統計避免混淆 --------------------------dontwarn android.support.v4.**-dontwarn org.apache.commons.net.**-dontwarn com.tencent.**-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 *;}-keepclasseswithmembers class * { public <init>(android.content.Context);}-dontshrink-dontoptimize-dontwarn com.google.android.maps.**-dontwarn android.webkit.WebView-dontwarn com.umeng.**-dontwarn com.tencent.weibo.sdk.**-dontwarn com.facebook.**-keep enum com.facebook.**-keepattributes Exceptions,InnerClasses,Signature-keepattributes *Annotation*-keepattributes SourceFile,LineNumberTable-keep public interface com.facebook.**-keep public interface com.tencent.**-keep public interface com.umeng.socialize.**-keep public interface com.umeng.socialize.sensor.**-keep public interface com.umeng.scrshot.**-keep public class com.umeng.socialize.* {*;}-keep public class javax.**-keep public class android.webkit.**-keep class com.facebook.**-keep class com.umeng.scrshot.**-keep public class com.tencent.** {*;}-keep class com.umeng.socialize.sensor.**-keep class com.tencent.mm.sdk.openapi.WXMediaMessage {*;}-keep class com.tencent.mm.sdk.openapi.** implements com.tencent.mm.sdk.openapi.WXMediaMessage$IMediaObject {*;}-keep class im.yixin.sdk.api.YXMessage {*;}-keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}-keep public class [your_pkg].R$*{ public static final int *;}# 熱修復混淆-keep class * extends java.lang.annotation.Annotation-keep class com.alipay.euler.andfix.** { *; }-keepclasseswithmembernames class * { native <methods>;}
(5)混淆配置完成之後編譯混淆包,測試
有的時候混淆之後可能會出現一些奇形怪狀的bug,有條件的話,可以讓QA回滾一次混淆包的測試。
- 資源文件混淆-微信方案
前面我們說過本文主要講的是Apk的混淆,除了源代碼的混淆,還有資源文件的混淆。
去年微信推出了一個apk資源混淆方案,該方案的具體原理課參見:安裝包立減1M–微信Android資源混淆打包工具
在其文章中分析了資源文件混淆的幾種方案:
  • 方案一:最簡單的方法,我們按照Proguard的做法,直接在源碼級別修改,將代碼以及xml的R.string.name中替換到R.string.a,icon.png重命名爲a.png 然後再交給Android編譯。
  • 方案二:根據Android的編譯流程,所有資源ID已經被編譯成32位int值。這說明我們並不需要去修改xml與java,因爲在編譯 過程已經被R.java所替換,我們直接修改resources.arsc的二進制數據,不改變打包流程,只要在生成resources.arsc之後修 改它,同時重命名資源文件。
  • 方案三:直接處理安裝包. 不依賴源碼,不依賴編譯過程,僅僅輸入一個安裝包,得到一個混淆包。
幾種方案的對比如下:

微信版apk資源混淆方案採用的就是方案三,其具體的實現原理可參見其微信公衆號中的介紹;
利用該方案我們可以實現對資源文件的混淆,將apk中所有的資源文件名稱都替換爲a、b、c、d…,這樣也從側面增加了不良人員反編譯apk的難度,同時也減少了apk的大小,有興趣的同學可以自己嘗試一下。
總結:
上面我們分析了兩種混淆方式代碼混淆和資源文件混淆,其都是通過對源代碼或者資源文件名稱混淆(將其名稱替換成無意義的名稱)增加反編譯的難度,減小 Apk的大小,因此對產品而言這項工作還是很有意義的,一般而言都是做到了源代碼混淆,而對資源文件混淆方面意識不足,希望大家通過閱讀本文對Apk的混 淆能有一個整體的認識。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章