Android中Apk加固之Dex文件的加密與解密

參考文檔:https://developer.android.google.cn/studio/build/multidex.html#keep 

1、由文檔中可以知道 瞭解到 在Android5.0之前我們使用的是Dalvik虛擬機,默認情況下,Dalvik 限制應用的每個 APK 只能使用單個 classes.dex 字節碼文件。要想繞過這一限制,您可以使用 Dalvik 可執行文件分包支持庫,它會成爲您的應用主要 DEX 文件的一部分,然後管理對其他 DEX 文件及其所包含代碼的訪問。

當然,當5.0以後,Android 5.0(API 級別 21)及更高版本使用名爲 ART 虛擬機的運行時,後者原生支持從 APK 文件加載多個 DEX 文件。ART 在應用安裝時執行預編譯,掃描 classesN.dex 文件,並將它們編譯成單個 .oat 文件,供 Android 設備執行。因此,如果您的 minSdkVersion 爲 21 或更高值,則不需要 Dalvik 可執行文件分包支持庫。

由於我們現在應用基本都在5.0以後的版本,所以大都支持多dex分包支持了,但是也會有一些其它的設備,比如智能家居等有使用低版本的時候,可能會遇到64K的問題,爲了正常使用多分包功能,可以參考上面的文檔中介紹的如下方式:

修改模塊級 build.gradle 文件以啓用 Dalvik 可執行文件分包,並將 Dalvik 可執行文件分包庫添加爲依賴項,如此處所示:

android {
    defaultConfig {
        ...
        minSdkVersion 15 
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.3'
}

2、我們一般的apk是這樣的,直接打開apk是可以看到裏面的源碼的,如下圖所示

這樣對大家來說就不安全,我們所要做的就是把我們的apk中的dex文件加密,讓別人就算拿到我們的apk裏面啥也看不到。如下圖所示,點擊加密之後的apk,裏面啥也沒有,一個代碼都看不到,這就是我們要做的:

2、具體怎麼做呢?請看下圖介紹

上圖中左邊是我們未加密的apk打開之後顯示的文件結構,我們需要一個proxy代理application  以及一個 加密所用的Tools ,用tools來給左邊的兩個dex進行加密,然後在把加密之後的文件和左邊其它的文件一起打包成apk 這樣別人就看不到我們的源碼了,但是新的文件的dex文件用戶是無法運行的,這個時候,我們就需要一個proxy 的application,把我們新打包的apk所有內容交給代理application,然後讓代理application去和Android系統對接,因爲系統可以加載dex文件的,所以這個時候,我們的代理application要做的就是把拿到的加密的apk中的dex文件進行解密,然後在交給系統處理。

 

3、我們要先了解自己寫的代碼是如何被加載到內存的,可以在MainActivity中用以下代碼查看:

Log.d("wwy",getClassLoader().toString());    經過運行發現打印信息爲:dalvik.system.PathClassLoader  

我們在系統源碼中查找這個PathClassLoader ,查看父類 BaseDexClassLoader

我們通過Android系統源碼找到  PathClassLoader ------>  BaseDexClassLoader  ----->  findClass()方法  -----> pathList.findClass() 方法    ,接着查看 pathList 類中都是什麼,發現這個類中的方法 就是 findClass(String name,List<Throwable> suppressed) ;它通過循環遍歷DexFile ,其實這就是獲取dex文件,其實系統所有的dex文件都是要經過這裏處理的

所以關鍵來了,既然所有的dex文件都是通過這裏處理,也就是 dexElements  , 它本身就是一個數組,我們只需要通過反射拿到這個數組,接着我們通過代碼把我們自己的解密之後的dex文件放到我們定義的一個數組中,然後把我們的數組和系統的dex文件數組合併在一起,交給系統去處理。

這裏我們在看系統的dex文件數組 dexElements 是怎麼初始化的呢?通過查看系統源碼,發現如下,

那麼我們通過反射拿到這個方法,就可以拿到系統的dex文件數組了,然後再把我們的數據和系統合併後在賦給系統裏面的dexElements 這樣就把dexElements更新後,這樣我們的dex文件就加載到android裏面運行了。

好了具體的思路上面就介紹到這裏,下面開始實現這個功能。

4、我們新建一個android project ,然後,在項目裏面Create New Module 選擇 Android Library   ,這就是給我們代理的application ,命名爲:proxy_core ;然後還需要一個加密工具,在項目中 Create New Module 選擇 Java Library  這個java library不需要我們運行時處理,它直接在我們編譯的時候就進行加密,這就是爲什麼創建的是java library ,這命名爲:proxy_tools  建好之後,記得把這個proxy_tools 添加到項目中,如下:

添加編譯完之後,在app的build.gradle中會自動如下所示:

好了,下面就開始寫代碼了!

具體的在下個博客中詳細介紹。先下班了!哈哈。。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章