Android SDK 開(kāi)發(fā)系列二 代碼混淆

現(xiàn)在大多商業(yè)應(yīng)用都是經(jīng)過(guò)混淆的陨簇,混淆后雖然不能防止反編譯,但是可以增加反編譯后的難度迹淌,減小包的大小河绽,做sdk開(kāi)發(fā)一般都是比較核心的技術(shù),所以一般都是需要添加上混淆規(guī)則的
文中大部分轉(zhuǎn)自:https://www.cnblogs.com/zhangmiao14/p/7098168.html

混淆的原理

Java是一種跨平臺(tái)唉窃、解釋型語(yǔ)言耙饰,Java源代碼編譯成的class文件中有大量包含語(yǔ)義的變量名外邓、方法名的信息数苫,很容易被反編譯為Java源代碼粥血。為了防止這種現(xiàn)象,我們可以對(duì)Java字節(jié)碼進(jìn)行混淆忘闻∷是停混淆不僅能將代碼中的類名峡继、字段岸梨、方法名變?yōu)闊o(wú)意義的名稱,保護(hù)代碼篷扩,也由于移除無(wú)用的類兄猩、方法,并使用簡(jiǎn)短名稱對(duì)類鉴未、字段枢冤、方法進(jìn)行重命名縮小了程序的大小。

ProGuard由shrink铜秆、optimize淹真、obfuscate和preverify四個(gè)步驟組成,每個(gè)步驟都是可選的羽峰,需要哪些步驟都可以在腳本中配置趟咆。參見(jiàn)ProGuard官方介紹添瓷。
  壓縮(Shrink):默認(rèn)開(kāi)啟梅屉,偵測(cè)并移除代碼中無(wú)用的類、字段鳞贷、方法和特性坯汤,減少應(yīng)用體積,并且會(huì)在優(yōu)化動(dòng)作執(zhí)行之后再次執(zhí)行(因?yàn)閮?yōu)化后可能會(huì)再次暴露一些未使用的類和成員)搀愧。
  -dontshrink 關(guān)閉混淆
  優(yōu)化(Optimize):默認(rèn)開(kāi)啟惰聂,分析和優(yōu)化字節(jié)碼,讓?xiě)?yīng)用運(yùn)行的更快咱筛。
  -dontoptimize 關(guān)閉優(yōu)化搓幌,默認(rèn)混淆配置文件開(kāi)始
  -optimizationpasses n 表示proguard對(duì)代碼進(jìn)行迭代優(yōu)化的次數(shù),Android一般為5
  混淆(Obfuscate):默認(rèn)開(kāi)啟迅箩,使用a溉愁、b、c饲趋、d這樣簡(jiǎn)短而無(wú)意義的名稱拐揭,對(duì)類、字段和方法進(jìn)行重命名奕塑,增大反編譯難度堂污。
  -dontobfuscate 關(guān)閉混淆
上面三個(gè)步驟使代碼大小更小、更高效龄砰,也更難被逆向工程盟猖。
  預(yù)檢(Preverify):在java平臺(tái)上對(duì)處理后的代碼進(jìn)行預(yù)檢讨衣。
混淆流程圖:

image

Proguard讀入input jars(or wars,zip or directories),經(jīng)過(guò)四個(gè)步驟生成處理之后的jars(or wars,ears,zips or directories),Optimization步驟可選擇多次進(jìn)行。
為了確定哪些代碼應(yīng)該被保留式镐,哪些代碼應(yīng)該被移除或混淆值依,需要確定一個(gè)或多個(gè)Entry Point。Entry Point經(jīng)常是帶有main methods,applets,midlets的classes碟案,它們?cè)诨煜^(guò)程中會(huì)被保留愿险。
Proguard的幾個(gè)步驟如何處理Entry Points。
 〖鬯怠(1).在壓縮階段辆亏,Proguard從上述Entry Points開(kāi)始遍歷搜索哪些類和類成員被使用。其他沒(méi)有被使用的類和類成員會(huì)移除鳖目。
 “邕丁(2).在優(yōu)化階段,Proguard進(jìn)一步設(shè)置非Entry Point的類和方法為private领迈、static和final來(lái)進(jìn)行優(yōu)化彻磁,不使用的參數(shù)會(huì)被移除,某些方法會(huì)被標(biāo)記為內(nèi)聯(lián)狸捅。
 ≈则选(3).在混淆階段,Proguard重命名非Entry Points的類和類成員尘喝。
 〈沤健(4).預(yù)檢階段是唯一沒(méi)有觸及Entry Points的階段。

混淆的使用方法

1. 開(kāi)啟混淆
在build.gradle 中開(kāi)啟混淆

buildTypes {
        release {
           // 設(shè)置為true朽褪,開(kāi)啟混淆開(kāi)關(guān)
            minifyEnabled true
          // 'proguard-android.txt' 是AndroidStudio默認(rèn)自動(dòng)導(dǎo)入的規(guī)則置吓,這個(gè)文件位于Android SDK根目錄\tools\proguard\proguard-android.txt。這里面是一些比較常規(guī)的不能被混淆的代碼規(guī)則缔赠。'proguard-rules.pro'是針對(duì)我們自己的項(xiàng)目需要特別定義混淆規(guī)則衍锚,它位于項(xiàng)目根目錄下面,里面的內(nèi)容需要我們自己編寫(xiě)
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

2. 編寫(xiě)自己的編譯規(guī)則
在proguard-rules.pro 中進(jìn)行編寫(xiě)

因?yàn)槲覀兪莏ar包開(kāi)發(fā)嗤堰,完成以上兩步還要自己編寫(xiě)打包規(guī)則

// 依賴一個(gè)我們上邊已經(jīng)寫(xiě)好的打包task
task proguardJar(dependsOn: ['xxx'], type: proguard.gradle.ProGuardTask) {

    //Android 默認(rèn)的 proguard 文件
    configuration android.getDefaultProguardFile('proguard-android.txt')

    //混淆的配置文件
    configuration 'proguard-rules.pro'

  // 一下為 
   String inJar = xxx.archivePath.getAbsolutePath()
    //輸入 jar
    injars inJar
    println "inJar->>" + inJar
    //輸出 jar
    String outJar = inJar.substring(0, inJar.lastIndexOf(File.separator)) + "/proguard-${xxx.archiveName}"
    outjars outJar
    println "outJar->>" + outJar

    //設(shè)置不刪除未引用的資源(類戴质,方法等)
    dontshrink
}

3.查看構(gòu)建輸出
構(gòu)建時(shí)Proguard都會(huì)輸出下列文件:(build之后)
  (1)dump.txt --- 說(shuō)明APK中所有類文件的內(nèi)部結(jié)構(gòu)
 ×禾摹(2)mapping.txt --- 提供原始與混淆過(guò)的類置森、方法和字段名稱之間的轉(zhuǎn)換
  (3)seeds --- 列出未進(jìn)行混淆的類和成員
 》(4)usage.txt --- 列出從APK移除的代碼
這些文件保存在/build/outputs/mapping/release目錄下凫海。
4.解碼混淆過(guò)的堆棧追蹤
使用混淆后,保存好mapping文件男娄,程序csh時(shí)通過(guò)腳本進(jìn)行解碼行贪。
retrace工具位于/tools/proguard/目錄下漾稀,解碼命令為(注意把stacktrace_file 中的AndroidRuntime 等字段去掉)

retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

混淆的規(guī)則介紹

#?      匹配一個(gè)字符
#*       匹配一個(gè)名字,除了目錄外分隔符外的任意部分
#**      匹配任意名建瘫,可能包含任意路徑分隔符
#崭捍!     排除
#<field>        匹配類中的所有字段
#<method>   匹配類中所有的方法
#<init>          匹配類中所有的構(gòu)造函數(shù)

#代碼混淆壓縮比,在0~7之間
-optimizationpasses 5# 
#混淆時(shí)不適用大小寫(xiě)混合啰脚,混合后的類名為小寫(xiě)
-dontusemixedcaseclassnames

#指定不去忽略非公共庫(kù)的類
-dontskipnonpubliclibraryclasses

#不做預(yù)校驗(yàn)殷蛇,preverify是proguard的四個(gè)步驟之一,Android不需要precerify,去掉這一步能夠加快混淆速度橄浓。
-dontpreverify

-verbose

#google推薦算法
-optimizations !code/simplification/arithmetic,!code/simplication/cast,!field/*,!class/mergin/*

#避免混淆Annotation粒梦、內(nèi)部類、泛型荸实、匿名類
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod

#重命名拋出異常時(shí)的文件名稱
-renamesourcefileattribute SourceFile

#拋出異常時(shí)保留代碼行號(hào)
-keepattributes SourceFile,LineNumberTable

#處理support包
-dontnote android.support.**
-dontwarn android.support.**

#保留四大組件匀们,自定義的Application等這些類不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * entends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

#保留本地native方法不被混淆
-keepclasseswithmembernames class * {
native <methods>
}

#保留枚舉類不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

#第三方j(luò)ar包不被混淆
-keep class com.github.test.** {*;}

#保留自定義的Test類和類成員不被混淆
-keep class class.lily.Test {*;}

#保留自定義的xlog文件夾下面的類、類成員和方法不被混淆
-keep class com.text.xlog.** {
<fields>;
<methods>;
}

#assume no side effects;刪除android.util.Log輸出的日志
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
public static *** w(...);
public static *** e(...);
}

#保留keep注解的類名和方法
-keep,allowobfuscation @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclassmember class * {
@android.support.annotation.Keep *;
}

#避免混淆內(nèi)部類
-keep class com.letv.tracker2.msg.MessageProcessor$* {*;}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末准给,一起剝皮案震驚了整個(gè)濱河市泄朴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌露氮,老刑警劉巖祖灰,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沦辙,居然都是意外死亡夫植,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)油讯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人延欠,你說(shuō)我怎么就攤上這事陌兑。” “怎么了由捎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵兔综,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我狞玛,道長(zhǎng)软驰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任心肪,我火速辦了婚禮锭亏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘硬鞍。我一直安慰自己慧瘤,他們只是感情好戴已,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著锅减,像睡著了一般糖儡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怔匣,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天握联,我揣著相機(jī)與錄音,去河邊找鬼每瞒。 笑死拴疤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的独泞。 我是一名探鬼主播呐矾,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懦砂!你這毒婦竟也來(lái)了蜒犯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荞膘,失蹤者是張志新(化名)和其女友劉穎罚随,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體羽资,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡淘菩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屠升。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潮改。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腹暖,靈堂內(nèi)的尸體忽然破棺而出汇在,到底是詐尸還是另有隱情,我是刑警寧澤脏答,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布糕殉,位于F島的核電站,受9級(jí)特大地震影響殖告,放射性物質(zhì)發(fā)生泄漏阿蝶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一黄绩、第九天 我趴在偏房一處隱蔽的房頂上張望羡洁。 院中可真熱鬧,春花似錦宝与、人聲如沸焚廊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咆瘟。三九已至嚼隘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間袒餐,已是汗流浹背飞蛹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灸眼,地道東北人卧檐。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像焰宣,于是被迫代替她去往敵國(guó)和親霉囚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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