av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Android高級(jí)混淆和代碼保護(hù)技術(shù)

這是一篇關(guān)于 Android 代碼保護(hù)的文章,旨在介紹代碼混淆、防止逆向工程的各種高級(jí)技巧。大家都很忙,我也趕著回去繼續(xù)開(kāi)發(fā)我的新應(yīng)用,因此話不多說(shuō),越干(gan, 一聲)越好。

在海東等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),全網(wǎng)整合營(yíng)銷推廣,成都外貿(mào)網(wǎng)站建設(shè),海東網(wǎng)站建設(shè)費(fèi)用合理。

開(kāi)始之前,值得一說(shuō)的是,本文超過(guò)五千字,完全由我開(kāi)發(fā)的「純純寫(xiě)作」書(shū)寫(xiě)而成,純純寫(xiě)作主打安全、寫(xiě)作體驗(yàn)和永不丟失內(nèi)容,于是本著珍愛(ài)生命,我用純純寫(xiě)作來(lái)寫(xiě)這篇文章。

本文有兩部分內(nèi)容,一部分講混淆,一部分介紹一些混淆之下的安全手段?;鶞?zhǔn)原則都是:在保證不麻煩到自身 以及 能夠正常閱讀異常日志的前提下,盡可能提高混淆強(qiáng)度和保護(hù)代碼安全。

本文原文地址:http://drakeet.me/android-advanced-proguard-and-security/

混淆

Android 官方集成了 Proguard 以供我們進(jìn)行代碼混淆工作,關(guān)于 Proguard 你可以搜索到各種它的 rules 解釋,這些文章千篇一律,因此我不再贅述,只說(shuō)一些特別的有用的技巧:

一般情況下,Android 的 gradle 中都會(huì)默認(rèn)寫(xiě)著:

 
 
 
  1. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

這一行代碼很多人不了解。它的意思是,指定了兩個(gè) Proguard rules 文件,一個(gè)是通過(guò)getDefaultProguardFile() 方法獲得官方自帶的混淆規(guī)則文件路徑,另一個(gè)是與當(dāng)前 gradle 相同目錄下的 proguard-rules.pro 文件路徑。

后者就在我們項(xiàng)目中,由我們書(shū)寫(xiě)的,沒(méi)什么好說(shuō)的,我們要關(guān)注的是前者這個(gè)默認(rèn) Proguard 文件,它的內(nèi)容是什么你有曾探究過(guò)嗎?沒(méi)有的話,你可以在你的系統(tǒng)文件里搜索proguard-android.txt 就應(yīng)該能把它找出來(lái),具體自己去看,我就說(shuō)一些關(guān)鍵的,這個(gè)默認(rèn)文件中幫我們聲明了許多混淆規(guī)則內(nèi)容,包括:keep 所有繼承自 View 的類,keep 所有繼承自 Activity 的類,keep 所有 JavascriptInterface、native 方法聲明,以及 keep 一些注解了@Keep 的內(nèi)容。

所以你知道為什么默認(rèn)情況下,即使你自己一條規(guī)則都沒(méi)有加入,你的自定義 View 和 Activity 都被保留下來(lái)了吧,至少類名都沒(méi)有被混淆。

那么為什么官方默認(rèn)會(huì)幫我們寫(xiě)下這些?為什么 View 和 Activity 默認(rèn)情況下應(yīng)該被保留呢?

簡(jiǎn)單來(lái)說(shuō),因?yàn)?Proguard 原本是為 Java 打造的,它無(wú)法搜索到我們 AndroidManifest、布局等文件中引用了哪些 Java 類,因此如果 Java 代碼變了而 XML 文件中的引用沒(méi)變,就會(huì)造成反射失敗。所以這些被 XML 使用到的類需要 keep 住。

對(duì)于這個(gè)問(wèn)題,餓了么 的團(tuán)隊(duì)提供了一個(gè)鮮為人知的 gradle 插件 用來(lái)無(wú)傷混淆 Activity 和 View,這個(gè)項(xiàng)目叫 Mess:https://github.com/eleme/Mess ,具體內(nèi)容各位可以稍后自行去閱讀其文檔和教程,鏈接***都還會(huì)附于末尾。簡(jiǎn)單來(lái)說(shuō),Mess 彌補(bǔ)了 Proguard 不能檢索 XML 文件的缺點(diǎn),幫 Proguard 完成了 Activity 和 View 的改名及 mapping。

話說(shuō)回來(lái),前面我建議各位都去逐行了解下默認(rèn)混淆配置文件,因?yàn)橹挥羞@樣,你才知道整個(gè)混淆工具幫你做了什么,了解清楚之后,我建議的一個(gè)做法是,把這個(gè)默認(rèn)文件拷貝到你的項(xiàng)目目錄之下,刪掉 getDefaultProguardFile('proguard-android.txt'),再引入現(xiàn)存于你目錄之下的原默認(rèn)文件。這么做的好處是,方便你修改這個(gè)默認(rèn)文件,因?yàn)樗行﹥?nèi)容是不必要或者可以更改的。不過(guò)基本上我們可以保留其原樣。復(fù)制過(guò)來(lái)的另一個(gè)好處是,避免其被外方更新導(dǎo)致你引用過(guò)來(lái)后產(chǎn)生變數(shù)??傊琾roguardFiles 這個(gè)配置項(xiàng)(其實(shí)是一個(gè) gradle 方法)可以接受***個(gè) rules 文件路徑,它的參數(shù)是一個(gè)可變字符串參數(shù),不過(guò)為了避免代碼橫向發(fā)展,我更愿意使用另一個(gè)方法,叫 proguardFile,注意,少了一個(gè) s 有沒(méi)有,它接受單個(gè)參數(shù),相當(dāng)于 add 一個(gè) rules。對(duì)此,提供我的配置以供參考:

 
 
 
  1. release {
  2.     debuggable false
  3.     minifyEnabled true
  4.     zipAlignEnabled true
  5.     shrinkResources true
  6.     signingConfig signingConfigs.release
  7.     proguardFile 'proguard-common.pro'
  8.     proguardFile 'proguard-rules.pro'
  9.     proguardFile 'proguard-rules-google-ads.pro'}

其中 proguard-common.pro 這個(gè)文件就是上述我說(shuō)的復(fù)制過(guò)來(lái)的官方默認(rèn)配置文件,它被我放在當(dāng)前 module 目錄之下和 proguard-rules.pro 并列。這么寫(xiě)很清楚而且便于復(fù)用。

講完基本內(nèi)容之后,我決定再介紹兩條特別實(shí)用的 Proguard rules:

-repackageclasses

-repackageclasses 這條規(guī)則配置特別強(qiáng)大,它可以把你的代碼以及所使用到的各種第三方庫(kù)代碼統(tǒng)統(tǒng)移動(dòng)到同一個(gè)包下,可能有人知道這條配置,但僅僅知道它還不能發(fā)揮它***的作用,默認(rèn)情況下,你只要在 rules 文件中寫(xiě)上 -repackageclasses 這一行代碼就可以了,它會(huì)把上述的代碼文件都移動(dòng)到根包目錄下,即在 / 包之下,這樣當(dāng)有人反編譯了你的 APK,將會(huì)在根包之下看到 成千上萬(wàn) 的類文件并列著,除此之外,由于我們有時(shí)不得不 keep 一些類文件,于是你應(yīng)用的包名層次仍然會(huì)存在,有一些沒(méi)被完全混淆的類將繼續(xù)存留在你的包名之下,這些類文件就相對(duì)得不到很好的保護(hù)。于是我要介紹一個(gè)小技巧,就是 -repackageclasses 后跟上一個(gè)你應(yīng)用的包名,如:

-repackageclasses com.drakeet.purewriter.debug

這么做以后,最終 Proguard 會(huì)將包括第三方庫(kù)的所有類文件都移動(dòng)到你的包名之下,所謂藏葉于林,這時(shí)候那些你未能完全混淆的類也可以藏身在這類文件大海之中,而且這些類文件名都會(huì)被混淆成 abcd 字母組合的名字。

需要注意的是,-repackageclasses + 你的包名 這種做法存在混淆 bug,而默認(rèn) -repackageclasses 不加包名不會(huì)出現(xiàn) bug,所以初次使用此法需要進(jìn)行測(cè)試,否則請(qǐng)退而求其次,關(guān)于這個(gè) bug 的具體內(nèi)容不多說(shuō),很贅述。

第二個(gè)實(shí)用 rules 配置項(xiàng):-obfuscationdictionary

-obfuscationdictionary 后面加一個(gè)純文本文件路徑,它的作用是指定一個(gè)字典文件作為混淆字典。默認(rèn)情況下我們的代碼命名會(huì)被混淆成 abcdefg... 字母組合的內(nèi)容,需要修改可以使用這個(gè)配置項(xiàng)將字典修改成亂碼或中文內(nèi)容。亂碼命名可以令反編譯者懷疑人生。中文命名則能夠破壞一些反編譯軟件的正常工作,而且有的中文命名還能起到亂花漸欲迷人眼的效果,比如 GitHub 上較為流行的某長(zhǎng)者的話語(yǔ)作為字典,在此不便貼出(可能會(huì)有人身危險(xiǎn)),各位可以自行搜索,找不到別怪我。這些話語(yǔ)作為代碼命名,可以令反編譯者沉浸其中,無(wú)心分析代碼 :P。

***,關(guān)于混淆的內(nèi)容,我們還有一塊軟肋,就是資源文件,Proguard 完全不會(huì)管我們的資源文件,因此如果資源文件名沒(méi)有做保護(hù)的話,很容易被順藤摸瓜找到關(guān)聯(lián)的 Java 代碼,對(duì)此,微信團(tuán)隊(duì)提供了一個(gè)好用的資源混淆工具,它不僅能幫你全面混淆資源文件,還能幫你縮減資源文件的整體體積,這個(gè)工具叫 AndResGuard,開(kāi)源地址:https://github.com/shwenzhang/AndResGuard

好了,終于簡(jiǎn)單講完了一些關(guān)于混淆的要點(diǎn),關(guān)于混淆其實(shí)還有許多小內(nèi)容,比如可以使用consumerProguardFiles 為一個(gè) library 或 SDK 項(xiàng)目配置混淆文件,這樣當(dāng)某個(gè) app 引用了你這個(gè)庫(kù),無(wú)需再配置相關(guān)混淆內(nèi)容,該 app 就會(huì)自動(dòng)從 consumerProguardFiles 配置的文件中讀取需要進(jìn)行的 keep 動(dòng)作,這對(duì)于庫(kù)開(kāi)發(fā)者是很有用的一個(gè)功能。更多就不細(xì)說(shuō)了,文章末尾我會(huì)附上我的混淆配置文件片段。

安全

有了代碼混淆還不夠,我們需要更多技巧來(lái)保護(hù)我們的代碼,特別是對(duì)于需要做混淆但又需要暴露許多 API 的 SDK 開(kāi)發(fā)者來(lái)說(shuō)?;煜腔A(chǔ),代碼安全是意識(shí)。

首先我們要知道我們混淆代碼是如何被攻破的,其實(shí)對(duì)于反編譯者來(lái)說(shuō),最簡(jiǎn)單的入手點(diǎn)就是字符串搜索,我們硬編碼留在代碼里的字符串值都會(huì)在反編譯過(guò)程中被原樣恢復(fù),因此這是我們首要關(guān)注對(duì)象。避免被通過(guò)字符串攻破,我們應(yīng)該做到以下幾點(diǎn):

一,不要硬編碼寫(xiě)入字符串值,即使你不得不這么做,也至少應(yīng)該另起一個(gè)類,比如叫做HardStrings,用于靜態(tài)存放這些硬編碼的字符串。這樣反編譯者只能搜索到你這個(gè)常量類,而較難以搜索到這些字符串常量被哪里引用。

二,在 release 混淆過(guò)程中刪除 Log 代碼,使用 -assumenosideeffects 這個(gè)配置項(xiàng)可以幫我們?cè)诰幾g成 APK 之前把日志代碼全部刪掉,這么做不僅有助于提升性能,而且日志代碼往往會(huì)保留很多我們的意圖和許多可被反編譯的字符串:

 
 
 
  1. -assumenosideeffects class android.util.Log {
  2.     public static boolean isLoggable(java.lang.String, int);
  3.     public static int d(...);
  4.     public static int w(...);
  5.     public static int v(...);
  6.     public static int i(...);
  7. }

三,對(duì)于你不得不留下的一些硬編碼和日志內(nèi)容,可以采用編碼形式替換,如 你可以規(guī)定 "4001" 代表某種錯(cuò)誤,而不是在你的代碼里寫(xiě)入這個(gè)錯(cuò)誤的具體描述字符串。這么做的話,你需要有個(gè)地方記下這些編碼映射的內(nèi)容,關(guān)于此有個(gè)技巧:你可以再創(chuàng)建一個(gè)常量類,其內(nèi)容是一堆靜態(tài)字符串對(duì)象,針對(duì)上面那個(gè)例子,你可以把真正的錯(cuò)誤信息作為一個(gè)字符串變量的名字,而把它的值寫(xiě)成一個(gè)編碼,如下:

 
 
 
  1. public static final String SHOULD_REGISTER_FIRST_ERROR = "ssrrffe";

這樣當(dāng)你在看沒(méi)混淆的代碼引用這個(gè)靜態(tài)變量,你能夠一目了然它的意思。而反編譯者看到的則是:

 
 
 
  1. public static final String abc = "ssrrffe";

命名看不懂,值也看不懂。

四,把 AppKey 之類特別敏感的字符串內(nèi)容藏在 native so 文件中。

關(guān)于字符串技巧的內(nèi)容差不多就這樣了,能做到這些就不錯(cuò)了,還有一些極端做法不多說(shuō),為了阻礙黑客閱讀,自己也變得非常麻煩,雙刃劍,這不是我們想要的結(jié)果。

然后我們講另一個(gè)混淆后代碼的軟肋,就是一些我們不得不 keep 的內(nèi)容,如果是閉源 SDK 開(kāi)發(fā)者,需要 keep 的內(nèi)容將會(huì)更多,幾乎只要是 public 的類、變量,方法,全部要 keep,那么針對(duì)這個(gè)問(wèn)題,我們?cè)撛趺崔k?介紹一個(gè)方法:

給這些需要 keep 的內(nèi)容設(shè)置委托者,然后將委托者投入大海之中。

很玄乎吧?哈哈,這么講有助于記憶。其實(shí)和我們?cè)诨煜鹿?jié)說(shuō)的藏葉于林的思想是一樣的。如果一個(gè)類不得不 keep,那就把它所做的全部?jī)?nèi)容都轉(zhuǎn)交給一個(gè) private 或 internal 的類對(duì)象去完成,這個(gè)委托類對(duì)象代碼可以完全混淆,然后你再把這個(gè)委托類通過(guò)混淆工具藏在大量的代碼之中,這樣就足夠給反編譯者帶來(lái)了很大的麻煩,相比直接獲取邏輯代碼,這么做以后要找到實(shí)體的邏輯代碼將費(fèi)勁得多。

因此,如果你知道有這么一個(gè)方式,其實(shí)你完全可以不使用餓了么提供的那個(gè) Activity 和 View 混淆工具,也能很好地保護(hù)你的 Activity 和 View。

不過(guò)一般情況我們無(wú)需所有內(nèi)容都保護(hù),只要把關(guān)鍵、核心內(nèi)容委托出去就可以了。

***的***,我們還需要做的就是防止反編譯者重新打包,全方位絕人之路呀,能做的就是在代碼中加入簽名驗(yàn)證,并做雙向依賴。關(guān)于此我寫(xiě)過(guò)一個(gè)類似阿里黑匣子的東西,能夠在 native 檢查簽名和加解密內(nèi)容,后續(xù)也有計(jì)劃整理開(kāi)源,這里暫且就不多說(shuō)了。

除此之外,我專門(mén)寫(xiě)過(guò)一篇叫作《Android 密鑰保護(hù)和 C/S 網(wǎng)絡(luò)傳輸安全理論指南》 的文章,感興趣可以之后移步閱讀。

總之,代碼安全和混淆是一個(gè)意識(shí)加技巧的問(wèn)題,但都不難,掌握以上內(nèi)容就已經(jīng)十分好了。分享到此結(jié)束,如有疑問(wèn)或問(wèn)題歡迎來(lái)信交流。


網(wǎng)站名稱:Android高級(jí)混淆和代碼保護(hù)技術(shù)
瀏覽地址:http://uogjgqi.cn/article/cdpodjd.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流