基于AS的代碼混淆配置

什么是代碼混淆

代碼混淆(Obfuscated code)亦稱花指令,是將計(jì)算機(jī)程序的代碼,轉(zhuǎn)換成一種功能上等價(jià),但是難于閱讀和理解的形式的行為。代碼混淆可以用于程序源代碼,也可以用于程序編譯而成的中間代碼。執(zhí)行代碼混淆的程序被稱作代碼混淆器。目前已經(jīng)存在許多種功能各異的代碼混淆器。

將代碼中的各種元素,如變量,函數(shù),類的名字改寫成無意義的名字。比如改寫成單個(gè)字母,或是簡(jiǎn)短的無意義字母組合,甚至改寫成“__”這樣的符號(hào),使得閱讀的人無法根據(jù)名字猜測(cè)其用途。重寫代碼中的部分邏輯,將其變成功能上等價(jià),但是更難理解的形式。比如將for循環(huán)改寫成while循環(huán),將循環(huán)改寫成遞歸,精簡(jiǎn)中間變量,等等。打亂代碼的格式。比如刪除空格,將多行代碼擠到一行中,或者將一行代碼斷成多行等等。
(以上摘自百度百科)

一些吐槽:
1.混淆后難以理解,在調(diào)試過程中,崩潰等問題出現(xiàn)后,無法從日志中直觀地看懂錯(cuò)誤信息,加大了調(diào)試難度。
2.并不能完全阻止反向,混淆本身就是為了阻止反編譯,但它的機(jī)制是將類名、方法、變量等名字改為單個(gè)字母之類的東西,只能加大閱讀和反向的難度,并不是無法反向。
3.給反射和Native帶來不便,java反射機(jī)制和jni調(diào)用的機(jī)制,都涉及到確定的類名和方法名等信息,經(jīng)過混淆后,原來正常的邏輯各種出錯(cuò)。

不要問我為啥不說優(yōu)點(diǎn),因?yàn)椴恍枰獌?yōu)點(diǎn),它本身的意義就是最大的優(yōu)點(diǎn),就算槽點(diǎn)再多,該用還是要用啊 (ˉ▽ˉ;)

混淆配置

本文只討論在Android Studio平臺(tái)下開發(fā)的場(chǎng)景。

1.開啟混淆

要使用代碼混淆,需要在當(dāng)前module下的 build.gradle 文件中android節(jié)點(diǎn)下做如下配置:

android {
    ......
    buildTypes {
        release {
            minifyEnabled true //開啟代碼混淆
            shrinkResources true //此句可選是否精簡(jiǎn)無用資源
            signingConfig signingConfigs.release

            //指定混淆時(shí)用到的配置文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        ......
    }
    ......
}

具體的混淆相關(guān)配置要到當(dāng)前module下的 proguard-rules.pro 文件中進(jìn)行配置。

首先是安卓四大組件和其他需要被反射的類。(對(duì)應(yīng)到j(luò)son接口的實(shí)體類在反序列化時(shí)為反射機(jī)制,四大組件聲明在清單文件中,也是由反射實(shí)例化)

-optimizationpasses 5 //指定代碼壓縮級(jí)別
-keep public class * extends android.app.Application
-keep public class * extends android.app.Activity
-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

//一般我們的實(shí)體類要實(shí)現(xiàn) Serializable 接口。(或Parcelable)
-keep classmembers class * implements java.io.Serializable {*;}

然后是引用到的第三方庫(kù),需要避免被混淆。否則,鬼知道它里面哪個(gè)類被反射或和Native交互。所以直接按照包名全部屏蔽。下面是一些我自己常用的三方庫(kù)。

# okhttp retrofit rxjava
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn retrofit2.**
-dontwarn rx.**
-keep class okhttp3.**{ *; }
-keep class okio.** {*;}
-keep class retrofit2.** { *; }
-keep class rx.** { *; }

# rxjava
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
 long producerIndex;
 long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
 rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
 rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

# json相關(guān)
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keepclassmembers class * { public <init>(org.json.JSONObject); }

# 極光
-dontwarn cn.jpush.**
-dontwarn cn.jiguang.**
-keep class cn.jpush.**{*;}
-keep class cn.jiguang.** { *; }

# 百度(地圖?)
-keep class com.baidu.** {*;}
-keep class vi.com.gdi.bgl.** {*;}

# Glide
-dontwarn com.bumptech.glide.**
-keep class com.bumptech.glide.**{ *; }

# ijkplayer
-keep class tv.danmaku.ijk.media.**{*;}

# zxing
-keep class com.google.zxing.**{*;}

# 支付寶
-keep class com.alipay.**{*;}

# 微信
-keep class com.tencent.**{*;}

如果你的項(xiàng)目中用到一些其它第三方的庫(kù),記得添加進(jìn)來,一般只需要keep一下就好了。

好了,配置完以后,打個(gè)包試試吧。不要直接run as 或者 debug,那樣是不走這個(gè)配置的,打包正常的話就是配置好啦,如果報(bào)錯(cuò)的話,記得去看gradle輸出的日志,看看是找不到類還是什么的,定位到需要屏蔽混淆的類。

------(˙<>˙)/------完。

轉(zhuǎn)載請(qǐng)注明出處,[@via 小風(fēng)風(fēng)吖-基于AS的代碼混淆配置 蟹蟹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容