关于 Xposed:Xposed 插件开发详细流程

Xposed 框架会在应用加载时,通过 Zygote 进程将你写的模块注入到目标应用中,然后我们就可以拦截函数调用、修改参数、返回值、甚至改 UI 等功能。


一、完整编写流程概览

步骤内容
1配置 Android Studio 工程(Library 模式)
2添加 Xposed API
3编写 Hook 代码(Java 实现 IXposedHookLoadPackage
4assets/xposed_init 声明入口类
5打包成 APK 并安装到手机
6在 Xposed/LSPosed 中启用并重启生效
7调试日志、查看效果

二、Hook 微信发送消息前拦截内容

一个简单的 Xposed 插件:Hook 微信某个函数,输出你发送的文字内容

2.1 创建 Android Studio 工程(Library 类型)

创建新工程时选择:

  • 类型:Android Library

  • 名字:WechatHookModule

2.2 配置 build.gradle

编辑 WechatHookModule/build.gradle

apply plugin: 'com.android.library'

android {
    compileSdkVersion 28

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
    }

    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

dependencies {
    compileOnly 'de.robv.android.xposed:api:82' // Xposed API(只编译不打包)
}

2.3 创建主 Hook 类

创建类 WechatHook.java

package com.example.wechathook; // 声明当前类所在的包名

import android.util.Log; // 导入 Android 日志工具类
import de.robv.android.xposed.IXposedHookLoadPackage; // 导入 Xposed 加载包接口
import de.robv.android.xposed.XC_MethodHook; // 导入 Xposed 方法钩子基类
import de.robv.android.xposed.XposedBridge; // 导入 Xposed 桥接工具类,用于输出日志等
import de.robv.android.xposed.XposedHelpers; // 导入 Xposed 助手类,提供反射与 Hook 方法
import de.robv.android.xposed.callbacks.XC_LoadPackage; // 导入 Xposed 包加载回调类

public class WechatHook implements IXposedHookLoadPackage { // 定义一个实现 IXposedHookLoadPackage 接口的类

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { // Xposed 加载每个包时都会回调此方法
        // Hook 微信
        if (!lpparam.packageName.equals("com.tencent.mm")) // 检查当前加载的包名是否是微信包名
            return; // 如果不是微信,则不做任何处理,直接返回

        XposedBridge.log("微信已加载,开始 Hook"); // 在 Xposed 日志中输出提示信息

        try {
            // 假设 ChattingUI 类有个 sendMessage 方法
            Class<?> clazz = XposedHelpers.findClass( // 通过类名和类加载器查找目标类
                "com.tencent.mm.ui.chatting.ChattingUI", lpparam.classLoader);

            XposedHelpers.findAndHookMethod(clazz, "sendMessage", String.class, new XC_MethodHook() { // 在 ChattingUI 类中 Hook sendMessage(String) 方法
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // 在原方法执行前回调
                    String msg = (String) param.args[0]; // 获取调用 sendMessage 时传入的消息内容
                    XposedBridge.log("即将发送的微信消息: " + msg); // 将消息内容输出到 Xposed 日志
                }
            });

        } catch (Throwable t) { // 捕获所有可能的异常
            XposedBridge.log("Hook 微信失败: " + Log.getStackTraceString(t)); // 输出失败原因的堆栈信息
        }
    }
}

2.4 创建 assets/xposed_init

main/assets/ 目录下创建文件:

xposed_init

内容为主类的全路径:

com.example.wechathook.WechatHook

这个文件告诉 Xposed 框架插件的入口类在哪。

2.5 修改 AndroidManifest.xml

注意写的是插件,不需要 Activity,只需要这样设置权限和包名即可:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.wechathook">

    <application
        android:allowBackup="true"
        android:label="微信Hook插件"
        android:supportsRtl="true">
    </application>

</manifest>

2.6 打包安装

  • 在 Android Studio 中点击 Build > Build APK

  • 用 ADB 安装插件到手机:

adb install -r app-debug.apk

或者 直接运行项目。

2.7 启用插件并重启

  • 打开 Xposed Installer 或 LSPosed

  • 启用插件 

  • 重启系统

2.8 验证效果

  • 打开微信发送一条消息

  • 查看 logcat Xposed 日志:

adb logcat | grep Xposed

能看到日志:

即将发送的微信消息: 哈喽 ChatGPT

成功。


三、常用 Hook 实例

3.1 Hook 常用 API

功能目标使用方法说明与例子
Hook 普通方法findAndHookMethodXposedHelpers.findAndHookMethod("com.xxx.Class", classLoader, "methodName", 参数类型..., new XC_MethodHook() { })✔ 用于 Hook 普通 Java 方法
Hook 构造方法findAndHookConstructorXposedHelpers.findAndHookConstructor("com.xxx.Class", classLoader, 参数类型..., new XC_MethodHook() { })✔ Hook 构造函数,一般用于初始化逻辑
获取成员变量getObjectField(obj, "fieldName")String s = (String) XposedHelpers.getObjectField(obj, "mText");✔ 获取成员变量(如 private 成员)
修改成员变量setObjectField(obj, "fieldName", value)XposedHelpers.setObjectField(obj, "mText", "Hello");✔ 修改成员变量
调用对象方法callMethod(obj, "method", args...)Object ret = XposedHelpers.callMethod(obj, "doSomething", 123);✔ 调用目标对象的方法
调用静态方法callStaticMethod(clazz, "method", args...)XposedHelpers.callStaticMethod(MyClass.class, "getVersion");
获取静态变量getStaticObjectField(clazz, "field")Object val = XposedHelpers.getStaticObjectField(MyClass.class, "STATIC_FIELD");
修改静态变量setStaticObjectField(clazz, "field", val)XposedHelpers.setStaticObjectField(MyClass.class, "STATIC_FIELD", "newVal");
修改返回值afterHookedMethod 中使用 param.setResult(...)param.setResult("Hooked!");
阻止方法执行beforeHookedMethod 中使用 param.setResult(...)直接设定返回值可以“阻止”方法执行
抛出异常终止执行param.setThrowable(new RuntimeException("error"))阻断流程用于模拟异常等
打印日志XposedBridge.log(...)XposedBridge.log("Hook hit here!");

3.2 详细举例说明

1)拦截 Toast 弹出并打印内容

XposedHelpers.findAndHookMethod(
    "android.widget.Toast",             // 要 Hook 的类名(这里是系统的 Toast 类)
    lpparam.classLoader,               // 当前应用的类加载器,用于加载这个类
    "show",                            // 要 Hook 的方法名(Toast 的 show() 方法)
    new XC_MethodHook() {              // Hook 回调对象
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            // 在 show() 方法执行之前触发
            XposedBridge.log("Toast 被调用!"); // 打日志:说明 Toast 要显示了
        }
    });

2)修改函数的返回值(假设有个 isVip()

XposedHelpers.findAndHookMethod(
    "com.example.app.User",          // 目标类的完整类名,这里是 com.example.app.User
    lpparam.classLoader,             // 类加载器,用于加载目标类
    "isVip",                         // 要 Hook 的方法名,这里是 isVip() 方法
    new XC_MethodHook() {           // 匿名内部类,用于定义 Hook 的行为
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            // 在原始 isVip() 方法执行完之后回调
            param.setResult(true);  // 强制修改返回值为 true —— 无论实际是不是 VIP,现在都变成了 VIP
        }
    });

3)获取并修改成员变量(如 TextView 的文本)

XposedHelpers.findAndHookMethod(
    "com.example.MainActivity",         // 要 Hook 的类名:MainActivity,是目标应用的主界面类
    lpparam.classLoader,                // 类加载器,用于从目标应用加载类
    "onCreate",                         // 要 Hook 的方法名:onCreate(Activity 生命周期的入口方法)
    android.os.Bundle.class,            // onCreate 的参数类型(必须精确匹配,否则 Hook 失败)
    new XC_MethodHook() {               // 匿名内部类:定义 Hook 的逻辑
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            // onCreate 方法执行完之后回调这个方法
            Object activity = param.thisObject; // 获取当前的 MainActivity 实例(即 this)
            TextView tv = (TextView) XposedHelpers.getObjectField(activity, "textView");
            // 使用反射获取 MainActivity 中名为 textView 的成员变量,并强转成 TextView 对象
            tv.setText("已 Hook 修改内容!"); // 修改这个 TextView 的文字显示内容
        }
    });

4)Hook 构造函数并打印参数

XposedHelpers.findAndHookConstructor(
    "com.example.User",              // 要 Hook 的类名:com.example.User
    lpparam.classLoader,             // 类加载器,用于加载目标类
    String.class, int.class,         // 构造函数的参数类型列表:第一个参数是 String,第二个参数是 int
    new XC_MethodHook() {            // 定义构造函数 Hook 的回调逻辑
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            // 构造函数执行前调用此方法
            String name = (String) param.args[0];  // 获取第一个参数 name
            int age = (int) param.args[1];         // 获取第二个参数 age
            XposedBridge.log("User 被构造: name=" + name + ", age=" + age);
            // 记录日志,打印构造 User 对象时传入的 name 和 age 参数
        }
    });

5)调用原方法(比如某对象的 getToken 方法)

Object token = XposedHelpers.callMethod(obj, "getToken");
// 通过 XposedHelpers.callMethod 反射调用对象 obj 的 getToken() 方法,返回结果赋值给 token

XposedBridge.log("调用 getToken 得到:" + token);
// 使用 XposedBridge.log 打印调用结果 token,方便调试或记录

6)修改传入参数(拦截支付金额)

XposedHelpers.findAndHookMethod(
    "com.example.PayActivity",         // 要 Hook 的类名:支付页面或支付逻辑所在的 Activity
    lpparam.classLoader,               // 当前包的类加载器
    "pay",                            // 要 Hook 的方法名,这里是 pay 方法
    int.class,                        // 方法参数类型,这里 pay(int amount)
    new XC_MethodHook() {             // 方法钩子回调
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            int originAmount = (int) param.args[0];        // 获取原始传入的金额参数
            XposedBridge.log("原始金额:" + originAmount);  // 打印原始金额,方便调试
            param.args[0] = 1;                             // 把金额参数修改为 1,即强制改成 1 元支付
        }
    });

7)拦截点击事件(拦截按钮点击)

XposedHelpers.findAndHookMethod(
    "android.view.View$OnClickListener",  // 目标类:内部接口 View.OnClickListener(注意 $ 表示内部类)
    lpparam.classLoader,                   // 当前进程的类加载器
    "onClick",                            // 方法名:onClick
    View.class,                          // 方法参数:单个 View 对象
    new XC_MethodHook() {                 // Hook 回调对象
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            XposedBridge.log("点击事件被拦截!");  // 在 onClick 执行前打印日志
        }
    });

8)静态变量获取与修改

Class<?> cls = XposedHelpers.findClass("com.example.Config", lpparam.classLoader);
// 通过类名和类加载器,获取目标类 com.example.Config 的 Class 对象

String originalValue = (String) XposedHelpers.getStaticObjectField(cls, "API_URL");
// 获取该类中名为 API_URL 的静态字段的当前值,假设是字符串类型

XposedBridge.log("原始地址:" + originalValue);
// 打印原始的 API_URL 地址,方便调试和验证

XposedHelpers.setStaticObjectField(cls, "API_URL", "https://api.hacked.com/");
// 将 API_URL 静态字段的值改为 "https://api.hacked.com/",实现地址篡改

3.3 常用 Hook 场景模板总结

场景Hook 方法说明
登录自动通过Hook 登录函数,修改返回值或参数.
跳过验证页Hook 验证函数,设置 param.setResult(true).
修改 UI 内容Hook onCreate() 后修改控件属性.
控制按钮逻辑Hook onClick().
替换服务地址修改静态字段,如 BASE_URL.
获取 TokencallMethod()getObjectField().

四、项目模板

4.1 项目结构

XposedTemplate/
├── app/
│   ├── src/
│   │   └── main/
│   │       ├── java/com/example/xposedtemplate/
│   │       │   └── MyHook.java
│   │       ├── assets/
│   │       │   └── xposed_init
│   │       └── AndroidManifest.xml
├── build.gradle
└── settings.gradle

4.2 settings.gradle

rootProject.name = "XposedTemplate"
include ':app'

4.3 项目根目录 build.gradle(可选)

如果提示 gradle 设置,添加:

// 项目根目录的 build.gradle,不是 app 的
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.2'
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

4.4 app/build.gradle

apply plugin: 'com.android.library'

android {
    namespace 'com.example.xposedtemplate'
    compileSdkVersion 28

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        // 不用 applicationId(这是 Library 模块)
    }

    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

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

4.5 AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xposedtemplate">

    <application
        android:label="Xposed模板插件"
        android:allowBackup="true"
        android:supportsRtl="true">
    </application>

</manifest>

4.6 assets/xposed_init

新建 app/src/main/assets/xposed_init,内容为:

com.example.xposedtemplate.MyHook

4.7 MyHook.java

package com.example.xposedtemplate;

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 MyHook implements IXposedHookLoadPackage {

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {

        // 示例:Hook 微信
        if (!lpparam.packageName.equals("com.tencent.mm")) return;

        XposedBridge.log("微信已加载,准备 Hook");

        try {
            Class<?> clazz = XposedHelpers.findClass(
                "com.tencent.mm.ui.chatting.ChattingUI", lpparam.classLoader);

            XposedHelpers.findAndHookMethod(clazz, "onCreate", android.os.Bundle.class,
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        XposedBridge.log("微信 ChattingUI onCreate 被调用!");
                    }
                });

        } catch (Throwable t) {
            XposedBridge.log("Hook 出错: " + t.getMessage());
        }
    }
}

4.8 使用说明

构建

在 Android Studio 中:

  • 打开项目

  • 点击菜单 Build > Make Module 'app'

  • 找到 APK 路径:app/build/outputs/apk/debug/app-debug.apk

安装

adb install -r app-debug.apk

启用

  • 打开 LSPosed 或 EdXposed

  • 勾选模块并重启

  • 使用 logcat 观察输出:

adb logcat | grep Xposed
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值