安卓逆向(Xposed-Hook)

关于参数问题

如果方法是这样

public int addNumbers(int a, int b) {
    return a + b;
}

Hook 代码

XposedHelpers.findAndHookMethod("com.example.app.Calculator",
    lpparam.classLoader,
    "addNumbers",
    int.class, int.class, // 两个参数,都是 int
    new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            XposedBridge.log("[+] addNumbers 被 Hook,参数: " + param.args[0] + ", " + param.args[1]);
        }
    });

beforeHookedMethodafterHookedMethod 的区别


简单理解

方法 执行时机 作用
beforeHookedMethod 目标方法执行前 获取/修改参数,阻止方法执行
afterHookedMethod 目标方法执行后 获取/修改返回值

beforeHookedMethod


beforeHookedMethod 作用

  1. 在方法执行前,获取参数param.args[0]
  2. 修改参数,让方法运行时使用新的参数param.args[0] = "NewValue"
  3. 阻止目标方法执行param.setResult(null)

beforeHookedMethod 获取参数

如果目标方法是

public void setUserInfo(String username, int age) {
    System.out.println("User: " + username + ", Age: " + age);
}

Hook 代码

XposedHelpers.findAndHookMethod("com.example.app.UserManager",
    lpparam.classLoader,
    "setUserInfo",
    String.class, int.class,  // 方法的参数类型
    new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            // 获取方法的参数
            String username = (String) param.args[0];
            int age = (int) param.args[1];

            XposedBridge.log("[+] 用户名: " + username);
            XposedBridge.log("[+] 年龄: " + age);
        }
    });

beforeHookedMethod 修改参数

修改参数,让方法执行时使用新参数

XposedHelpers.findAndHookMethod("com.example.app.UserManager",
    lpparam.classLoader,
    "setUserInfo",
    String.class, int.class,
    new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            // 修改参数
            param.args[0] = "HookedUser"; // 修改用户名
            param.args[1] = 99; // 修改年龄

            XposedBridge.log("[+] 参数已修改 -> 用户名: " + param.args[0] + ",年龄: " + param.args[1]);
        }
    });

beforeHookedMethod 阻止方法并返回假数据

如果方法有返回值

public boolean isUserPremium() {
    return false;
}

Hook 代码

XposedHelpers.findAndHookMethod("com.example.app.UserManager",
    lpparam.classLoader,
    "isUserPremium",
    new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            XposedBridge.log("[+] isUserPremium 被 Hook,强制返回 true");
            param.setResult(true); // 让方法永远返回 true
        }
    });

作用

  • isUserPremium() 方法永远返回 true
  • 适用于绕过 VIP 限制

afterHookedMethod


XposedHelpers.findAndHookMethod("com.example.app.UserManager",
    lpparam.classLoader,
    "getUserInfo",
    new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            XposedBridge.log("[+] 原始返回值: " + param.getResult());

            // 修改返回值
            param.setResult("Hooked UserInfo");

            XposedBridge.log("[+] 修改后返回值: " + param.getResult());
        }
    });

作用

  • 方法执行后,修改返回值
  • 原来的 getUserInfo() 返回 "Real UserInfo"
  • Hook 之后,返回 "Hooked UserInfo"

功能 beforeHookedMethod afterHookedMethod
执行时机 方法执行 方法执行
获取参数 param.args[0] ❌(只能看返回值)
修改参数 param.args[0] = "NewValue"
阻止方法执行 param.setResult(null)
修改返回值 param.setResult("NewValue")
让方法延迟执行 Thread.sleep(5000)

MethodHookParam 的常用方法


方法 作用
param.args[i] 获取/修改方法的第 i 个参数
param.thisObject 获取当前调用方法的对象(this
param.getResult() 获取方法的返回值(仅 afterHookedMethod 可用)
param.setResult(Object value) 修改返回值(仅 afterHookedMethod 可用)
param.setThrowable(Throwable t) 让方法抛出异常
param.hasThrowable() 检查方法是否抛出异常
param.getThrowable() 获取方法抛出的异常

Xposed 直接启动某个方法


Xposed 里,你可以使用 XposedHelpers.callMethod()XposedHelpers.callStaticMethod() 直接启动(调用)某个方法,就像 Frida 里的 choose() 之后手动调用方法一样。

1️⃣ 使用 XposedHelpers.callMethod() 调用对象方法

假设目标类 User 里有一个方法

public class User {
    public String getUsername() {
        return "Alice";
    }
}

在 Xposed 里 Hook 该类,并调用 getUsername()

XposedHelpers.findAndHookConstructor("com.example.app.User",
    lpparam.classLoader,
    String.class, int.class,
    new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            Object instance = param.thisObject; // 获取 User 实例
            String username = (String) XposedHelpers.callMethod(instance, "getUsername");
            XposedBridge.log("[+] 直接调用 getUsername(),返回值: " + username);
        }
    });

作用

  • User 对象被创建后,直接调用 getUsername()
  • 不需要等 App 调用这个方法,Xposed 主动触发
  • 适用于 Hook 目标对象后立即执行特定方法

1️⃣ replaceHookedMethod() 直接替换方法

和frida的这个方法差不多implementation。

Frida

Java.use("com.example.app.TargetClass").targetMethod.implementation = function(arg) {
    console.log("Hooked! 参数: " + arg);
    return "Hooked Result";
};

Xposed

XposedHelpers.findAndHookMethod("com.example.app.TargetClass",
    lpparam.classLoader,
    "targetMethod",
    String.class,
    new XC_MethodReplacement() {  // 直接替换方法
        @Override
        protected Object replaceHookedMethod(MethodHookParam param) {
            XposedBridge.log("[+] targetMethod 被完全替换");
            return "Hooked Result"; // 返回新的结果
        }
    });


XC_MethodHook

  • 这是一个抽象类,用于实现方法的钩子功能
  • 主要用于在目标方法执行前后插入自定义代码
  • 包含两个重要的回调方法:
  // 在原方法执行之前调用
  protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
      // 你的代码
  }

  // 在原方法执行之后调用
  protected void afterHookedMethod(MethodHookParam param) throws Throwable {
      // 你的代码
  }

MethodHookParam

方法hook的参数(包含了被钩子方法的所有相关信息

  • 主要属性和方法:
  • param.thisObject: 获取被 Hook 方法所在的对象实例
  • param.args: 获取原方法的参数数组
  • param.getResult(): 获取原方法的返回值
  • param.setResult(): 修改方法的返回值
  • param.setThrowable(): 设置异常
XC_MethodHook hook = new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        // 获取方法参数
        String arg1 = (String) param.args[0];
        
        // 修改方法参数
        param.args[0] = "新参数";
    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        // 获取方法返回值
        Object result = param.getResult();
        
        // 修改返回值
        param.setResult("新的返回值");
    }
};

okhttp3.Request.Builder

这是 OkHttp 库中用于构建 HTTP 请求的建造者模式(Builder Pattern)实现。$ 符号表示 Builder 是 Request 类的内部类。

主要用法:

// 创建一个基本的GET请求
Request request = new Request.Builder()
    .url("https://api.example.com/data")
    .get()  // GET请求(默认是GET,可以不写)
    .build();

// 创建一个带header的POST请求
Request request = new Request.Builder()
    .url("https://api.example.com/data")
    .post(RequestBody.create(MediaType.parse("application/json"), "{\"key\":\"value\"}"))
    .addHeader("Authorization", "Bearer token123")
    .build();

CallMethod

// 1. 获取响应体
Object body = XposedHelpers.callMethod(response, "body");
// 等同于 response.body()
// response 是 OkHttp 的 Response 对象,body() 方法返回响应内容

// 2. 获取请求对象
Object request = XposedHelpers.callMethod(param.thisObject, "request");
// 等同于 response.request()
// 从 Response 对象中获取对应的 Request 对象

// 3. 获取URL对象
Object urlObj = XposedHelpers.callMethod(request, "url");
// 等同于 request.url()
// 从 Request 对象中获取 URL

完整的调用链是这样的:

// 正常的 OkHttp 代码是这样的:
Response response = ...;
ResponseBody body = response.body();          // 获取响应内容
Request request = response.request();         // 获取请求信息
HttpUrl url = request.url();                 // 获取请求的URL

// 但在 Xposed 中,我们需要用 callMethod 来调用这些方法:
Object response = ...;
Object body = XposedHelpers.callMethod(response, "body");    // 调用 body() 方法
Object request = XposedHelpers.callMethod(response, "request"); // 调用 request() 方法
Object url = XposedHelpers.callMethod(request, "url");       // 调用 url() 方法

为什么要用 callMethod?

  • 因为在 Xposed 中,我们可能无法直接访问这些类和方法
  • callMethod 允许我们调用任何方法,即使是私有的
  • 这就像是一个"万能钥匙",可以打开任何门(调用任何方法)

// originalRequest 是 OkHttp3 中 RealCall 类的一个字段
// 表示原始的 HTTP 请求对象,包含了请求的 URL、请求头、请求体等信息
Object request = XposedHelpers.getObjectField(call, "originalRequest");

你可能感兴趣的:(android,前端,javascript)