1. 程式人生 > >Xposed框架開發入門(二)--使用Xposed框架實現Activity跳轉攔截

Xposed框架開發入門(二)--使用Xposed框架實現Activity跳轉攔截

接著上一篇Xposed框架入門開發(一)繼續,在上一篇中已經說了,第二篇主要介紹的是Xposed框架開發的基礎的應用。在接下來的文章中,主要以一個Activity的跳轉APP為例, 示範Xposed框架的基本使用方法。

1、編寫一個簡單的Activity跳轉的應用

在Android Studio中建立工程XposedDemo,在app中新增兩個Activity。首先新建在layout中新建layout1.xml和layout2.xml,向每個layout中新增一個TextView,標明其對應的activity。如下為layout1.xml的程式碼:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.zhayh.xposeddemo.Layout1Activity">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id
="@+id/tv_01" android:text="Activity_01" android:textSize="40sp" android:layout_centerInParent="true"/>
</RelativeLayout>

效果如下:
這裡寫圖片描述
新建兩個Activity:Layout1Activity和Layout2Activity,直接在onCreate()的setContentView設定layout1和layout2。

在activity_main.xml中設定兩個button,通過這兩個button分別跳轉到activity1和activity2。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.zhayh.xposeddemo.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_01"
        android:text="跳轉Activity_01"
        android:layout_centerInParent="true"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_02"
        android:text="跳轉Activity_02"
        android:layout_below="@id/btn_01"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

效果如下:
這裡寫圖片描述

此時在MainActivity中設定對應的點選事件。這裡先新建一個util包,在其下新建一個ButtonListener.java類,該類實現了OnClickListener介面,重寫了onClick方法,用來設定點選事件,程式碼如下:

public class ButtonListener implements View.OnClickListener {
    private Context context = null;
    private Class deste_activity_class = null;

    public ButtonListener(Context context,Class dest_activity_class) {
        this.context = context;
        this.deste_activity_class = dest_activity_class;
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent(context,deste_activity_class);
        context.startActivity(intent);
    }
}

這個類非常重要,因為我們接下來的跳轉攔截時就是對點選事件進行hook,修改目標activity的引數,達到跳轉到我們設定的activity中,從而實現跳轉攔截。

然後在MainActivity.java中設定點選事件,程式碼如下:

public class MainActivity extends Activity {
    private Button btn_01 = null;
    private Button btn_02 = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_01 = (Button) findViewById(R.id.btn_01);
        btn_02 = (Button) findViewById(R.id.btn_02);

        btn_01.setOnClickListener(new ButtonListener(MainActivity.this,Layout1Activity.class));
        btn_02.setOnClickListener(new ButtonListener(MainActivity.this,Layout2Activity.class));
    }
}

OK,到這裡我們Activity跳轉的應用就完成了,執行程式,結果如下:
這裡寫圖片描述
可以看到點選“跳轉Activity_01”後跳轉到Activity_01,點選“跳轉Activity_02”後跳轉到Activity_02.
同時最終專案目錄結構如下:
這裡寫圖片描述

2、Xposed模組基本配置

1、新建Xposed模組專案,在XposedDemo中New Module為“hookjump”,選擇Add No Activity(我們這裡的Xposed模組不需要Activity),完成專案建立。
這裡寫圖片描述

2、在Module中建立一個lib資料夾,然後將下載好的XposedBridgeApi.jar(我這裡為XposedBridgeApi-54.jar)拷貝到該目錄下,然後右鍵“Add As Library…” 。
這裡特別注意是新建一個lib資料夾而不是直接放到工程中已經建立好的libs資料夾,否則不會hook成功。

3、在build.gradle中將在dependencies下自動生成的compile files(‘lib/XposedBridgeApi-54.jar’)改為provided files(‘lib/XposedBridgeApi-54.jar’)
這裡寫圖片描述

4、在AndroidManifest.xml中新增meta-data元素:

        <!--新增標識-->
        <meta-data
            android:name="xposedmodule"
            android:value="true"/>
        <!--在Xposed框架模組中的描述資訊-->
        <meta-data
            android:name="xposeddescription"
            android:value="Hook Activity Jump Method"/>
        <!--匯入jar的最低版本-->
        <meta-data
            android:name="xposedminversion"
            android:value="54"/>

5、新建主類Main,該類實現了IXposedHookLoadPackage介面,重寫了public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {}方法。我們的Hook的主要操作就是在該方法中進行的。如下所示:
這裡寫圖片描述

6、在main目錄下建立一個assets資料夾,然後在assets中新建xposed_init檔案,向其中寫入包名+類名,如:
這裡寫圖片描述
該檔案是Xposed模組的入口,其中宣告的“packagename+主類”便是宣告需要載入到XposedInstaller 的入口類。

到此時一個Xposed模組基本框架就完成了,接下來要進行的就是Hook核心程式碼的編寫。
專案的目錄結構如下,所有需要改動的地方都在圖中標識出。
這裡寫圖片描述

3、尋找Hook點,Hook實現Activity跳轉攔截

在對一個專案進行hook時,我們首先得知道我們要hook的點是哪裡,然後才能進行接下來的操作。首先我們對app進行分析,可以發現點選跳轉按鈕時會進行Activity間的跳轉,那麼控制Activity跳轉的程式碼肯定在Button 的點選事件中,對跳轉按鈕的點選事件進行分析:
這裡寫圖片描述

這裡寫圖片描述
可以發現,其跳轉的目標Activity便在自定義的OnClickListene的構造方法的第二個引數這裡設定 。所以只要在Activity跳轉時Hook ButtonListener類的構造方法,將其dest_activity_class改為其他的activity的class便可以實現跳轉攔截。

我們這裡演示使用hook將兩個button的目標activity互換,即點選“跳轉Activity_01”後跳轉到Activity_02,點選“跳轉Activity_02”後跳轉到Activity_01.

所以需要在Main方法中找到ButtonListener的構造方法對其進行hook,修改相應的引數。我們這裡使用XposeHelper類的findAndHookConstructor方法來hook ButtonListener類的構造方法,從而修改dest_activity_class.

首先點進XposeHelper中檢視findAndHookConstructor方法的定義:
這裡寫圖片描述
可以看到它的引數列表為:

/**
*1、String className:要hook的類的全限定名
*2、ClassLoader classloader:當前的ClassLoader
*3、Object... parameterTypesAndCallback:要hook的構造方法的引數列表
*/

所以,我們的Hook函式如下:
這裡寫圖片描述
其中,使用if(loadPackageParam.packageName.equals(“com.zhayh.xposeddemo”))來找到要hook的應用,然後使用XposedHelpers.findAndHookConstructor進行hook。

新增Hook具體程式碼,程式碼邏輯為:

if(dest_activity_class == Activity_01.class){
    dest_activity_class = Activity_02.class
}else if(dest_activity_class == Activity_02.class){
    dest_activity_class = Activity_01.class
}else{
    error
}

具體程式碼為:
這裡寫圖片描述
其中,由於在進行dest_activity_class = Activity_01(2)_calss時,需要將新的Activity的Class傳給param.args[1],所以首先應該找到新Activity的Class。對於找到一個只知道類名的類的Class,需要使用XposedHelpers類的findClass(String className,ClassLoader classloader)方法來找到對應的Class。

OK,到這裡整個Hook模組便已經編寫完畢。執行程式,啟用模組後重啟,開啟原app,執行效果如下:
這裡寫圖片描述
可以看到成功執行後點擊“跳轉Activity_01”後實際跳轉到了Activity_02,點選“跳轉Activity_02”後實際跳轉到了Activity_01.
同時,DDMS中的Log輸出如下:
這裡寫圖片描述
可以看到我們已經成功的攔截到了原app的Activity的跳轉,同時將目標Activity改為新的Activity。

總結

在這片文章中,主要介紹了Xposed模組開發的基本步驟(5個主要步驟):

  1. 將XposedBridgeApi.jar匯入到目錄下,同時Add As Library…
  2. 修改build.gradle,將compile改為provided
  3. 在AndroidManifest.xml中新增meta-data元素
  4. 新建主類,實現IXposedHookLoadPackage介面,重寫handleLoadPackage方法
  5. 在main目錄下新建assets資料夾,然後在assets中新建xposed_init檔案,寫入packagename+主類

然後又通過hook一個activity跳轉的應用,示例了使用Xposed進行hook的基本用法。

在下一篇文章中將會帶來“Android某狗輸入法使用者個人詞庫的提取”,來示範Xposed框架在實際應用中的使用。