Android 應用防止被二次打包指南

前言

「Android APP二次打包」則是盜版正規Android APP,破解後植入惡意代碼從新打包。無論從性能、用戶體驗、外觀它都跟正規APP如出一轍可是背後它確悄悄運行着可怕的程序,它會在不知不覺中浪費手機電量、流量,惡意扣費、偷窺隱私等等行爲。java

二次打包問題只是Android應用安全風險中的一部分, 通常是經過反編譯工具嚮應用中插入廣告代碼與相關配置,再在第三方應用市場、論壇發佈。react

對於打包黨對於移動App帶來的危害有如下幾種:android

  • 1. 插入本身廣告或者刪除原來廣告;
  • 2. 惡意代碼, 惡意扣費、木馬等;
  • 3. 修改原來支付邏輯。

上述惡意行爲嚴重危害移動產品和用戶利益,同時也影響企業口碑。面試

關於移動App破解、數據泄露風險問題,以金融行業爲例:衆所周知數據是金融類應用產品重要資源之一,關乎企業生存與發展、但移動應用常常被破解、數據被抓包,致使本地存儲數據以及用戶名、密碼等重要信息泄露。下面舉例說明數據泄露案例。算法

金融類本地存儲數據泄漏react-native

數據抓包,泄漏用戶名和密碼安全

面對二次打包很多公司都有本身的防範措施,知名公司的APP幾乎都是本身在程序內部作過處理防止其APP被二次打包,一旦打包後從新運行則程序自動退出。接下來,我就來詳解一下如何防止APP被二次打包。數據結構

### 如何解決移動App安全風險問題?app

基於多年的移動安全經驗積累,網易雲易盾在移動APP安全風險問題上,從起始的開發階段、中間的測試階段再到結尾發佈階段,針對移動APP全生命週期進行安全防禦。工具

開發階段——移動應用開發時接入安全組件,保護數據安全。其中,針對安全通訊方面,實現數據高強度加密,結合傳統的對稱、非對稱加密算法和hash算法,客戶端加密數據只有認證服務端才能解密,從而防止了數據泄漏、數據竊取和篡改。另外,爲了實現增強數據的安全強度,安全組件結合自適應特徵算法和隨機切換算法,保證不一樣時間、不一樣終端的算法和密鑰的差別性。

測試階段——對移動應用進行人工滲透測試,發現漏洞解決產品修復相關問題,包括:APP滲透測試和服務端滲透測試。

發佈階段——APP上架以前針對應用作安全加固,提升安全防禦等級,上架以後作盜版監測。網易雲易盾可針對dex文件進行加固防禦,防止被靜態反編譯獲取代碼邏輯;保護應用在被非法二次打包後不能正常運行;防止經過使用調試器工具對應用進行非法破解;提供自研高穩定的設備指紋,防止潛在的刷單風險;加密資源文件,防止apk資源文件被破解;對so文件進行加固保護,防止native代碼被逆向分析;對遊戲提供加固保護,讓遊戲免受破解、外掛等威脅。

要實現代碼內部防止APP被二次打包首先得了解APK的機器識別原理,APK的惟一識別是依靠包名和簽名來作鑑定的,相似豌豆夾的洗白白、360手機衛士等安全軟件對APK的山寨識別,他們就是依賴包名來肯定APK而後經過簽名來肯定其是否山寨。因此說本身的程序內部在啓動的時候能夠經過獲取APK自己的簽名而後和正確的簽名作對比來識別本身是否被二次打包。

經過PackageManag對象能夠獲取APK自身的簽名。

過對簽名的碼的分解獲得一串20左右的字符串,此字符串則是APK的簽名的MD5值,經過獲取的簽名MD5值與正確的MD5值進行對比,就能夠識別其APK是否被盜版。

下圖是一些已作過保護的APP的代碼塊分析:

上圖是「XX省電王「的防止二次打包的關鍵代碼

上圖是」XX電池管家」的防止二次打包的關鍵代碼

以上兩處都是smali層的代碼,以上2處代碼的截圖都是下載量很是高的APP所作的防止二次打包的處理,其處理的代碼確定會使用到的關鍵代碼是

Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature。

此方法可以起到必定的安全做用,通常的打包黨面對它是迫不得已的,若是你瞭解一些smali語法它的做用就等於0了。

### Android 應用加固的技術細節

此外,針對如何加固的技術細節問題,網易雲資深安全工程師鍾亞平在安卓巴士全球開發者論壇的活動中也作過《安卓App逆向與保護》的主題演講:

安卓App安全包含不少內容,包括混淆代碼、總體Dex加固、拆分 Dex 加固、虛擬機加固等方面。事實上,這些內容也是國內近幾年Android App安全保護的一種主要趨勢。

1、混淆代碼

Java代碼是很是容易反編譯的,做爲一種跨平臺的、解釋型語言,Java 源代碼被編譯成中間「字節碼」存儲於class文件中。因爲跨平臺的須要,這些字節碼帶有許多的語義信息,很容易被反編譯成Java源代碼。爲了很好地保護Java源代碼,開發者每每會對編譯好的class文件進行混淆處理。

混淆就是對發佈出去的程序進行從新組織和處理,使得處理後的代碼與處理前代碼完成相同的功能,而混淆後的代碼很難被反編譯,即便反編譯成功也很可貴出程序的真正語義。ProGuard就是一個混淆代碼的開源項目,可以對字節碼進行混淆、縮減體積、優化等處理。

Proguard處理流程圖以下所示,包含壓縮、優化、混淆、預檢四個主要環節:

    1. 壓縮(Shrink):檢測並移除代碼中無用的類、字段、方法和特性(Attribute);
    1. 優化(Optimize):對字節碼進行優化,移除無用的指令。優化代碼,非入口節點類會加上private/static/final,沒有用到的參數會被刪除,一些方法可能會變成內聯代碼;
    1. 混淆(Obfuscate):使用a、b、c、d這樣簡短而無心義的名稱,對類、字段和方法進行重命名;
    1. 預檢(Preveirfy):在Java平臺上對處理後的代碼進行預檢,確保加載的class文件是可執行的。

混淆代碼逆向分析

若是想要反編譯混淆代碼,鍾亞平分享了一個國外的工具DEGUADR,它可以經過統計的方式來解混淆。雖然這個工具的正確率達不到100%,可是能在必定程度上幫助反編譯代碼。

com.xxxxx.common.util.CryptoUtil網站也提供了一種反編譯服務,以下所示:

java.lang.String a(byte[]) -> encodeToString

java.lang.String a(byte[],boolean,java.lang.String) ->a

byte[] a(byte[],byte[]) -> encrypt

byte[] b(byte[]) -> getKey

byte[] b(byte[],byte[]) -> decrypt

byte[] d(java.lang.String) -> getKey

java.lang.String a(byte,char[]) -> a

java.lang.String a(java.io.File) -> getHash

java.lang.String a(java.lang.String) -> c

java.lang.String b(java.lang.String) -> encode
2、總體Dex加固

爲了增強Android保護強度,隨着安全技術的發展,又出現了新型的「加固技術」。Dex加固是對Dex文件進行加殼防禦,防止被靜態反編譯工具破解而泄露源碼,最剛開始出現的是總體加固技術方案。

總體加固技術的原理如上所示,包括替換application/classes.dex、解密/動態加載原classes.dex、調用原application相關方法、將原application對象/名稱設置到系統內部相關變量四大環節。其中最爲關鍵的一步就是解密/動態加載原classes.dex,經過加密編譯好的最終ex源碼文件,而後在一個新項目中用新項目的application啓動來解密原項目代碼並加載到內存中,再把當前進程替換爲解密後的代碼,可以很好地隱藏源碼並防止直接性的反編譯。

總體Dex加固逆向分析

總體Dex加固逆向分析有兩種經常使用的方法。其一是在內存中暴力搜索 dexn035,再 dump。如下是在32位系統中的效果示例:

另外一種方法就是經過Hook dvmDexFileOpenPartial(void addr, int len, DvmDex*)。

3、拆分Dex加固

隨着業務規模發展到必定程度,不斷地加入新功能、添加新的類庫,代碼在急劇膨脹的同時,相應的apk包的大小也急劇增長,那麼簡單的總體加固方案就不能很好地知足安全需求,在總體加固方案以外又出現了拆分加固的技術方案。

可是如上所示,Dex文件在加固時,針對中間缺失的一部分數據會以解密後的數據來替換,有的時候這種拆分替換也會致使數據不許確。那麼到底應該拆分什麼樣的數據呢?就須要瞭解一下Dex文件的數據結構。

Dex文件結構極爲複雜,如下圖示選取了其中較爲重要的內容。事實上,Dex文件是一個以class爲核心組裝起來的文件,其中最重要的是classdata和classcode兩部分,有其特定的接口和指令數據,選取這兩部分來拆分的話,即便拆分出來也不會泄露class數據和字節碼數據,反編譯出來也不完整,安全性較高。

拆分Dex加固逆向分析

對於Dex拆分加固的逆向分析,以下所示,能夠用classdata替換從而組裝成新的Dex文件,雖然和原來的Dex文件不會徹底一致,但也在必定程度上覆原了被拆分數據的樣子。

但要注意的是,這種方法僅適用於被拆分出去的數據變形一次性完成,也就是說,在有其餘保護思路的狀況下儘可能避免使用,並且即便有須要也儘可能選在用到這個類的時候纔去恢復。

此外還有一個更底層一些的工具dexhunter,這個工具較爲前衛,但同時也有一些侷限性,譬如部分指令數據會被優化,造成的代碼界面不是很美觀等等。

4、虛擬機加固

虛擬機加固也屬於Dex拆分加固的一種,它是對字節作了一些變化處理。以下所示,這是一個正常安卓系統中的代碼,在其中進行了虛擬機加固操做:

以add-int v0, v1, v二、sub-int v0, v1, v二、mul-int v0, v1, v2這三條指令進行替換,而後進行加固編譯,這樣子操做後,即便把替換後的數據恢復了,也不會以add-int v0, v1, v二、sub-int v0, v1, v二、mul-int v0, v1, v2這三條指令進行替換,而後進行加固編譯,這樣子操做後,即便把替換後的數據恢復了,也不會變造成爲以前的字節碼,安全係數較高。

虛擬機加固逆向分析—HOOK JNI 接口

這種方式下的逆向分析,一方面能夠經過HOOK JNI 接口來實現,它有兩種實現方式。

其一是類成員/靜態變量操做相關接口,好比:

  • GetStaticDoubleField SetStaticDoubleField GetDoubleField SetDoubleField …

(byte, object, int, long…)

其二是反射調用類方法,好比:

*   CallVoidMethodA CallBooleanMethodA CallShortMethodA CallObjectMethodA …

*   CallStaticVoidMethodA CallStaticBooleanMethodA CallStaticShortMethodA CallStaticObjectMethodA …

*   (byte, int, long,double …)

*   CallObjectMethodA(JNIEnv* env, jobject object, jmethoID method, …)

經過HOOK JNI 接口實現虛擬機加固逆向分析

經過HOOK JNI 接口不用逆向底層,就能夠了解App大體的調用流程。可是對於複雜的調用過程,或者虛擬化方法數量較多的狀況,這種逆向分析手段看起來會比較混亂;對於不須要返射到Java層執行的指令,如算術、邏輯運算等,則沒法監控到。

虛擬機加固逆向分析—分析指令操做碼映射

另外一方面,也能夠經過分析指令操做碼映射來逆向分析。在同一加固版本,或者映射關係相同的狀況下,能夠採起如下所示的方法:

但在實際狀況中,每次加固時的映射關係都是隨機變化的,以下所示,這種狀況下就沒法直接創建映射關係。

不依賴於操做碼的映射關係只與虛擬機結構有關,因此須要根據偏移關係創建映射關係,從而進行逆向分析。

安卓App逆向保護做爲開發工做中的重要內容,一直是網易雲易盾致力提供的應用服務。後續,咱們將在SO加密保護方面進行更加深刻地研究,對SO裏面的邏輯進行分析,保護Native代碼不被逆向分析

總結

Android應用作不到徹底的防止二次打包。
一、簡單型

最簡單的就像簽名驗證。驗證編譯以後的dex簽名,md5等數據。

二、微有點技術含量型

由native在運行時釋放class到內存。釋放bytes數據直接餵給classloader。

三、難度型

對native自己再進行一些加固,加逆向坑(暗樁)增長破解難度。

四、較難度型

Java代碼執行代碼的時候調用native操做,實現破解必須破解native部分。

最後若是須要,部分必要算法轉移到雲端執行,最大限度的去保證防被破解和二次打包

做者:yijian2595
連接:https://www.jianshu.com/p/b6c...

閱讀更多

react-native技術的優劣

 一招教你讀懂JVM和Dalvik之間的區別

一招教你打造一個滑動置頂的視覺特效

NDK項目實戰—高仿360手機助手之卸載監聽

(Android)面試題級答案(精選版)

相信本身,沒有作不到的,只有想不到的

在這裏得到的不只僅是技術!

相關文章
相關標籤/搜索