文章出處

基于代理Application機制的Anddroid應用加殼方法。殼是指一個程序的外面再包裹上另外一段代碼,保護里面的代碼不被非法修改或反編譯的程序。它們一般都先于程序運行,拿到控制權,然后完成它們保護軟件的任務。對于Android APP來說,所有的實現邏輯都集成于DEX文件中,DEX文件是一個APP的核心所在,因此保護DEX文件被逆向或者修改尤其重要。Android應用的DEX加殼過程如下:

\

盡管上述DEX加殼過程中,關于如何對DEX進行加密或者利用其它方法對其進行處理的方法有很多,但是通過自定義DexClassLoader替換原DexClassLoader,并通過后者來加載被保護代碼是所有加殼程序都必須實現的必經之路。本文重點介紹的就是通過一種代理Application的機制把原DexClassLoader替換成用自定義的DexClassLoader,并通過它來加載被保護DEX代碼從而達到正常運行加殼后的Android應用。

Android應用中有且僅有為一個Application組件,并且Application組件的生命周期從應用啟動開始到應用退出結束, 與Android的整個應用的生命周期是相同的,因此通過在Application組件外面包裹一層殼來隱藏整個應用的DEX文件,是最簡單且有效的一種方法。

顯然,系統的DexClassLoader已經不能用來加載被保護后的DEX文件,因此我們必須定義一個自定義的DexClassLoader來完成加載被保護后的DEX文件。所有的Class包括自定義Application組件(下文一律稱為MyWrapperProxyApplication)都必須被自定義的ClassLoader所加載。為了要實現這個需求,需要在MyWrapperProxyApplication被加載之前,必須用自定義的DexClassLoader先替換掉API層的默認的DexClassLoader,否則MyWrapperProxyApplication就會被默認的DexClassLoader加載。但這會產生一個悖論,因為MyWrapperProxyApplication組件的onCreate函數是整個Android應用的入口,MyWrapperProxyApplication被加載之前,沒有任何應用代碼可以運行,因此替換ClassLoader無法辦到。基于代理Application框架就是用來解決這類問題的。

首先我們需要修改AndroidManifest.xml文件:

在我們這個框架里,加殼后的應用一共有兩個Application對象,一個是我們自己自定義的MyWrapperProxyApplication,另外一個就是被保護后的Application對象,我們姑且稱之為OriginalApplication,首先我們需要修改Android應用的AndroidManifest.xml文件對新加的Application組件進行重新定義。老的AndroidManifest.xml文件定義:

android:name=".MyApplication"

android:icon="@drawable/icon"

android:label="@string/app_name" >

修改后AndroidManifest.xml文件定義為:

android:name=".MyWrapperProxyApplication"

android:icon="@drawable/icon"

android:label="@string/app_name" >

android:name="ORIGINAL_APPLICATION_CLASS_NAME"

android:value=".MyApplication" >

....

我們通常認為Application:onCreate()函數是整個應用的入口,所以我們直接在Application:onCreate函數里面生成自定義的DexClassLoader即可,但當應用注冊有ContentProvider的時候,這并不正確的。ContentProvider:onCreate()調用優先于Application:onCreate()函數的調用,但是自定義的DexClassLoader也必須把ContentProvider組件也加載到內存里面,所以如果直接就在Application:onCreate()里面替換系統默認的DexClassLoader是行不通的。

幸好,我們還有另一個方法:attachBaseContext()。Android的幾個主要組件Application、Activity和Service都是ContextWrapper的子類。ContextWrapper一方面繼承了Context,一方面又包含了一個Context對象(稱為mBase),對Context的實現為轉發給mBase對象處理。這一個聽起來很繞的設計,是為了對這些組件中的Context功能做延遲初始化(delay init)的處理。其類圖關系如下所示:

\

ContextWrapper完成這個延遲化處理的方法就是attachBaseContext()。可以這樣說,Application對象在剛剛構造完成時是“殘廢”的,訪問所有Context的方法都會拋出NullPointerException。只有attachBaseContext()執行完后,它的功能才完整。在ContentProvider:onCreate()中,我們知道Application:onCreate()還沒有運行,但已經可以使用getContext().getApplicationContext()函數獲取Application對象,并訪問其Context方法。顯然,Android的API設計者不能允許此時獲取的Application是“殘廢”的。結論是Application:attachBaseContext()必須要發生在ContentProvider:onCreate()之前,否則API將出現BUG;無論Android的系統版本如何變化,這一點也不能改變。

看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170220/104373.html

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()