Android-項(xiàng)目中采用的混淆加固多渠道打包方案

用打包禮物的心情打包 apk
用打包禮物的心情打包 apk

前言

當(dāng)我們?nèi)f分努力將項(xiàng)目開(kāi)發(fā)完成之后,提交最后一行代碼后,會(huì)怎么樣?
長(zhǎng)舒一口氣,終于完成了,給自己放一天假,休息一下吧?

不,還沒(méi)完,作為一個(gè) Android 開(kāi)發(fā)者,我們接下來(lái)做的事情還有不少呢。

第一步 :混淆和加固應(yīng)用

實(shí)不相瞞,我之前從未對(duì)我的應(yīng)用加固過(guò),因?yàn)槲腋杏X(jué)用戶量不是太大,也不會(huì)有人有興趣來(lái)反編譯或者攻擊。直到我看到這一句話:

當(dāng)用戶使用你的應(yīng)用的那一刻起,作為開(kāi)發(fā)者,你就有責(zé)任去保證應(yīng)用使用整個(gè)過(guò)程中的用戶設(shè)備和信息的安全。

回想之前,覺(jué)得自己真的好爛,從現(xiàn)在開(kāi)始,我想成為一個(gè)負(fù)責(zé)任的開(kāi)發(fā)者。

第二步:打各種渠道包,看吶,這百花齊放的應(yīng)用市場(chǎng)。

因?yàn)閭ゴ蟮膲Γ瑳](méi)有了 Google Play ,但是我們收獲了一大片森林,多少個(gè)渠道包,取決于我們的運(yùn)營(yíng)是有多大的野心,一般情況下,幾十個(gè)是少不了的。

混淆和加固的區(qū)別

首先要明確的,混淆和加固是兩個(gè)非常不同的概念。(明確的原因,在于我之前就傻傻的以為混淆和加固是一回事,掩面羞愧逃~ )

混淆,是一種類似障眼法的作用,讓反編譯后的代碼閱讀難度增加,本質(zhì)上來(lái)說(shuō),并非是防止了反編譯,而是增加了閱讀難度。例如將要混淆類名和函數(shù)名,替換為無(wú)意義的短名稱,(OrderUtils. createOrder() -> A.b() )。

加固,可以理解為,將APK的外層加了一層殼,如果想反編譯,必須突破這層殼的保護(hù)。加固后的APK,反編譯出來(lái),看到的只是外面那層殼的代碼。加固涉及到的技術(shù)手段就很多了,同時(shí)也非常的深?yuàn)W,例如dex 文件加密和字節(jié)碼變形等。

混淆

開(kāi)啟混淆很簡(jiǎn)單

說(shuō)到混淆吧,沒(méi)用過(guò)混淆的人,看到混淆的那些關(guān)鍵字,估計(jì)都和我之前一樣,簡(jiǎn)直一臉懵,但是混淆過(guò)的我,告訴你們,完全不要害怕,混淆的道理真的很簡(jiǎn)單。

混淆,主要包括三個(gè)部分,資源壓縮,代碼混淆和代碼壓縮。

  • 資源壓縮
    主要壓縮的是對(duì)象是項(xiàng)目 res 和 asset 文件下未被引用的資源文件。這個(gè)工作是通過(guò) Gradle 的 Android 插件去實(shí)現(xiàn),默認(rèn)資源壓縮是關(guān)閉的,我們?cè)?build.gradle 中可以通過(guò) shrinkResources true 來(lái)開(kāi)啟。

  • 代碼壓縮和代碼混淆
    上面針對(duì)的是資源,這個(gè)針對(duì)的就是代碼文件了。這個(gè)方面,有一個(gè)在專門做 Java 字節(jié)碼混淆的工具 ProGuard ,使用起來(lái)非常方便,是不是很開(kāi)心?更開(kāi)心的是 Android Studio 2.0 之后已經(jīng)集成 ProGuard,我們?cè)俅慰梢酝ㄟ^(guò)在 build.gradle 中通過(guò) minifyEnabled true 就可以開(kāi)啟混淆了。

所以 build.gradle 中添加短短的三行代碼,項(xiàng)目打包 release 包就已經(jīng)是混淆后的包了。

buildTypes {
        release {
            minifyEnabled true  //開(kāi)啟混淆和代碼壓縮
            shrinkResources true //開(kāi)啟資源壓縮
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

這里注意 shrinkResources true 在 minifyEnabled true 的前提下,才會(huì)生效。因?yàn)樾枰a壓縮,釋放掉無(wú)用資源的引用,資源壓縮才能正常工作。

思考->為什么需要自定義規(guī)則,不能自動(dòng)混淆好嗎?

這是上面混淆三行代碼的中最長(zhǎng)的一句:

//混淆規(guī)則的文件
 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

上面代碼中有涉及到兩個(gè)文件,其中
proguard-android.txt 是 Android SDK 提供的默認(rèn)混淆文件,里面有 Android 應(yīng)用通用的一些混淆規(guī)則,位置在 sdk/tools/proguard/ 中,這個(gè)文件不需要我們修改,默認(rèn)就好。

proguard-rules.pro 是項(xiàng)目的混淆文件,提供給開(kāi)發(fā)者,用來(lái)編寫自定義的混淆規(guī)則,這個(gè)文件,才是我們做混淆工作的主戰(zhàn)場(chǎng)。

寫之前,需要明確的是,我們?yōu)槭裁匆?proguard-rules.pro中自定義規(guī)則?

這個(gè)需要明白兩個(gè)問(wèn)題

1.ProGuard 是怎么做到混淆的?

壓縮: 移除無(wú)效的類、屬性、方法等
優(yōu)化: 優(yōu)化字節(jié)碼,并刪除未使用的結(jié)構(gòu)
混淆: 將類名、屬性名、方法名混淆為難以讀懂的字母,比如a,b,c

2.ProGuard 混淆的范圍?是全部的類嗎?

ProGuard 是一個(gè)優(yōu)化 Java 字節(jié)碼的工具,也就是說(shuō),只要是Java文件都會(huì)被混淆。
但是這并不是我們想要的結(jié)果,因?yàn)橛行╊悾绻换煜蜁?huì)出現(xiàn)問(wèn)題,舉個(gè)例子,布局中有一個(gè) button 的 android: onClick 引用了 Activity MainActivity 中的方法 buttonClick()。混淆之后,布局文件是 .xml 文件不會(huì)被混淆,保持不變,Activity類是 .java 文件,會(huì)被混淆 ,MainActivity 被混淆成 A,buttonClick()被混淆成 b()。然后,讓我們點(diǎn)擊 button ,觸發(fā) onClick ,找不到 MainActivity.buttonClick(),是不是就會(huì)報(bào)錯(cuò)了,干脆利落地 Crash 了。

造成這個(gè)結(jié)果的原因是,ProGuard 并不是專門用來(lái)優(yōu)化 Android 應(yīng)用的一個(gè)工具,所以它并不知道什么該混淆,什么不該混淆。

混淆規(guī)則的制訂,更多的是一種保護(hù),告訴 ProGuard 某些類某些方法不用混淆。

proguard-android.txt 中默認(rèn)的一些規(guī)則,就是針對(duì)所有的 Android 項(xiàng)目都適用的混淆規(guī)則。

例如:

#包名不混合大小寫
-dontusemixedcaseclassnames

#不跳過(guò)非公共的庫(kù)的類
-dontskipnonpubliclibraryclasses

#混淆時(shí)記錄日志
-verbose

#關(guān)閉預(yù)校驗(yàn)
-dontpreverify

#不優(yōu)化輸入的類文件
-dontoptimize

#保護(hù)注解
-keepattributes *Annotation*

//等等,全部?jī)?nèi)容請(qǐng)自己去看sdk/tools/proguard/proguard-android.txt

由于每個(gè)項(xiàng)目的情況都不一樣,所以 項(xiàng)目中 proguard-rules.pro 的文件,就是留給開(kāi)發(fā)者根據(jù)自身項(xiàng)目情況,去設(shè)置混淆規(guī)則的。可謂是非常人性化。

混淆的99%工作->編寫自定義混淆規(guī)則

自定義混淆規(guī)則文件 proguard-rules.pro 的內(nèi)容可以分為三個(gè)部分:

  • 一些前輩們總結(jié)的,一般項(xiàng)目都會(huì)用到的混淆規(guī)則
  • 第三方庫(kù)的混淆規(guī)則 ,這個(gè)第三方文檔上都有。
  • 如果有使用ORM類型的數(shù)據(jù)庫(kù),例如greenDao,需要保護(hù)映射數(shù)據(jù)表的實(shí)體類不被混淆
  • 保護(hù) JNI 中調(diào)用的類不被混淆。
  • 保護(hù) WebView 中 JavaScript 調(diào)用的方法不被混淆
  • 保護(hù) Layout 布局使用的View構(gòu)造函數(shù)、android:onClick等不被混淆。

關(guān)于怎么保護(hù),這個(gè)按照 ProGuard 制訂規(guī)則去保護(hù)了,關(guān)鍵詞很多,而且視項(xiàng)目不同,混淆文件一般也不一樣,我也沒(méi)法給你提供一個(gè)模板什么。

你可以看這篇文章 寫給 Android 開(kāi)發(fā)者的混淆使用手冊(cè),寫的超級(jí)詳細(xì)超級(jí)棒,我就是看這個(gè)學(xué)會(huì)的混淆。

加固

加固這方面的技術(shù)要求太高了,沒(méi)有特別的安全需求的話,都會(huì)選擇第三方加固平臺(tái),公司項(xiàng)目采用的是梆梆加固

梆梆加固的使用方式很簡(jiǎn)單,上傳 apk 包,點(diǎn)擊加固,等待加固完畢,當(dāng)加固成功后,會(huì)得到一個(gè)評(píng)估報(bào)告,要仔細(xì)閱讀一下,查看是否由代碼上可修改的漏洞等,如果有,修改后再加固,然后,下載加固后的加固包即可。

多渠道打包

只要是需要分發(fā)到各大市場(chǎng)的應(yīng)用,多渠道的統(tǒng)計(jì)必不可少,因此多渠道打包必不可少,公司項(xiàng)目采用多渠道打包工具是 PackerNg。

PackerNgV2 提供 gradle 集成打包和腳本打包,因?yàn)槲覀冃枰庸蹋赃x擇腳本打包方式。具體步驟可以看 PackerNg的文檔

完整打包流程

基本的打包流程如下:

這里寫圖片描述

<font color="#008000">注意看,除了上面介紹的部分,多了一個(gè)重新簽名的步驟。</font>

因?yàn)楫?dāng)加固之后的 Apk 沒(méi)有簽名,需要我們重新簽名。自動(dòng)簽名的工具有很多,包括梆梆加固都有提供再簽名的工具,使用這些簽名之后PackerNg 腳本打包后會(huì)出現(xiàn) Error: Invalid Signature 錯(cuò)誤。原因是現(xiàn)在提供的工具大多只支持了 V1 簽名,而項(xiàng)目集成的 PackerNg 最新版本需要 V2 簽名,所以我們要給 Apk 重新簽 V2 簽名。

命令如下:

zipalign -v 4 <apk_path> <after_apk_path>//對(duì)齊
apksigner sign --ks <keystore_path> <after_apk_path> //重新簽名

//以下命令可用來(lái)驗(yàn)證對(duì)齊和再簽名的結(jié)果
zipalign -c -v 4 <apk_path>//驗(yàn)證是否對(duì)齊 
apksigner verify --verbose  <after_apk_path>  //查看簽名信息,用來(lái)驗(yàn)證是否是 V2 簽名

其中
apksigner 是Android SDK 自24.0.3開(kāi)始提供的官方簽名工具,位于:Android SDK/build-tools/對(duì)應(yīng)版本/apksigner。

zipalign 是 Android SDK 提供代碼對(duì)齊工具, 位于 Android SDK/build-tools/對(duì)應(yīng)版本/zipalign。

如果已經(jīng)配置好 sdk/build-tools/的 Path,直接在 Terminal 中,任何路徑下就能使用,如果沒(méi)有可以選擇是配置一下路徑或者切換到 sdk/build-tools/ 對(duì)應(yīng)版本/ 中操作。

最后

真的很感嘆,我也終于自己完整的走通了一個(gè)項(xiàng)目到發(fā)布市場(chǎng)的一整套流程,現(xiàn)在做完之后,看起來(lái)一切都很簡(jiǎn)單,步驟也不是很多,但是對(duì)于上周的我來(lái)說(shuō),因?yàn)閷?duì)混淆和加固的知之甚少,真的膽戰(zhàn)心驚的去做這件事情,混淆之后安裝測(cè)試,簽名之后安裝測(cè)試等等,因?yàn)榧s了百度的首發(fā),上線時(shí)間有限制,真的害怕搞出來(lái)自己短時(shí)間內(nèi)無(wú)法解決的問(wèn)題。

我仔細(xì)想想,當(dāng)時(shí)的緊張,都是對(duì)未知的恐懼。例如,簽名遇到問(wèn)題了,才知道 Android 7.0 新出了 V2 簽名機(jī)制等,因?yàn)闆](méi)用過(guò),也測(cè)了又測(cè),直到放心。

在這個(gè)知識(shí)的海洋里,我知道的真是太少了,努力加油吧,為了以能夠自信多一點(diǎn)點(diǎn)。


剛剛開(kāi)通了個(gè)人微信公眾號(hào),最新的博客,好玩的事情,都會(huì)在上面分享,歡迎關(guān)注 ^ o ^ 。

微信公眾號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,606評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,044評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,826評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,227評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,447評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,807評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,001評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評(píng)論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,243評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,667評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,930評(píng)論 1 287
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,709評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,996評(píng)論 2 374

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