一、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?