1. 程式人生 > >Android Hook框架Xposed入門

Android Hook框架Xposed入門

轉:http://chendd.com/blog/2016/05/15/learn_xposed/

一.基礎知識

       Xposed是Android平臺上較為出名的一個開源框架。在這個框架下,我們可以載入很多外掛App,這些外掛App可以直接或間接操縱普通應用甚至系統上的東西。Xposed原理上是Hook Android 系統的核心程序Zygote來達到修改程式執行過程和結果。講到這裡,可能有人會問什麼是Hook?什麼是Zygote?

  • Hook(鉤子),鉤子實際上是一個處理訊息的程式段,通過系統呼叫,把它掛入系統。每當特定的訊息發出,在沒有到達目的視窗前,鉤子程式就先捕獲該訊息,亦即鉤子函式先得到控制權。這時鉤子函式即可以加工處理(改變)該訊息,也可以不作處理而繼續傳遞該訊息,還可以強制結束訊息的傳遞。

  • Zygote(Android程序名),Android系統是基於Linux核心的,而在Linux系統中,所有的程序都是init程序的子孫程序,也就是說,所有的程序都是直接或者間接地由init程序fork出來的。在Android系統中,所有的應用程式程序以及系統服務程序SystemServer都是由Zygote程序孕育(fork)出來的,這也許就是為什麼要取名英文字意為受精卵的Zygote原因吧。

       由於Xposed框架Hook了Android的核心程序Zygote,而其他應用啟動都是從Zygote程序fork而來,就夠達到針對系統上所有的應用程式程序的Hook。

二.Xposed簡介

       rovo89大神github主頁,如圖所示

       image

主頁大致可以看出,xposed主要由三個專案來組成的

  • Xposed,Xposed的C++ 部分,主要是用來替換/system/bin/app_process,併為XposedBridge提供JNI方法
  • XposedBridge,Xposed 提供的jar檔案,app_process啟動過程中會載入該jar包,其他的Modules的開發都是基於該jar包
  • XposedInstaller,Xposed的安裝包,提供對基於Xposed框架的Modules的管理

xposed目前已逐步支援ART虛擬機器,相容android 5.0以上版本

三.Xposed使用

       在Android 4.0以上Android裝置(需root許可權,建議直接用模擬器)安裝XposedInstaller

啟動XposedInstaller點選 【框架】

image

點選 【安裝/更新】 並重啟,再點選框架看到看到 啟用底下兩個都是綠色 代表框架安裝成功

image

我們可以點選【下載】來檢視熱門外掛進行安裝

安裝完外掛點選【模組】進行勾選啟用

之後還需重啟,外掛才能生效。大家可以自己下載幾個外掛玩玩,本文重點不在這,就不演示了。

四.編寫外掛

這裡我們hook自己編寫的一個小的登入app來獲取使用者名稱密碼。

介面比較簡單,輸入使用者名稱密碼點選登入彈出使用者輸入的密碼

image

介面程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public EditText et_username;
  // 屬性為private 時普通反射獲取不到該物件
  // private  EditText et_password;
  public EditText et_password;
  public Button bt_login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_username = (EditText) findViewById(R.id.et_username);
      et_password = (EditText) findViewById(R.id.et_password);
      bt_login = (Button) findViewById(R.id.bt_login);
      bt_login.setOnClickListener(this);
    }
    private boolean isCorrectInfo(String username, String password) {
      // 校驗使用者名稱密碼是否正確,直接返回true
      return true;
    }
  @Override
  public void onClick(View v) {
      switch (v.getId()) {
      case R.id.bt_login:
          if(isCorrectInfo(et_username.getText().toString(), et_password.getText().toString())) {
              // 帳號密碼校驗成功,彈出當前密碼
              Toast.makeText(MainActivity.this, "password:"+et_password.getText().toString(), Toast.LENGTH_SHORT).show();
          }
          break;
      default