1. 程式人生 > 實用技巧 >Android之hook簡單認識

Android之hook簡單認識

一、Hook技術

1.Hook英文翻譯為“鉤子”,而鉤子就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子鉤上事件一樣,並且能夠在鉤上事件時,處理一些自己特定的事件;
2.Hook使它能夠將自己的程式碼“融入”被勾住(Hook)的程序中,成為目標程序的一部分;
3.在Andorid沙箱機制下,Hook是我們能通過一個程式改變其他程式某些行為得以實現;

二、Hook分類


1.根據Android開發模式,Native模式(C/C++)和Java模式(Java)區分,在Android平臺上
Java層級的Hook;
Native層級的Hook;
2.根Hook物件與Hook後處理事件方式不同,Hook還分為:
訊息Hook;
API Hook;
3.針對Hook的不同程序上來說,還可以分為:
全域性Hook;
單個程序Hook;


三、Hook原理

Hook技術本質是函式呼叫,由於處於Linux使用者狀態,每個程序有自己獨立的程序控制元件,所以必須先注入所要Hook的程序空間,修改其記憶體中程序程式碼,替換過程表的符號地址,通過ptrace函式附加程序,向遠端程序注入so庫,從而達到監控以及遠端程序關鍵函式掛鉤;

四、Hook工作流程

1.Android相關核心函式:
ptrace函式:跟蹤一個目標程序,結束跟蹤一個目標程序,獲取記憶體位元組,像記憶體寫入地址;
dlopen函式:以指定模式開啟指定的動態連結庫檔案;
mmap函式:分配一段臨時的記憶體來完成程式碼的存放;
2.向目標程序注入程式碼總結後的步驟分為以下幾步:
用ptrace函式attch上目標程序;
發現裝載共享庫so函式;
裝載指定的.so;
讓目標程序的執行流程跳轉到注入的程式碼執行;
使用ptrace函式的detach釋放目標整合;


五、常用Hook工具-Xposed框架

1.Xposed框架是一款可以在不修改APK的情況下影響程式執行(修改系統)的框架服務;
2.通過替換/system/bin/app_process程式控制zygote程序,使app_process在啟動過程中載入XposedBridge.jar這個jar包,從而完成對Zygote程序及其建立的Dalvik虛擬機器的劫持;

六、Xposed框架安裝

1.從官方網站(http://repo.xposed.info/module/de.robv.android.xposed.installer),下載de.robv.android.xposed.installer_v33_36570c.apk,安裝本地服務XposedInstaller;


2.安裝進入到XposedInstaller應用程式,“框架”模組出現“未啟用”提示;

3.點選“框架”,進入到需要啟用框架的介面,我們點選“安裝/更新”就能完成框架的激活了,因為安裝時會需要Root許可權(下載相關工具如“Root精靈”),安裝後會啟動Xposed的app_process,所以安裝過程會存在裝置多次重啟(安裝過程如下圖);


正在安裝(下載):

獲取Root許可權(授權Root許可權提示,並確定):



安裝完成(安裝完成提示重啟):



安裝成功(框架模組啟用提示消失,即安裝成功):


七、Xposed框架模組安裝

1.Xposed框架內建了下載功能,我們只需要在下載模組點選之後,進行瀏覽、下載、搜尋即可;



2.預設按照時間排序,你可以點選放大鏡圖示,進行搜尋如(XuiMod,一款專門用於狀態列和置頂電池模組);

搜尋XuiMod模組:



3.點選搜尋到的模組,可以檢視到該模組的描述資訊,版本資訊。在版本資訊模組下進行模組的下載安裝;
XuiMod描述資訊:



XuiMod版本資訊,點選下載相關模組:

下載完成,點選“安裝”進行安裝:



安裝完成後,進入“模組”,啟用下載安裝的模組,重啟生效:



重啟後,長按XuiMod進入到模組執行介面,進行相關的操作,重啟生效(如下圖,手機頂部開啟電源充電,居中,充電動畫功能):

八、Xposed自定義模組開發

上個段落,我們講解下如何下載、安裝和使用Xposed模組。那麼我們如何根據自己的需求,自己開發一個Xposed模組,下面我們就介紹下相關流程:
1.下載XposedBridgeApi-<version>.jar(http://forum.xda-developers.com/xposed/xposed-api-changelog-developer-news-t2714067)檔案,使用者提供Hook相關的API,如下:

/** 
*包裝載入時的回撥 
*/ 
public void handleLoadPackage(final LoadPackageParam lpparam)  
/** 
*Xposed提供的Hook方法 
*@param className 待Hook的Class 
*@param classLoader ClassLoader 
*@param methodName 待Hook的Method 
*@param paramterTypesAndClassback hook回撥 
*/ 
Unhook findAndHookMethod(String className,ClassLoader classLoader,String methodName,Object... parameterTypesAndCallback)

2.建立一個Android Project HookDemo,在專案app目錄下建立lib目錄(如果將jar包放置到libs目錄下,可能會產生錯誤,估計Xposed作者在其框架內部也引用了BrideApi,這樣操作能避免重複),將jar包放置到lib目錄(不是專案本身的libs目錄)下,選擇jar包->右鍵->Add As Library將這個jar包新增到BuildPATH;


3.建立一個InputDemo專案(該專案使用輸入框提示使用者輸入資訊,點選按鈕獲取使用者的資訊並做相關的邏輯),用於模擬Hook目標,通過Xposed獲取使用者輸入資訊(關鍵程式碼和執行如下);

OK.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                String inPut = Input.getText() + ""; 
                //獲取使用者輸入,並驗證是否輸入正確 
                if (isInputOK(inPut)) { 
                    Toast.makeText(MainActivity.this, "Input Success", Toast.LENGTH_SHORT).show(); 
                } else { 
                    Toast.makeText(MainActivity.this, "Input Faild", Toast.LENGTH_SHORT).show(); 
                } 
            } 
        }); 
… …  
 private boolean isInputOK(String inPut) { 
        if ("123456".equals(inPut)) { 
            return true; 
        } else { 
            return false; 
        } 
    }


4.在HookDemo專案中,修改AndroidManifest.xml檔案中配置外掛的名稱和Api版本號;

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.pengchengxiang.hookdemo"> 
    <application> 
        … … 
        <meta-data 
            android:name="xposedmodule" 
            android:value="true" /> 
        <!--模組描述--> 
        <meta-data 
            android:name="xposeddescription" 
            android:value="a hook demo" /> 
        <!--模組版本--> 
        <meta-data 
            android:name="xposedminversion" 
            android:value="30" /> 
    </application> 
</manifest>

5.建立一個入口類繼承並實現IXposedHookLoadPackage介面,使用findAndHookMethod方法Hook輸入資訊;

public class Main implements IXposedHookLoadPackage { 
    @Override 
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { 
        if (!loadPackageParam.packageName.equals("com.example.pengchengxiang.inputdemo")) { 
            return; 
        } 
 
 
        XposedBridge.log("Loaded app:" + loadPackageParam.packageName); 
        //Hook MainActivity類的isInputOK方法,並將該方法的引數輸出至Xposed工具中 
        findAndHookMethod("com.example.pengchengxiang.inputdemo.MainActivity", loadPackageParam.classLoader, "isInputOK", String.class, new XC_MethodHook() { 
            @Override 
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 
                XposedBridge.log("hook start"); 
                XposedBridge.log("param1:" + param.args[0]); 
            } 
 
            @Override 
            protected void afterHookedMethod(MethodHookParam param) throws Throwable { 
                XposedBridge.log("hook end"); 
                XposedBridge.log("param1:" + param.args[0]); 
            } 
        }); 
    } 
}

注意:在實際應用過程中,你Hook的方法引數可能是目標程式自定義的類,非Android SDK提供,如"com.example.pengchengxiang.inputdemo.Test"。這裡我們可以使用方法XposedHelpers.findClass來獲取引數型別的class物件,如下:

XposedHelpers.findAndHookMethod("com.example.pengchengxiang.inputdemo.MainActivity", loadPackageParam.classLoader, "isInputOK", String.class,
                XposedHelpers.findClass("com.example.pengchengxiang.inputdemo.Test", loadPackageParam.classLoader), new XC_MethodHook() {...}

6.宣告主入口路徑,在assets資料夾中建立xposed_init檔案,並在其中宣告主入口類;

com.example.pengchengxiang.hookdemo.Main

7.完成InputDemo和HookDemo並安裝在手機中,在XposedInstaller中啟動我們的自己開發的模組;



8.重新啟動手機,在XposedInstaller中日誌模組,檢視在InputDemo中使用XposedBridge.log輸出的日誌;




提示1:檢視日誌模組,如果報錯如下圖:



處理1:第一,檢查XposedBridgeApi-54.jar是否防在新建的lib目錄下;第二,估計Xposed作者在其框架內部也使用了BridgeApi,使用Provided依賴避免重複引用;

轉載於:https://blog.csdn.net/p106786860/article/details/52213695?