Xposed模塊開發基本方法記錄

  因爲某些課程實驗的要求,須要經過xposed框架對某應用進行hook操做,筆者選用了開源且免費的xposed框架進行實現。雖然網上存在一些利用xposed實現特定功能的文章資源,但大多均將xposed模塊的構建做爲一個小節內容一筆帶過,並且介紹的內容隨着考慮的因素、使用的編輯環境不一樣也大有區別,使得筆者在實際構建過程當中每每提心吊膽,出現了錯誤也不知道如何去改正。故而這裏特將筆者最近摸索和學習到的簡單xposed構建的知識記錄,以供查閱和參考。php

 

Xposed 框架html

  想要使用Xposed模塊實現特定的功能,必須依賴Xposed框架,正如 apk 的運行須要Android系統提供支持同樣,Xposed模塊任務的完成也離不開Xposed框架的支持,Xposed框架提供了Xposed模塊運行所必需的環境和功能接口,同時也能夠對系統上已安裝的模塊進行禁用、卸載等管理。故而在想經過Xposed模塊完成必定任務以前,必須安裝Xposed框架。java

  Xposed框架Installer下載地址:http://repo.xposed.info/module/de.robv.android.xposed.installer,安裝的過程可參考網絡資料。android

  注意:因爲Xposed框架安裝時須要將系統文件夾/system/bin的部分文件進行替換和備份,故而手機須要具有root權限git

 

Xposed 模塊github

  下面以Android Studio 3.0.1爲例,總結下簡單的Xposed模塊的編寫所需的配置和注意事項。api

  項目建立微信

  Xposed模塊其實是做爲一種較爲特殊的apk安裝在系統上,因爲Xposed 模塊的功能一般藉助於其餘應用和系統資源實現,其通常沒有應用界面,故而建立一個沒有活動的項目便可。網絡

  A.在Android Studio中,點擊 file -> new -> new project 進行新項目的建立。指定應用名稱、公司域名、存儲位置和包名等信息,這裏須要注意應用名和包名這兩個名字;app

  

  B.勾選 Phone and Tablet 選項,選擇該 Xposed 模塊( 實際就是apk)將要運行的 Android 環境所對應的 API。注意這裏的API指定的是Android環境與apk之間交互的接口,只有該API與以後apk實際運行的Android環境相匹配,apk才能正確的安裝和運行。如筆者的 Xposed 模塊將要運行在 Android 4.4上,則應該選擇 Android 4.4 對應的API 19.

  

  C.在接下來的界面中,選擇「 add no activity 」即不添加活動( Xposed 模塊不須要活動 ),便可完成項目的建立。

 

  項目配置

  Xposed模塊被視爲一種特殊的apk,故而在建立項目以外,還須要針對其進行 Xposed 模塊相關的配置。

  A. 切換目錄結構。點擊界面左上方的豎式 Project,展開項目界面,將項目結構從 Android 切換至 Project 模式,方便以後的編輯;

  

  B. 添加 Xposed API依賴。Xposed 模塊的功能借助 Xposed 框架實現,Xposed 模塊經過對應的 Xposed 框架 API 來使用 Xposed 框架提供的功能。想要使用 Xposed 框架 API,則必須提供對應的庫( 名爲 XposedBridge API jar)的路徑等信息。(如下信息來自 Using the Xposed Framework API )

    *針對 Android Studio

    Android Studio 中使用gradle進行項目的構建,故而想要使用 Xposed 框架 API 對應的庫,則須要在 gradle 的配置文件中進行指定。在 應用名(test) -> app -> build.gradle 中加入如下內容:

1      repositories {  //一般新項目的 build.gradle 中不包含有repositories塊,直接在空白處增長1-3行便可
2  jcenter();   } 3  
4      dependencies {  //一般 build.gradle 文件中已包含dependncies塊,因此只需將第6行的內容添加進已有的 dependencies 中便可
5          provided 'de.robv.android.xposed:api:53'
6        provided 'de.robv.android.xposed:api:53:sources'   //該行是可選的,用於下載API相關的文檔等信息
7  }

    其中,第2行表示將 jcenter 做爲代碼倉庫,可在上面引用開源項目,而第 6 行則指定引用項目的項目名和版本信息。

    第6行的聲明須要注意兩點:  

    a) 使用 provided 關鍵字而不是 compile,後者會將引用的 Xposed 框架 API 類打包至生成的 apk 中,而這些類在安裝好的 Xposed 框架中是已經存在的,因此可能會產生衝突,而 provided 關鍵字則僅保留對 API 的引用,實現具體功能的類則由安裝好的 Xposed 框架提供;     

    b)使用系統對應的 Xposed 框架 api 版本,不一樣的 Xposed 框架 API 在不一樣的 Android 環境中發揮做用。如Android 4.x 環境則只能選擇 API 53。

    

    *針對 eclipse

    eclipse 環境下沒法經過指定 jcenter 中的開源項目來實現對其的引用,因此必須在實際的項目中手動添加所需引用的庫文件 XposedBridge API jar 的路徑,在這裏手動下載所需的 API 版本,將其複製到項目的文件夾下( 注意不要放置在項目自己已經有的 lib / libs 文件夾下,緣由與Android Studio環境下使用 provided 而不是 compile 一致 ),選中 jar 包 右鍵 -> Build Path -> add to build path 便可。

  

  C. Android Studio 環境下須要禁用 Instant run 。在 File -> Settings -> Build, Execution, Deployment -> Instant Run 中取消其勾選,不然源程序中的類會由一個 stub 應用加載,而不是直接包含在 apk 文件中,而 Xposed 框架目前沒法處理這樣的狀況。

  D. 修改 AndroidManifest.xml 文件中的屬性。在 應用名(test) -> app -> src -> main 文件夾中找到 AndroidManifest.xml,修改其中的屬性,使得咱們最終生成的 apk 可以被 Xposed 框架識別。請保證最終文件的部份內容爲如下格式。

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" >    // App相關的信息

    <meta-data android:name="xposedmodule"    //標誌該 apk 爲一個 Xposed 模塊,供 Xposed 框架識別
            android:value="true" />
    <meta-data android:name="xposedminversion" android:value="53" />       //xposed最小版本號,請與(2)步中選用的api版本保持一致
    <meta-data android:name="xposeddescription" android:value="hook a function" /> //針對該模塊的描述,會在Xposed框架的模塊管理界面中顯示出來,便於模塊管理

    </application>

  完成上述步驟後,則可將項目文件打包成 apk ( Android Studio 下打包 apk 的簡單步驟能夠參見這裏),並在手機中安裝。安裝成功後,在 Xposed 框架的模塊管理界面會出現該模塊對應的管理項,證實對 Xposed 模塊的配置是成功的。勾選對應的模塊,並重啓設備,重啓以後該模塊則開始發揮功能。固然目前咱們並無實現任何功能。

  

  簡單示例

  在完成 Xposed 框架的配置後可在該項目中進行框架功能的編寫。在 應用名(test) -> app -> src -> main -> java 目錄下,能夠看到 Android Studio 已經自動根據咱們在建立項目時指定的包名生成了一個包( package )的條目,如筆者項目中的包名爲 xposed.test(見建立項目時的界面截圖),選中該包右鍵 -> new -> java  ->class ,建立本身的一個 class ,如 test.class 。用戶可在該 class 中實現簡單的xposed hook功能。

  ( 如下部分不涉及具體的實現原理,僅提供函數的簡單功能的描述,更多關於Xposed 框架API的功能可在這裏查看)

  一個 Xposed 模塊能夠有多個不一樣的入口,其中實現的方法既能夠在 Android 系統啓動時被調用,也可在一個應用程序包被加載時被調用,想要在不一樣的時期被調用,則該功能類須要實現不一樣的接口。

 Xposed公共接口 package:de.robv.android.xposed.IXposedHookZygoteInit interface :IXposedHookZygoteInit   //在Android系統啓動時被調用,做用於初始的zygote進程,可用於實現應用於全部應用的hook

    package:de.robv.android.xposed.IXposedHookLoadPackage interface:IXposedHookLoadPackage  //當指定應用被加載時被調用,通常用於hook特定應用的方法

    package:de.robv.android.xposed.IXposedHookInitPackageResources interface:IXposedHookInitPackageResources //指定應用的資源進行初始化時被調用,通常用於資源的替換

   

  以實現 IXposedHookLoadPackage 接口的模塊爲例,實現一個簡單的hook功能。

  一般使用 findAndHookMethod 方法來定位待 hook 的類中的方法(官方解釋在這裏)

 findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)  className:被hook的方法所在類的完整名稱,包括 包名 + 類名  classLoader:可經過 lpparam.classLoader 得到 methodName:被hook的方法的名,注意若有混淆,則應該用混淆後的名字 object... 與爲被hook的方法的參數對應 Callback  :指定該方法被調用時,須要被執行的回調

  例如,想要hook以下代碼,即hook包 com.test.example 中的類 a 下的 b 方法

package com.test.example public class a{ public int b(String s, int i, MyClass m) {} } 

  則對應的 findAndHookMethod方法應該寫做

findAndHookMethod("com.test.example.a", lpparam.classLoader,"b", String.class, int.class, "com.test.example.MyClass", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { do somthing } }); 這裏須要注意: (1)對於待hook函數中的java自帶類型的參數,如 int 和 String,則應使用 int.class 和 String.class 做爲findAndHookMethod的參數 (2)若待Hook函數中包含有形如 MyClass 這樣的自定義類型的參數,則直接使用該類型的完整路徑名便可,如 "com.test.example.MyClass"

  在 findAndHookMethod 方法的參數中,直接定義了一個 XC_MethodHook 回調,其中通常有兩個方法可供使用者從新定義。

   @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // 該方法在被hook函數以前被調用
 } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { // 該方法在被hook函數以後被調用
      }

 

  如下代碼實現了微信的一個日誌函數的簡單 hook 。

 1 package xposed.xposed_wechat_log;  //實現的類所在的包
 2 
 3 import android.util.Log;       //系統提供的Log方法的包
 4 import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;  //findAndHookMethod方法所在的包
 5 import de.robv.android.xposed.IXposedHookLoadPackage;             6 import de.robv.android.xposed.XC_MethodHook;  7 import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;  8 
 9 public class test implements IXposedHookLoadPackage {  //test類實現了IXposedHookLoadPackage接口
10  @Override 11     public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {  // handleLoadPackage 在任意包被加載時被調用,參數lpparam,包含有加載的 app 的信息
12         if ( lpparam.packageName.equals("com.tencent.mm")) {             // 可經過 lpparam 中包含的包信息對包進行篩選,如這裏表示 com.tencent.mm 包加載時,才執行下一步操做
13     findAndHookMethod("com.tencent.mm.sdk.platformtools.x",lpparam.classLoader, "d" , String.class, String.class, Object[].class, 14             new XC_MethodHook() { 15  @Override 16                 protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 17                     String str0  = (String) param.args[0];              //可經過 param.args[i]得到 hook 方法的參數
18                     String str1  = (String) param.args[1]; 19                     Object[] obj2= (Object[]) param.args[2]; 20                     String  str = obj2 == null ? str1 : String.format(str1, obj2); 21 
22                     if( str==null) 23                         str = ""; 24 
25                     Log.e( "Xposed_hook_d"+str0,str); 26                     super.beforeHookedMethod(param); 27  } 28  }); 29      } 30   } 31 }
simple_hook

  

  完成上述模塊功能的編寫後,需在 應用名(test) -> app -> src -> main 目錄下新建一個 assets 目錄,並在該目錄下創建一個名爲 exposed_init 的文本文件。該文件中記錄模塊中全部實現了Xposed 功能接口的類的完整路徑名,每一行書只寫一個這樣的路徑。

  如在上述實例模塊中,test 類實現了接口 IXposedHookLoadPackage,則 exposed_init 文件中應該有如下內容:

xposed.test.test  //其中 xposed.test 爲包名,test爲實現接口的類名

  全部實現了 Xposed 接口的類均要在該文件中記錄,以供 Xposed 框架進行處理。

  以後便可打包完成的項目,將其安裝至設備上進行驗證了。

 

參考資料:

  1. [TUTORIAL]Xposed module development詳細的xposed模塊開發示例

  2. Using the Xposed Framework API關於如何在模塊中使用Xposed框架提供的API

  3.  Development tutorial簡單的xposed模塊示例

相關文章
相關標籤/搜索