Android代碼混淆

一、為什么要進(jìn)行代碼混淆大州?

java是一種跨平臺(tái)的续语、解釋型語言、Java源代碼編譯成中間”字節(jié)碼”存儲(chǔ)于class文件中厦画。由于跨平臺(tái)的需要疮茄,Java字節(jié)碼中包括很多源代碼信息,如變量名根暑、方法名力试,并且通過這些名稱來訪問變量和方法,這些符號(hào)帶有許多語義信息排嫌,很容易被反編譯成Java源代碼畸裳。為了防止這種現(xiàn)象,我們可以使用Java混淆器對Java字節(jié)碼進(jìn)行混淆躏率。

二躯畴、什么是代碼混淆?

混淆就是對發(fā)布出去的程序進(jìn)行重新組織和處理薇芝,使用處理后的代碼與處理前代碼完成相同的功能蓬抄,而混淆后的代碼很難被反編譯,即使反編譯成功也很難得出程序的真正語義夯到。被混淆過的程序代碼嚷缭,仍然遵照原來的檔案格式和指令集,執(zhí)行結(jié)果與混淆前一樣,只是混淆器將代碼中的所有變量阅爽、函數(shù)路幸、類的名稱變?yōu)楹喍痰挠⑽淖帜复?hào),在缺乏相應(yīng)的函數(shù)名和程序注釋的情況下付翁,即使被反編譯简肴,也將難以閱讀。同時(shí)混淆是不可逆的百侧,在混淆過程中有一些不影響正常運(yùn)行的信息將永遠(yuǎn)丟失砰识,這些信息的丟失使程序變得更加難以理解。

三佣渴、代碼混淆的作用辫狼?

混淆器的作用不僅僅是保護(hù)代碼,它也有精簡編譯后程序大小的作用辛润。由于以上介紹的縮短變量和函數(shù)名以及丟失部分信息的原因膨处,編譯后jar文件體積大約能減少25%,這對當(dāng)前費(fèi)用較貴的無線網(wǎng)絡(luò)傳輸是有一定意義的砂竖。

四真椿、混淆后apk個(gè)資源文件的比較(見圖)

  • 1、包名的比較


    混淆前.png

    混淆后.png
  • 2晦溪、變量名


    混淆前.png

    混淆后.png
  • 3瀑粥、方法名


    混淆前.png

    混淆后.png
  • 4挣跋、字節(jié)碼文件


    混淆前.png

    混淆后.png

五三圆、代碼混淆怎么做?

  • 1避咆、AndroidStudio環(huán)境下代碼混淆涉及到的文件及配置

     1. 項(xiàng)目的app/build.gradle
    
image.png

image.png
   2.代碼混淆工具以及混淆的配置文件(android SDK目錄下)
image.png
  • 具體代碼混淆操作
    首先在app/build.gradle文件中開啟代碼混淆開關(guān)
    minifyEnabled true //混淆開關(guān)
    默認(rèn)的混淆腳本文件(proguard-android.txt)中設(shè)置了默認(rèn)的保留不混淆條件舟肉,但是大多數(shù)情況下我們?nèi)匀灰O(shè)置我們自己的混淆腳本文件。具體操作如下:


    image.png

    然后需要在項(xiàng)目生成的混淆腳本中添加過濾混淆的條件

# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
 **[] $VALUES;
 public *;
}

# Gson
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# OkHttp3
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# Okio
-dontwarn com.squareup.**
-dontwarn okio.**
-keep public class org.codehaus.* { *; }
-keep public class java.nio.* { *; }
# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
# RxJava RxAndroid
-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;
}
#數(shù)據(jù)模型(實(shí)體類)
-keep class com.seekfangle.pad.bean.* {*;}
#第三方架包
-keep class  cn.com.** { *;}
-keep class  android_serialport_api.** { *;}

配置說明使用到的開源架包(Rxjava查库、Gson等)都能從網(wǎng)上找到混淆配置,直接拷貝到腳本文件中


image.png

使用但三方放架包時(shí)如下圖路媚,配置時(shí)最好打開找到其包名采用上述配置文件中的配置方式。


image.png

六樊销、混淆為什么要保留類名或方法名整慎?

1、讓C/C++程序可以通過jni使用對應(yīng)的java方法
2围苫、四大組件由于在AndroidManifest.xml里面注冊了裤园,所以需要保留。
3剂府、R文件混淆會(huì)導(dǎo)致引用錯(cuò)誤拧揽。
4、第三方架包有的已經(jīng)經(jīng)過混淆了,再次混淆會(huì)導(dǎo)致找不到類名或者方法名

七淤袜、什么時(shí)候不被混淆痒谴?

一般以下情況都會(huì)不混淆:
1.使用了自定義控件那么要保證它們不參與混淆
2.使用了枚舉要保證枚舉不被混淆
3.對第三方庫中的類不進(jìn)行混淆
4.運(yùn)用了反射的類也不進(jìn)行混淆
5.使用了 Gson 之類的工具要使 JavaBean 類即實(shí)體類不被混淆
6.在引用第三方庫的時(shí)候,一般會(huì)標(biāo)明庫的混淆規(guī)則的铡羡,建議在使用的時(shí)候就把混淆規(guī)則添加上去积蔚,免得到最后才去找
7.有用到 WebView 的 JS 調(diào)用也需要保證寫的接口方法不混淆,原因和第一條一樣
8.Parcelable 的子類和 Creator 靜態(tài)成員變量不混淆烦周,否則會(huì)產(chǎn)生 Android.os.BadParcelableException 異常

八库倘、混淆語法

  • 基本規(guī)則
    兩個(gè)常用的混淆命令,注意一顆星表示只是保持該包下的類名论矾,而子包下的類名還是會(huì)被混淆教翩;而兩顆星表示把本包和所包含的子包下的類名都保留。

    -keep class cn.hadcn.test.**
    -keep class cn.hadcn.test.*
    

如果既想保持類名贪壳,又想保持里面的內(nèi)容不被混淆饱亿,就執(zhí)行以下方法

    -keep class com.example.bean.** { *; }

在此基礎(chǔ)上,我們也可以使用Java的基本規(guī)則來保護(hù)特定類不被混淆闰靴,比如我們可以用extend彪笼,implement等這些Java規(guī)則。如下例子就避免所有繼承Activity的類被混淆

保留我們使用的四大組件蚂且,自定義的Application等等這些類不被混淆
因?yàn)檫@些子類都有可能被外部調(diào)用

-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
  • 2配猫、基本混淆模板
#############################################
#
# 對于一些基本指令的添加
#
############################################## 代碼混淆壓縮比,在0~7之間杏死,默認(rèn)為5泵肄,一般不做修改
-optimizationpasses 5
# 混合時(shí)不使用大小寫混合,混合后的類名為小寫
-dontusemixedcaseclassnames
# 指定不去忽略非公共庫的類
-dontskipnonpubliclibraryclasses
# 這句話能夠使我們的項(xiàng)目混淆后產(chǎn)生映射文件# 包含有類名->混淆后類名的映射關(guān)系
-verbose
# 指定不去忽略非公共庫的類成員
-dontskipnonpubliclibraryclassmembers
# 不做預(yù)校驗(yàn)淑翼,preverify是proguard的四個(gè)步驟之一腐巢,Android不需要preverify,去掉這一步能夠加快混淆速度玄括。
-dontpreverify
# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature
# 拋出異常時(shí)保留代碼行號(hào)
-keepattributes SourceFile,LineNumberTable
# 指定混淆是采用的算法冯丙,后面的參數(shù)是一個(gè)過濾器# 這個(gè)過濾器是谷歌推薦的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*

#############################################
#
# Android開發(fā)中一些需要保留的公共部分
#
#############################################
# 保留我們使用的四大組件遭京,自定義的Application等等這些類不被混淆# 因?yàn)檫@些子類都有可能被外部調(diào)用
-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

# 保留support下的所有類及其內(nèi)部類
-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中的方法參數(shù)是view的方法胃惜,# 這樣以來我們在layout中寫的onClick就不會(huì)被影響
-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();
}
# 對于帶有回調(diào)函數(shù)的onXXEvent、**On*Listener的哪雕,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}
# webView處理船殉,項(xiàng)目中沒有使用到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);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市热监,隨后出現(xiàn)的幾起案子捺弦,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件列吼,死亡現(xiàn)場離奇詭異幽崩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)寞钥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門慌申,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人理郑,你說我怎么就攤上這事蹄溉。” “怎么了您炉?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵柒爵,是天一觀的道長。 經(jīng)常有香客問我赚爵,道長,這世上最難降的妖魔是什么唁奢? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任麻掸,我火速辦了婚禮,結(jié)果婚禮上赐纱,老公的妹妹穿的比我還像新娘。我一直安慰自己千所,他們只是感情好淫痰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烈评,像睡著了一般讲冠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玻熙,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天嗦随,我揣著相機(jī)與錄音枚尼,去河邊找鬼署恍。 笑死锭汛,一個(gè)胖子當(dāng)著我的面吹牛唤殴,可吹牛的內(nèi)容都是我干的到腥。 我是一名探鬼主播乡范,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼晋辆,長吁一口氣:“原來是場噩夢啊……” “哼瓶佳!你這毒婦竟也來了霸饲?” 一聲冷哼從身側(cè)響起厚脉,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤霞溪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坊饶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幼东,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年简逮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了散庶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悲龟。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖轻腺,靈堂內(nèi)的尸體忽然破棺而出贬养,到底是詐尸還是另有隱情误算,我是刑警寧澤尉桩,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布止邮,位于F島的核電站,受9級(jí)特大地震影響导披,放射性物質(zhì)發(fā)生泄漏屈扎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一撩匕、第九天 我趴在偏房一處隱蔽的房頂上張望鹰晨。 院中可真熱鬧模蜡,春花似錦、人聲如沸扁凛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春澄峰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堂竟。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工魂毁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人出嘹。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓席楚,卻偏偏與公主長得像垮斯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子只祠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 聲明 這篇文章更多的是做一個(gè)整理兜蠕,內(nèi)容來自于ProGuard官方文檔以及各種博客等,相關(guān)文章的鏈接在參考目錄里抛寝,感...
    夷陵小祖閱讀 3,682評論 0 23
  • 什么是代碼混淆 代碼混淆就是將代碼中的各種元素熊杨,如變量,方法盗舰,類和包的名字改寫成無意義的名字晶府,增加項(xiàng)目反編譯后被讀...
    蝸牛家族史閱讀 5,147評論 1 4
  • 最近抽空研究了下android 加殼技術(shù)郊霎,發(fā)現(xiàn)關(guān)于加殼的源代碼特別少,即使有也不能做到版本兼容爷绘,問題又特別多书劝,對a...
    悠悠我思閱讀 1,643評論 0 3
  • 本篇文章:自己在混淆的時(shí)候整理出比較全面的混淆方法,比較實(shí)用土至,自己走過的坑购对,淌出來的路。請大家不要再走回頭路陶因,可能...
    Zane_Samuel閱讀 55,367評論 8 93
  • 我的第二故鄉(xiāng)骡苞,在貴州貴陽,這里有我的舅舅楷扬、公公解幽、婆婆、姨媽烘苹、姨父躲株。在我還是一個(gè)懵懂小孩的時(shí)候來過這里,十多年之后我...