日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Xposed之开发Hook插件

發布時間:2024/1/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Xposed之开发Hook插件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題記:

Xposed作為一個著名的Hook框架,早已經在移動安全行業家喻戶曉。今天寫這篇文章主要也是想下手玩玩這個框架,至于框架的安裝,雖然也會碰見很多問題,但是今天暫不附上教程,因為最近精力有限,等有時間我會附上安裝教程,以及遇見的問題解決方法!

知識前導:

Hook技術

  • Hook英文翻譯為“鉤子”,而鉤子就是在事件傳送到終點前截獲并監控事件的傳輸,像個鉤子鉤上事件一樣,并且能夠在鉤上事件時,處理一些自己特定的事件;

  • Hook使它能夠將自己的代碼“融入”被勾住(Hook)的進程中,成為目標進程的一部分;

  • 在Andorid沙箱機制下,Hook是我們能通過一個程序改變其他程序某些行為得以實現;

Hook分類

  • 根據Android開發模式,Native模式(C/C++)和Java模式(Java)區分,在Android平臺上

    Java層級的Hook;

    Native層級的Hook;

  • 根Hook對象與Hook后處理事件方式不同,Hook還分為:

    消息Hook;

    API Hook;

  • 針對Hook的不同進程上來說,還可以分為:

    全局Hook;

    單個進程Hook;

  • Hook原理

    Hook技術本質是函數調用,由于處于Linux用戶狀態,每個進程有自己獨立的進程控件,所以必須先注入所要Hook的進程空間,修改其內存中進程代碼,替換過程表的符號地址,通過ptrace函數附加進程,向遠程進程注入so庫,從而達到監控以及遠程進程關鍵函數掛鉤;

    Hook工作流程

  • Android相關內核函數:

    ptrace函數:跟蹤一個目標進程,結束跟蹤一個目標進程,獲取內存字節,像內存寫入地址;

    dlopen函數:以指定模式打開指定的動態鏈接庫文件;

    mmap函數:分配一段臨時的內存來完成代碼的存放;

  • 向目標進程注入代碼總結后的步驟分為以下幾步:

    1. 用ptrace函數attch上目標進程;

    2. 發現裝載共享庫so函數;

    3. 裝載指定的.so;

    4.讓目標進程的執行流程跳轉到注入的代碼執行;

    5. 使用ptrace函數的detach釋放目標集成;

  • Xposed原理分析

    ?Xposed框架的原理是修改系統文件,替換了/system/bin/app_process可執行文件,在啟動Zygote時加載額外的jar文件(/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar),并執行一些初始化操作(執行XposedBridge的main方法)。然后我們就可以在這個Zygote上下文中進行某些hook操作。

    在Android中,zygote是整個系統創建新進程的核心進程。zygote進程在內部會先啟動Dalvik虛擬機,繼而加載一些必要的系統資源和系統類,最后進入一種監聽狀態。

    在之后的運作中,當其他系統模塊(比如AMS)希望創建新進程時,只需向zygote進程發出請求,zygote進程監聽到該請求后,會相應地fork出新的進程,于是這個新進程在初生之時,就先天具有了自己的Dalvik虛擬機以及系統資源。

    zygote進程是由init進程啟動起來,由init.rc 腳本中關于zygote的描述可知:zygote對應的可執行文件就是/system/bin/app_process,也就是說系統啟動時會執行到這個可執行文件的main()函數里。

    知識小記

    Xposed 提供了幾個接口類供xposed模塊繼承,不同的接口類對應不同的hook時機 IXposedHookZygoteInit zygote 初始化前就執行掛鉤,即loadModule執行時就掛鉤了 IXposedHookLoadPackage apk包加載的時候執行掛鉤,先將掛鉤函數保存起來,等加載apk函數執行后觸發callback (這里的callback是xposed框架自己掛鉤的函數),再執行模塊注冊的掛鉤函數 IXposedHookInitPackageResources apk資源實例化時執行掛鉤,同上。

    正文

    Xposed的技術實現是通過系統進程Hook技術,所以必須要有root權限才行。一般通過刷機來實現,這里我找了個兼容模擬器的Xposed來操作。這里我通過三個簡單的Hook插件開發,來介紹下Xposed插件開發的基本方法。當然我會附上完整源碼來供大家學習研究。接下來,讓我們開啟上帝模式!

    Hook裝載的apk程序包名

    新建一個入口類并繼承并實現IXposedHookLoadPackage接口

    如下操作,我們新建了一個Hook的類,并實現IXposedHookLoadPackage接口中的handleLoadPackage方法,然后對當前裝載的apk程序包名進行打印。

    package com.example.test; ? import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage; /** * Created by Ethan on 2018/11/18. */ public class Hook implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {// 打印裝載的apk程序包名XposedBridge.log("Launch app: " + loadPackageParam.packageName);XposedBridge.log("Hook已經成功了");}}

    這是一個最簡單的一個Xposed插件,實現的功能就是對當前安卓虛擬機裝載的apk程序的報名進行Hook,并且打印出來。

    Hook效果:

    按鈕劫持Hook

    首先自己寫一個粗糙的apk,實現的功能就是點擊界面的按鈕,就會彈出消息你未被劫持的消息!具體完整代碼如下:

    MainActivity:

    package com.example.ceshi; 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; ?public 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:

    <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.ceshi.MainActivity"> ?<Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button" /> ? </android.support.constraint.ConstraintLayout>

    實現功能如圖

    接下來我們要對這個apk的按鈕的方法進行Hook,并且修改方法。

    package com.example.xposed; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; ? public class HookToast implements IXposedHookLoadPackage { ? //Module繼承了IXposedHookLoadPackage接口,當系統加載應用包的時候回回調 handleLoadPackage;public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {//過濾包名,定位要Hook的包名if (loadPackageParam.packageName.equals("com.example.ceshi")) { ?//定位要Hook的具體的類名Class clazz = loadPackageParam.classLoader.loadClass("com.example.ceshi.MainActivity");//Hook的方法為toastMessage,XposedHelpers的靜態方法 findAndHookMethod就是hook函數的的方法,其參數對應為 類名+loadPackageParam.classLoader(照寫)+方法名+參數類型(根據所hook方法的參數的類型,即有多少個寫多少個,加上.class)+XC_MethodHook回調接口;XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {protected void beforeHookedMethod(MethodHookParam param) throws Throwable {super.beforeHookedMethod(param);} ?protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {//param.setResult("你已被劫持")將返回的結果設置成了你已被劫持param.setResult("你已被劫持");}});}} }

    ?

    經過以上操作,當apk執行時會調用我們的Hook類,然后執行就會對apk對應的進程方法進行修改,達到Hook的效果。

    Hook后效果如圖:

    ?

    登陸劫持

    上面進行的按鈕劫持的效果也許還不夠明顯或者說是有趣。大家可能跟我一樣喜歡登陸劫持密碼這樣的操作,首先我們還是自己寫一個簡單的登陸程序。

    MainActivity:

    package com.example.xposedtest; ? import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; ? public class MainActivity extends AppCompatActivity {EditText Name; //定義Plain Test控件第一個輸入框的名字EditText Pass; //定義Plain Test控件第二個輸入框的名字 ?protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Name = (EditText) findViewById(R.id.TEXT_NAME); //通過findViewById找到輸入框控件對應的id并給它起一個名字Pass = (EditText) findViewById(R.id.TEST_PASS);//通過findViewById找到輸入框控件對應的id并給它起一個名字Button Login = (Button) findViewById(R.id.BTN_Login);//通過findViewById找到按鈕控件對應的id并給它起一個名字Login.setOnClickListener(new View.OnClickListener() { //監聽有沒有點擊按鈕控件 如果點擊了就會執行onClick函數@Overridepublic void onClick(View view) {check(Name.getText().toString().trim(),Pass.getText().toString().trim()); //調用check函數}});}public void check(String name,String pass) //自定義函數check 這里用來檢查用戶名和密碼是否是cck和1234{if(name.equals("cck")&&pass.equals("1234")){Toast.makeText(MainActivity.this,"登錄成功", Toast.LENGTH_SHORT).show();//彈框}elseToast.makeText(MainActivity.this,"登錄失敗", Toast.LENGTH_SHORT).show();//彈框} }

    activity_main.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"tools:context="com.example.xposedtest.MainActivity"> ?<TextViewandroid:text="用戶名:"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_alignParentLeft="true"android:layout_alignParentStart="true"android:layout_marginLeft="63dp"android:layout_marginStart="63dp"android:layout_marginTop="77dp"android:id="@+id/textView"/> ?<TextViewandroid:text="密碼:"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="77dp"android:id="@+id/textView2"android:layout_below="@+id/textView"android:layout_alignLeft="@+id/textView"android:layout_alignStart="@+id/textView"/> ?<EditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:inputType="textPersonName"android:ems="10"android:layout_alignBottom="@+id/textView"android:layout_toRightOf="@+id/textView"android:layout_toEndOf="@+id/textView"android:id="@+id/TEXT_NAME"/> ?<EditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:inputType="textPassword"android:ems="10"android:layout_alignBottom="@+id/textView2"android:layout_toRightOf="@+id/textView2"android:layout_toEndOf="@+id/textView2"android:id="@+id/TEST_PASS"/> ?<Buttonandroid:text="登錄"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/TEST_PASS"android:layout_toRightOf="@+id/textView"android:layout_toEndOf="@+id/textView"android:layout_marginLeft="13dp"android:layout_marginStart="13dp"android:layout_marginTop="130dp"android:id="@+id/BTN_Login"/> ? </RelativeLayout>

    實現效果如圖:

    只有當我們輸入正確的用戶名cck和密碼1234時才會彈出登陸成功的消息。

    這里的我們要Hook的效果為不管輸入什么,都會顯示登陸成功,實現的手段就是Hook對應的方法,并對相應的參數進行修改,還是使用上面的回調方法來實現

    package com.example.xposeddeluhook; ? import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; ? ? import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage; ? import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; public class Hookdenglu implements IXposedHookLoadPackage { ?/*** 包加載時候的回調*/public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { ?// 將包名不是 com.example.xposedtest 的應用剔除掉,可以減少管理的類if (!lpparam.packageName.equals("com.example.xposedtest"))return;XposedBridge.log("Loaded app: " + lpparam.packageName); ?//第一個參數是className,表示被注入的方法所在的類//第二個參數是類加載器,照抄就行//第三個參數是被注入的方法名//第四五個參數是第三個參數的兩個形參的類型//最后一個參數是匿名內部類findAndHookMethod("com.example.xposedtest.MainActivity", lpparam.classLoader, "check", String.class,String.class, new XC_MethodHook() { ?/*** 該方法在check方法調用之前被調用,我們輸出一些日志,并且捕獲參數的值。* 最后兩行的目的是改變參數的值。也就是說無論參數是什么值,都會被替換為name為cck,pass為1234* @param param* @throws Throwable*/protected void beforeHookedMethod(MethodHookParam param) throws Throwable {XposedBridge.log("開始劫持了~");XposedBridge.log("參數1 = " + param.args[0]);XposedBridge.log("參數2 = " + param.args[1]);param.args[0] = "cck";param.args[1] = "1234";}/*** 該方法在check方法調用之后被調用* @param param* @throws Throwable*/ ?protected void afterHookedMethod(MethodHookParam param) throws Throwable {XposedBridge.log("劫持結束了~");XposedBridge.log("參數1 = " + param.args[0]);XposedBridge.log("參數2 = " + param.args[1]); ?}});} ? }

    上述代碼我們通過對方法的參數進行了重賦值,來達到了我們想要的結果!

    實現效果如下:

    Xposed日志如下:

    Think one Think

    ? ? ? Xposed可以在不修改APK源碼的情況下,通過自己編寫的模塊來影響程序運行的框架服務,采用了插件機制,通過替換/system/bin/app_process程序控制zygote進程,使得app_process在啟動過程中會加載XposedBridge.jar這個jar包,從而完成對Zygote進程及其創建的Dalvik虛擬機的劫持,從而可以使我們開啟上帝模式,從原理上講,只要你對要操作的方法,參數的個數,類型了如指掌,那你就可以實現任意應用的任意方法的Hook。這也是Xposed插件開發的初衷!

    總結

    以上是生活随笔為你收集整理的Xposed之开发Hook插件的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。