標籤:業務 包括 diy blank 資訊 html 編譯 自己的 jar
代碼混淆
Android開發除了部分功能採用C/C++編碼外,其餘主要都是採用Java進行編碼開發功能。Java應用非常容易被反編譯,Android自然也不例外。只要利用apktool等類似的反編譯工具,就可以通過安裝包擷取原始碼。Google為了保護開發人員的智慧財產權,為Android提供了ProGuard混淆方案,以增加反編譯後源碼閱讀,但對於Android開發老司機和逆向工程師來說,解讀還原出原始碼只是時間問題。
ProGuard是針對Java應用的保護,並不是專門針對Android應用的,Android雖然使用Java開發,但是畢竟不是跑在JVM上,所以安裝包結構和普通的Java應用還是區別多多。如果你對免費的ProGuard放心不下,可考慮試試付費的混淆方案DexGuard,除了擁有ProGuard的功能外,還包含資源混淆,字串加密,類加密和dex檔案分割等。
- 關於ProGuard,詳見:https://www.guardsquare.com/en/proguard
- 關於DexGuard,詳見:https://www.guardsquare.com/en/dexguard
- 關於反編譯工具,詳見我一篇舊文:那些值得你試試的Android競品分析工具
雖然代碼混淆是最為基礎的保護措施,不過國內仍有不少應用還是裸奔的,其中還包括一些大廠應用(此處不表)。
簽名校正
Android黑產裡面,有一個叫做二次打包,也稱為重打包。即通過反編譯正版應用後,可以獲得smali源碼,往其中注入代碼或者修改相應商務邏輯後,再利用新的簽名進行重新打包,並發布到應用市場去,很多無良開發人員就是通過這種方式去破解一些付費應用或者往其中注入廣告代碼來獲利。簡單梳理一下重打包的基本流程:
- 對正版應用用apktool類逆向工具進行解包;
- 在某處地方注入smali代碼;
- 利用IDE產生簽名檔案,再通過jarsigner進行簽名;
- 上傳應用市場;
為了與二次打包做對抗,可以在應用內的關鍵功能入口增加校正簽名的檢測,如果發現應用簽名非正版,則強制關閉應用或者限制使用者使用。加簽名校正代碼時,可以考慮:
- 在JNI層中加校正代碼,相比在Java層的代碼,JNI層的逆向難度更大;
- 如果要在Java層加校正代碼,不要在一個地方暴露一段長串字串,對於逆向工程師是來說,這是非常明顯的提示。可以考慮將字串打散存放在各處,這樣會增加破解分析的難度;
當然,不要以為放在JNI就高枕無憂,對於JNI層,同樣可以進行代碼注入,來暴力破解你簽名校正的邏輯,只不過相比Java層的,JNI層所需成本更高,這樣也就能攔截掉一部分逆向人員的歪主意。
加殼
加殼的原理是通過加密原應用的安裝包中的dex檔案,其主要操作方式大致如下:
- 準備要進行加殼的原應用安裝包(以下簡稱原apk)、用於做殼的安裝包(以下簡稱殼apk);
- 對原Apk進行拆解擷取各個部分,並將dex檔案進行演算法加密(以下簡稱加密原dex);
- 將加密原dex和殼Apk中的dex進行組合,合并成為新的dex檔案;
- 利用特製的打包工具合并產生加密後的apk;
這種通過隱藏dex檔案的方式加殼方式,最終是利用ClassLoader在記憶體中解密並進行動態載入運行。而如果是修改dex檔案的加殼方式,其主要是抽取DexCode中的位元組碼指令後用零去填充,或者修改方法屬性等操作,其修複時機則是運行時在記憶體中做相應的修正工作。
通過加殼得到的安裝包如果不進行脫殼操作,逆向人員就無法拿到真正的dex檔案,也就無從分析。這裡可以看看使用360加固的一個應用的結構在沒脫殼前的安裝包結構
只有寥寥幾個類,而正真的安裝包中的dex檔案則被藏起來了,這進一步加大了逆向的難度。關於加殼,市面上已經有很多成熟企業加固方案可以使用,如梆梆安全、愛加密、360加固保等,如果不是專門研究這塊的開發人員去自行開發一套加殼方案,顯然不太現實。
加殼也只是提高被逆向的門檻,對於功力不夠的逆向開發人員而言,只能就此作罷,而對於逆向老鳥來說,脫殼同樣這是外包時間問題罷了。此外,對應用加殼還要留意平台相容性問題,如此前某著名加固產品就出現過在ART虛擬機器不相容問題,以及將會影響項目使用某些熱修複技術。
反動態調試
你是不是曾以為沒有拿到原始碼就不可以調試Android應用了?然而並不是,只要反編譯後拿到smali代碼工程,再加上smalidea調試神奇,分分鐘在Android Studio調試應用給你看,具體操作並不複雜,可以參照我文末提供的資料。即使你把核心代碼放到了JNI層,我也可以祭出神器IDA Pro繼續調試給你看,更何況,實際開發中能放進JNI層實現的核心代碼實在有限。
為了對抗動態調試,可以考慮在源碼中隨意穿插相關的檢測代碼,在檢測到動態調試時,直接進程自殺,異常退出虛擬機器,大致實現如下:
/** * 檢測動態調試 */ public void detectedDynamicDebug(){ if (!BuildConfig.DEBUG){ if (Debug.isDebuggerConnected()){ //進程自殺 int myPid = android.os.Process.myPid(); android.os.Process.killProcess(myPid); //異常退出虛擬機器 System.exit(1); } } }
以上只是一個簡單的例子,市面上很多加固產品做了更多的動態調試對抗措施。
資料保護
資料保護這個主要例舉以下幾點:
- 不要在客戶的存放登入密碼(即使你加密了),最好採用token的形式;
- 資料轉送記得加密;
- 重要資料存放內建儲存中,不要存放在外置儲存;
- 加密存放在xml和資料庫中的重要訊息;
資源保護
資源保護同樣可以提高逆向分析的難度,但個人覺得只對逆向小白有效,可以考慮引入試試,目前比較知名的方案就是和美團兩家的了,具體參見:
- 安裝包立減1M--Android資源混淆打包工具
- 美團Android資源混淆保護實踐
總結
應用安全的攻防就是這麼一個相愛相殺又相輔相成的過程,對於用戶端能做到的安全防範也是有限的,更多的還是應該結合後台業務分析來實現相應的對抗機制,對於中小企業而言,沒有專門的安全人員去研究對抗方案,選擇市面上成熟的加固方案是一個不錯的選擇。而對於大企業來說,內部早已有了自己的資訊安全中心,自然也有自己的一系列對抗方案,包括在後端產生每個使用者的畫像來判別使用者類型等等。大致就是這麼些了,文末附上一些不錯的資料,希望本文能對你有所啟發!
Android 應用安全風險與防範