jshook 中文文档 下载 App

重载方法指定——用 overload() 消除 Frida 的歧义

问题场景

Java 里一个类可以有同名的多个方法,靠参数类型/数量区分(重载):

class Shop {
    void buy(String itemId) { ... }              // 版本 1
    void buy(String itemId, int count) { ... }   // 版本 2
    void buy(String itemId, int count, int price) { ... } // 版本 3
}

直接写 Shop.buy.implementation = ...,Frida 会自动选第一个重载版本(通常是参数最少的那个)。这不是你想要的怎么办?

用 overload() 指定

Java.perform(function () {
    var Shop = Java.use('com.example.Shop');
    
    // 拦截只传 itemId 的版本
    Shop.buy.overload('java.lang.String').implementation = function (itemId) {
        console.log('[+] buy(String) 被调用');
        return this.buy(itemId);
    };
    
    // 拦截传 itemId + count 的版本
    Shop.buy.overload('java.lang.String', 'int').implementation = function (itemId, count) {
        console.log('[+] buy(String, int) 被调用');
        return this.buy(itemId, count);
    };
});

overload() 里写参数的全限定类名(基本类型小写):

参数类型overload 写法
String'java.lang.String'
int'int'
long'long'
float'float'
boolean'boolean'
Bundle'android.os.Bundle'
Context'android.content.Context'
数组'[Ljava.lang.String;'

怎么知道有哪些重载

Java.perform(function () {
    var Shop = Java.use('com.example.Shop');
    // 列出 buy 方法的所有重载
    console.log(Shop.buy.overloads);
});

Frida 会打印每个重载的参数类型列表,对着抄就行。

基本类型和包装类型的区别

Java 里 int 和 Integer 是两种完全不同的类型:

void setCount(int count) { ... }      // 基本类型
void setCount(Integer count) { ... }  // 包装类型(可能为 null)

overload 写法要严格区分:

Java 类型overload
int'int'
Integer'java.lang.Integer'
long'long'
Long'java.lang.Long'
boolean'boolean'
Boolean'java.lang.Boolean'

调用原重载

显式指定了 overload() 后,调用原方法也要用同样的 overload():

Shop.buy.overload('java.lang.String', 'int').implementation = function (itemId, count) {
    // 这样调用原方法——确保调到正确的重载版本
    Shop.buy.overload('java.lang.String', 'int').call(this, itemId, count);
};

或者继续用 apply + arguments,Frida 会自动匹配。

构造方法

构造方法(<init>)也有重载,用法一样:

Activity.$init.overload('android.os.Bundle').implementation = function (savedInstanceState) {
    console.log('[+] Activity 构造被调用');
    this.$init(savedInstanceState);
};

类查找的重载

Java.use 本身不会有歧义(全限定类名唯一)。但 Java.classFactory 或按名称搜索方法时,如果遇到匿名内部类或同名方法多个重载,也要用 overload() 消除歧义。