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個主要步驟):
- 將XposedBridgeApi.jar匯入到目錄下,同時Add As Library…
- 修改build.gradle,將compile改為provided
- 在AndroidManifest.xml中新增meta-data元素
- 新建主類,實現IXposedHookLoadPackage介面,重寫handleLoadPackage方法
- 在main目錄下新建assets資料夾,然後在assets中新建xposed_init檔案,寫入packagename+主類
然後又通過hook一個activity跳轉的應用,示例了使用Xposed進行hook的基本用法。
在下一篇文章中將會帶來“Android某狗輸入法使用者個人詞庫的提取”,來示範Xposed框架在實際應用中的使用。