萬物皆可Hook!從新撿起Hook神器-Xposed框架

引言

  這個Hook不是鄧紫棋要給你唱的Hook哦!而是在程序界流傳的強大祕技-Hook函數,Hook原意是指鉤子,它表示的就是在某個函數的上下文作自定義的處理來實現咱們想要的黑科技。   在不少技術領域都存在的這種Hook技術,好比下面這些:java

  • PythonWeb框架中,如DjangoFlask都存在這種Hook技術,能夠在請求的上下文應用的上下文作自定義操做。android

  • Scrapy框架中,能夠自定義MiddlerWare,在請求解析的時候作自定操做。編程

  • K8S編排框架中,咱們也能夠在執行某些函數的上下文中插入Hook函數,這也是和Web框架同理   而今天咱們講解的是關於AndroidHook技術,而有一款神器可以幫助咱們快速地開發Hook模塊,也就是Xposed框架。其實網上的關於Xposed模塊編寫的教程可謂是一抓一大把。但因爲時間的推移,不少工具和方法都發生了變化(如Eclipse退出安卓編程舞臺,AndroidStudio 不斷升級致使其一些設置也隨之變化等)也正所以,網上的教程每每有一些時限性,好比現現在 provide 這個關鍵字已經被捨棄了卻仍有人在用,還有些說要把jar包放到lib文件夾而非libs文件夾……種種錯誤或者落伍的教程對新手產生了很大的誤導。以前也搞過一陣子Xposed框架,而今天在從新部署環境的時候參考某些教程的時候也遇到了不少的坑,因此想從新結合最新的配套工具寫個小教程,主要講解的如下兩個方面:segmentfault

  • Xposed框架介紹以及原理api

  • Xposed框架實戰bash

Xposed框架介紹以及原理

  XposedGithubrovo89大佬設計的一個針對Android平臺的動態劫持項目,經過替換/system/bin/app_process程序控制Zygote進程,使得app_process在啓動過程當中會加載XposedBridge.jar這個jar包,從而完成對Zygote進程及其建立的Dalvik虛擬機的劫持。   由於Xposed工做原理是在/system/bin目錄下替換文件,在install的時候須要root權限,可是運行時不須要root權限。   看到這裏不少人會很懵,什麼是Zygote?簡單來講在Android系統中,應用程序進程都是由Zygote進程孵化出來的,而Zygote進程是由Init進程啓動的。Zygote進程在啓動時會建立一個Dalvik虛擬機實例,每當它孵化一個新的應用程序進程時,都會將這個Dalvik虛擬機實例複製到新的應用程序進程裏面去,而一個應用程序進程被Zygote進程孵化出來的時候,不只會得到Zygote進程中的Dalvik虛擬機實例拷貝,還會與Zygote一塊兒共享Java運行時庫。這也就是能夠將XposedBridge這個jar包加載到每個Android應用程序中的緣由。XposedBridge有一個私有的Native(JNI)方法hookMethodNative,這個方法也在app_process中使用。這個函數提供一個方法對象利用JavaReflection機制來對內置方法覆寫。。。。等等這些都會借鑑各路大神的思路和分析,總而言之,就是從底層替換方法,可讓咱們在不修改APK源碼的狀況下,經過本身編寫的模塊來影響程序運行的框架服務,實現相似於自動搶紅包、微信消息自動回覆等功能。   其實,從本質上來說,Xposed模塊也是一個Android程序。但與普通程序不一樣的是,想要讓寫出的Android程序成爲一個``Xposed 模塊,要額外多完成如下四個硬性任務:微信

一、讓手機上的xposed框架知道咱們安裝的這個程序是個xposed模塊。

二、模塊裏要包含有xposed的API的jar包,以實現下一步的hook操做。

三、這個模塊裏面要有對目標程序進行hook操做的方法。

四、要讓手機上的xposed框架知道,咱們編寫的xposed模塊中,哪個方法是實現hook操做的。
複製代碼

  這就引出我即將要介紹的四大件(與前四步一一對照):網絡

一、AndroidManifest.xml

二、XposedBridgeApi-xx.jar 與 build.gradle

三、實現hook操做的具體代碼

四、xposed_Init
複製代碼

  牢記以上四大件,按照順序一個一個實現,就能完成咱們的第一個Xposed模塊編寫。以上的原理咱們大體就介紹這麼多,下面咱們實戰開始吧!架構

Xposed框架實戰

1. 邁開第一步,新建項目並編輯AndroidManifest.xml

  咱們使用的 IDEAndroid Studio,首先打開 AndroidStudio(以版本 3.4.2爲例,還在用老版本的請升級),創建一個工程,提示咱們選擇「 Activity」,那就選一個 Empty Activity吧。(這個是模塊的界面,隨意選擇便可)。

二、快速運行模板的Xposed模塊

  咱們能夠把項目查看方式設置爲Project模式,以方便查看。而後在 「項目名稱/app/src/main/」目錄下找到AndroidManifest.xml,打開這個文件,並在指定位置插入如下三段代碼:app

<meta-data
          android:name="xposedmodule"
            android:value="true" />
        <meta-data
            android:name="xposeddescription"
            android:value="微信hook" />
        <meta-data
            android:name="xposedminversion"
            android:value="53" />
複製代碼

  效果如圖:

  插入代碼以後,咱們能夠點擊 Run運行 App
  不過,此時會出現如圖提示,也就是缺乏 Device設備來運行這個 App
  下一步咱們要把手機鏈接 Android Studio,鏈接的辦法不少,包括經過 USB鏈接(物理鏈接)Wifi鏈接(也就是網絡鏈接),咱們爲了節省方法,就採用物理鏈接,Ps: 有關於遠程鏈接能夠參考 這篇文章,鏈接好咱們的實體機以後咱們點擊這裏
  咱們等待 Android Studio鏈接手機,鏈接好咱們就能夠看到在 Logcat選項裏面看到咱們的手機運行的日誌報告。
  有如圖所示的日誌打印以後咱們就會發現咱們就能夠運行了,點擊 Run以後會提示咱們的手機安裝咱們剛纔剛寫的 Apk,不過個人手機提示 安裝時驗證超時,不能直接安裝,苦惱,之後選手機也要選個正常的。關於 Android Studio安裝 Apk失敗的緣由能夠參考 這篇文章,既然咱們不能直接安裝 Apk,咱們就使用 adb直接來安裝
  安裝好應用以後咱們在 Xposed框架中勾選咱們剛纔的模塊,而後咱們重啓一下 Xposed框架,就能夠啦
  這一步只是說明 Xposed框架已經認出了咱們寫的程序。但先別高興太早——雖然框架已經以爲他是一個 Xposed模塊了,但咱們本身內心清楚,這個模塊還啥都不會幹呢。下一步,咱們讓這個模塊長點本事。

三、搞定XposedBridgeApi-xx.jar 與 build.gradle

  咱們知道,Xposed模塊主要功能是用來Hook其餘程序的各類函數。可是,如何讓前一步中的那個「一貧如洗」的模塊長本事呢?那就要引入 XposedBridgeApi.jar 這個包,你能夠理解爲一把兵器,模塊有了這把寶刀才能施展出Hook本領。不少之前的老教程都須要手動下載諸如XposedBridgeApi-54.jarXposedBridgeApi-82.jarjar包,而後手工導入到libs目錄裏,才能走下一步道路,而這些jar沒有官方的渠道來安裝,一般只是一個傳一個的,都不知道變成了什麼版本。其實在最新的AndroidStudio 3.1之後,咱們徹底不用這麼麻煩,只須要多寫一行代碼,就讓AndroidStuido自動給咱們配置XposedBridgeApi.jar!下面操做開始:   在 「項目名稱/app/src/main/」目錄下找到build.gradle,在圖示位置加上:

repositories {

    jcenter()

}
compileOnly 'de.robv.android.xposed:api:82'

compileOnly 'de.robv.android.xposed:api:82:sources'
複製代碼

  這句代碼是告訴AndroidStuido使用jcenter做爲代碼倉庫,從這個倉庫裏遠程尋找 de.robv.android.xposed:api:82這個API。這個網上不多有Xposed教程介紹它的!(咱們不用本身找XposedBridgeApi.jar了。注意!此處要用compileOnly這個修飾符!網上有些寫的是provide,可是如今已經停用了!坑人啊!)   寫完以後, build.gradle會提示文件已經修改,是否同步。點擊 「sync now」,同步便可:

  等待依賴構建完成
  【Ps:若是網絡不通,或者同步不順暢,就不要進行第三步的 repositories { jcenter()}這個步驟了,改作這個步驟:手動下載 XposedBridgeApi-82.jar,拖放到 「項目名稱/app/libs/」裏面(不是網上說的單獨創建 lib文件夾,那是好久之前的故事了!),而後右鍵 「Add As Library」自行添加這個 jar包。而 compileOnly ‘de.robv.android.xposed:api:82′compileOnly ‘de.robv.android.xposed:api:82:sources’這兩句仍然照常添加。】   好了,咱們如今已經搞好了全部的準備工做。下一步,就要開始「施展刀法」(編寫 hook代碼)了。

四、實現hook操做的具體代碼

  在「施展刀法」(編寫hook代碼)以前,咱們先要立一個靶子。在界面上畫一個按鈕,並在MainAcitiviy裏寫代碼以下:

package com.example.wx;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Button button;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                Toast.makeText(MainActivity.this, toastMessage(), Toast.LENGTH_SHORT).show();

            }

        });

    }

    public String toastMessage() {

        return "我未被劫持";

    }

}
複製代碼

  而在頁面佈置的文件中,也就是activity_main.xml中增長以下紅框的代碼

  這個靶子很簡單: MainActivity界面有個按鈕,點擊按鈕後會彈出一個 toast提示,該提示的內容由 toastMessage()方法提供,而 toastMessage()的返回值爲 「我未被劫持」。   如今,咱們已經作好了咱們的 App了,下面咱們正式開始「施展刀法」(編寫 hook代碼) 來 hook咱們的 MainActivity並修改這個類的 toastMessage()方法,讓它的返回值爲 「你已被劫持」

五、在MainActivity的同級路徑下新建一個類「HookTest.java」

package com.example.wx;

import de.robv.android.xposed.IXposedHookLoadPackage;

import de.robv.android.xposed.XC_MethodHook;

import de.robv.android.xposed.XposedBridge;

import de.robv.android.xposed.XposedHelpers;

import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class HookTest implements IXposedHookLoadPackage {

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

        if (loadPackageParam.packageName.equals("com.example.root.xposd_hook_new")) {

            XposedBridge.log(" has Hooked!");

            Class clazz = loadPackageParam.classLoader.loadClass(

                    "com.example.root.xposd_hook_new.MainActivity");

            XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {

                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

                    super.beforeHookedMethod(param);

                    //XposedBridge.log(" has Hooked!");

                }

                protected void afterHookedMethod(MethodHookParam param) throws Throwable {

                    param.setResult("你已被劫持");

                }

            });

        }

    }

}
複製代碼

  由代碼可知,咱們是經過 IXposedHookLoadPackage接口中的 handleLoadPackage方法來實現 Hook並篡改程序的輸出結果的。代碼中 「com.example.wx」是目標程序的包名, 」com.example.wx.MainActivity」是想要Hook的類, 「toastMessage」是想要 Hook的方法。咱們在 afterHookedMethod方法(用來定義Hook了目標方法以後的操做)中,修改了 toastMessage()方法的返回值爲「你已被劫持」。在完成代碼編寫以前,說一下爲何要 Hook toastMessage這個方法,咱們先用 Jadx查看一下咱們 Apk的源代碼
  這個源碼是沒有通過混淆的,因此咱們能夠看到這個源碼和咱們以前寫的同樣,咱們根據項目結構能夠判斷出咱們須要 Hook的函數。   OK,以上用來 hook的代碼編寫完畢,讓咱們進行下一步操做。

六、最後一步,添加入口點

  右鍵點擊 「main 」文件夾 , 選擇new –> Folder –>Assets Folder,新建assets文件夾:

  而後右鍵點擊 assets文件夾, new–> file,文件名爲xposed_init(文件類型選text),並在其中寫上入口類的完整路徑(就是本身編寫的那一個Hook類),這樣,Xposed框架就可以從這個xposed_init讀取信息來找到模塊的入口,而後進行Hook操做了:

  好了,曙光就在前面!最後選擇禁用Instant Run: 單擊 File -> Settings -> Build, Execution, Deployment -> Instant Run,把勾所有去掉。   咱們從新以前的安裝Xposed模塊的方法,運行模塊,點擊,奇蹟出現~

  大功告成!!!

結語

  從上面的實戰中咱們能夠發現Hook的基本原理以及步驟,從新看看咱們以前說的四大步,Hook的關鍵其實咱們須要知道針對哪一個模塊的哪一個方法進行Hook

一、讓手機上的xposed框架知道咱們安裝的這個程序是個xposed模塊。

二、模塊裏要包含有xposed的API的jar包,以實現下一步的hook操做。

三、這個模塊裏面要有對目標程序進行hook操做的方法。

四、要讓手機上的xposed框架知道,咱們編寫的xposed模塊中,哪個方法是實現hook操做的。
複製代碼

  像咱們這個例子很簡單,沒有特地的進行代碼混淆以及程序入口改寫等等,咱們尋找仍是很簡單的,通常市面上的App都是有不少反Xposed的行爲,咱們其實要學習的還有不少,這個小教程就當作個小入門吧。   下一篇文章和最近工做上的需求有關係,針對的是2019.10.28以後搜狗微信關閉了在某些公衆號內搜索的功能,因此咱們想要獲取最新的公衆號文章就不能採起搜狗微信這個渠道了,網上有不少教程都在談論其餘的方法,相比較來講,仍是Hook這個渠道是最實際的,咱們將會在以後的文章裏詳細談論,你們能夠期待一下~

注意:  項目已經完成,想要得到源碼能夠關注下面的微信號,回覆「hook入門」便可得到項目地址以及現成的Apk

號主介紹

  • 前兩年在二線大廠工做,目前在創業公司搬磚

  • 接觸方向是爬蟲雲原生架構方面

  • 豐富的反爬攻克經驗以及雲原生二次開發經驗

  • 其餘諸如數據分析黑客增加也有所涉獵

  • 作過百餘人的商業分享以及屢次開辦培訓課程

  • 目前也是CSDN博客專家華爲雲享專家

震驚 | 只需3分鐘!極速部署我的Docker雲平臺

深刻理解Python的TLS機制和Threading.local()

我爲何不建議你使用Python3.7.3?

下一代容器架構已出,Docker何去何處?看看這裏的6問6答!!

公衆號內回覆「私藏資料」便可領取爬蟲高級逆向教學視頻以及多平臺的中文數據集

相關文章
相關標籤/搜索