6. Xposed 替换函数调用及 XposedBridge 相关 API 讲解
在上一节中,我们可能接触过 XposedHelpers,它对反射进行了封装,使用起来非常简便。但在 LSPosed/Xposed 开发的底层,XposedBridge 才是核心。
本节我们将通过一个“靶场”案例,深入讲解 XposedBridge 的核心 API,重点介绍如何替换函数调用(拦截原函数),以及精准 Hook (hookMethod) 和 批量 Hook (hookAllMethods) 的区别。
1. 准备一个“靶场” Demo
为了演示,我们先编写一个简单的 Android 应用作为“靶场”。这个应用包含一个 Person 类,用来演示如何拦截它的方法。
1.1 编写 Person 类
在 com.example.hookdemo 包下新建 Person.java:
package com.example.hookdemo;
import android.util.Log;
public class Person {
// 这是一个有返回值的方法,方便演示替换返回值
public String getName() {
return "原版名字";
}
// 这是一个普通方法
public void print(String content) {
Log.d("muyang", "Target: 原函数执行中 -> " + content);
}
}
1.2 在 MainActivity 中调用
Person p = new Person();
// 1. 调用 print
p.print("Hello");
// 2. 获取返回值并打印
Log.d("muyang", "Get Name: " + p.getName());
2. 替换函数调用 (XC_MethodReplacement)
这是本节的重点。之前我们用的 XC_MethodHook 主要是为了在函数执行前后插入代码(Before/After),原函数通常还是会执行的。
如果你想彻底干掉原函数(比如去除广告逻辑、破解会员校验返回 True),需要使用 XC_MethodReplacement。
2.1 替换 Void 方法(阻止执行)
场景:我们要阻止 Person.print 打印日志,替换成我们自己的逻辑。
Class<?> clazz = Class.forName("com.example.hookdemo.Person", false, loadPackageParam.classLoader);
Method printMethod = clazz.getDeclaredMethod("print", String.class);
// 注意:这里 new 的是 XC_MethodReplacement,而不是 XC_MethodHook
XposedBridge.hookMethod(printMethod, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
// 这里的代码会完全替代原函数的逻辑
String arg = (String) param.args[0];
Log.d("muyang", "拦截成功!原函数 print 没执行。拦截到的参数: " + arg);
// 可以在这里写新的逻辑
// 对于 void 方法,返回 null 即可
return null;
}
});
效果:控制台不会出现 “Target: 原函数执行中…”,只会打印 “拦截成功!…”。
2.2 替换有返回值的方法(篡改结果)
场景:getName() 原本返回 “原版名字”,我们要强制让它返回 “破解版名字”。
Method getNameMethod = clazz.getDeclaredMethod("getName");
XposedBridge.hookMethod(getNameMethod, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Log.d("muyang", "getName 被拦截");
// 直接返回我们想要的结果
// 注意:返回值的类型必须与原函数签名一致(或兼容)
return "破解版名字";
}
});
效果:APP 中调用 p.getName() 得到的结果将变成 “破解版名字”。
3. XposedBridge.hookMethod (精准 Hook)
XposedBridge.hookMethod 是最基础的 API。它的特点是:必须传入具体的 Method 对象。这意味着你需要自己通过 Java 反射机制找到那个确切的函数。
3.1 代码示例
// 必须手动反射获取具体的 Method 对象
Method method = clazz.getDeclaredMethod("print", String.class);
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("muyang", "hookMethod: 精准注入");
}
});
适用场景:你非常确定要 Hook 的函数签名,且只想精准打击这一个函数,不希望误伤重载的同名函数。
4. XposedBridge.hookAllMethods (批量 Hook)
如果目标类中有多个同名函数(重载),或者混淆严重导致参数不确定,使用 hookAllMethods 可以一次性 Hook 指定名称的所有方法。
4.1 代码示例
// 不需要反射具体的 Method,只需要类和方法名 "print"
XposedBridge.hookAllMethods(clazz, "print", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
// param.args 是参数数组,通过长度判断是哪个重载方法
Log.d("muyang", "hookAllMethods: 捕获到一个 print 调用,参数个数: " + param.args.length);
}
});
5. Hook 构造函数
构造函数(Constructor)也是函数,只是没有返回值。
5.1 精准 Hook
// 反射构造函数
Constructor<?> ctor = clazz.getDeclaredConstructor(); // 无参构造
XposedBridge.hookMethod(ctor, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.d("muyang", "Person 对象创建完毕");
}
});
5.2 批量 Hook (hookAllConstructors)
XposedBridge.hookAllConstructors(clazz, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.d("muyang", "任意构造函数被调用");
}
});
6. 总结
| 类/方法 | 作用 | 核心 API |
|---|---|---|
| XC_MethodHook | 监听函数 | beforeHookedMethod / afterHookedMethod |
| XC_MethodReplacement | 替换函数 | replaceHookedMethod (原函数不再执行) |
| hookMethod | 精准 Hook | 需要传入反射好的 Method 对象 |
| hookAllMethods | 批量 Hook | 传入 String 方法名,Hook 所有同名重载 |
更多推荐


所有评论(0)