Xposed 框架会在应用加载时,通过 Zygote 进程将你写的模块注入到目标应用中,然后我们就可以拦截函数调用、修改参数、返回值、甚至改 UI 等功能。
一、完整编写流程概览
步骤内容1配置 Android Studio 工程(Library 模式)2添加 Xposed API3编写 Hook 代码(Java 实现 IXposedHookLoadPackage)4写 assets/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,只需要这样设置权限和包名即可:
package="com.example.wechathook"> android:allowBackup="true" android:label="微信Hook插件" android:supportsRtl="true">
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
package="com.example.xposedtemplate"> android:label="Xposed模板插件" android:allowBackup="true" android:supportsRtl="true">
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