静态方法和实例方法的hook

  • 不需要区分修饰符,也不需要区分静态和实例方法,hook代码的写法都是一样的

得到Money类对象

var money = Java.use("com.xiaojianbang.hook.Money");

hook实例方法

money.getInfo.implementation = function(){
var result = this.getInfo();
console.log("money.getInfo result:",result);
return result;
}

hook静态方法

money.setFlag.implementation = function(a){
console.log("money.setFlag parmm:",a);
return this.setFlag(a);
}

函数参数和返回值的修改

var money = Java.use("com.xiaojianbang.hook.money");
var str = Java.use("java.lang.String");
money.getInfo.implementation = function(){
var result = this.getInfo();
console.log("money.getInfo result:",result);
return str.$new("xiaojianbang");
}

money.setFlag.implementation = function(a){
console.log("money.setFlag param:",a);
return this.setFlag("xiaojianbang");
}

构造方法的hook

var money = Java.use("com.xiaojianbang.hook.Money");
money.$init.implementation = function(a,b){
console.log("money.$init param:",a,b);
return this.$init("美元",200);
}

对象参数的构造与修改 $new

var wallet = Java.use("com.xiaojianbang.hook.Wallet");
var money = Java.use("com.xiaojianbang.hook.Money");
wallet.deposit.implementation = funciton(a){
console.log("wallet.deposit param:",a.getInfo());
return this.deposit(money.#new("美元",200));
}

var wallet = Java.use("com.xiaojianbang.hook.Wallet");
wallet.deposit.implementation = function(a){
a.setAmount(2000);
console.log("wallet.deposit param:",a.getInfo());
return this.deposit(a);
}

HashMap的打印

var utils = Java.use("com.xiaojianbang.hook.Utils");
var stringBuilder = Java.use("java.lang.StringBuild");
utils.shuufferMap.implementation = function(a){
var key = a.keySet();
var it = key.iterator();
var result = stringBuilder.$new();
while(it.hasNext()){
var keystr = it.next();
var valuestr = a.get(keystr);
result.append(valuestr);
}
console.log("utils.shfferMap param:",result.toString());
var result = this.shufferMap(a);
console.log("utils.shufferMap result:",result);
return result;
}

重载方法的hook

var utils = Java.use("com.xiaojianbang.hook.Utils");
utils.getCalc.overload('int','int').implementation = function(a,b){
console.log("utils.getCalc param:",a,b);
return this.getCalc(a,b);
}
utils.getCalc.overload('int','int','int').implementation = function(a,b,c){
console.log("Utils.getCalc param:",a,b,c);
}
utils.getCalc.overload('int','int','int','int').implementation = function(a,b,c,d){
console.log("utils.getCalc param:",a,b,c,d);
return this.getCalc(a,b,c,d);
}

hook方法的所有重载

var utils = Java.use("com.xiaojianbang.hook.Utils");
var overloadsArr = utils.getCalc.overloads;
for(var i = 0;i < overloadArr.length; i++){
overloadsArr[i].implementation = function(){
var params = "";
for(var j = 0; j < arguments.length; j++){
params += arguments[j] + " ";
}
console.log("utils.getCalc is called! params is:",params);
}
console.log(this);
return this.getCalc.apply(this,arguments);
}

主动调用

  • 静态方法

  • var money = Java.use("com.xiaojianbang.hook.Money");
    money.setFlag("xiaojianbang");
    

    - 实例方法 创建新对象

    - ```javascript
    var moneyObj = money.$new("卢布",1000);
    console.log(moneyObj.getInfo());
  • 实例方法 获取已有对象(Java.choose)

  • Java.choose("com.xiaojianbang.hook.Money",{
        onMatch:function(obj){
            console.log(obj.getInfo());
        },
        onComplete:function(){
            console.log("内存中的Money对象搜索完毕");
        }
    });
    

    ### 获取和修改类的字段

    - 静态字段

    ```javascript
    var money = Java.use("com.xiaojianbang.hook.Money");
    console.log(money.flag.value);
    money.flag.value = "VX:xiaojianbang8888";
    console.log(moeny.flag.value);
  • 实例字段 创建新对象

  • var moneyObj = money.$new("欧元",2000);
    console.log(moneyObj.currency.value);
    moneyObj.currency.value = "xiaojianbang currency";
    console.log(moneyObj.currency.value)
    

    - 实例字段 获取已有对象

    - ```javascript
    Java.choose("com.xiaojianbang.hook.Money",{
    onMatch:function(obj){
    console.log("Java.choose Money:",obj.currency.value);
    }, onCompelte:function(){

    }
    });

    //如果字段名和方法名一样 需要加下划线前缀
    Java.choose("com.xiaojianbang.hook.BankCard",{
    onMatch:function(obj){
    console.log("Java.choose BankCard:",obj._accountName.value);
    },onComplete:function(){

    }
    });

hook内部类与匿名类

Java.choose("com.xiaojianbang.hook.Wallet$InnerStructure",{
onMatch:function(obj){
console.log(
"Java.choose Wallet$InnerStructure:",obj.bankCardsList.value
);
},onComplete:function(){

}
});

var money$1 = Java.use("com.xiaojianbang.app.MainActivity$1");
money$1.getInfo.implementaton = function(){
var result = this.getInfo();
console.log("money.getInfo result:,"result);
return result;
}

jadx动态调试

cat default.prop
要看到ro.debuggable=1
目前水平不够,不会调

混淆函数的Hook方法

Java.perform(function(){
var money = Java.use("com.xiaojianbang.hook.Money");
var base64 = Java.use("android.util.Base64");
var str = Java.use("java.lang.String");
var funcName = str.$new(base64.decode("Z2V0SW5mb2==",0));
console.log(funcName);
money[funcName].implementation = function(){
var result = this.getInfo();
console.log("money.getInfo result:",result);
return result;
}
});

将类名进行base64加密

原因:防止乱码和空格

枚举所有已加载的类

  • 枚举的是已经加载的类
  • 出现的类,也不一定能hook到,原因是类加载器的关系
console.log(Java.enumerateLoadedClassesSync().join("\n"));

枚举类的所有方法

var wallet = Java.use("com.xiaojianbang.gook.Wallet");
var methods = wallet.class.getDeclaredMethods();
var constructors = wallet.class.getDeclareddConstructors();
var fields = wallet.class.getDeclaredFields();
var classes = wallet.class.getDeclaredClasses();

hook类的所有方法

function hookFunc(methodName){
console.log(methodName);
var overloadsArr = utils[methodName].overloads;
for(var j = 0; j<overloadsArr.length;j++){
overloadsArr[j].implementation = function(){
var params = "";
for(var k = 0;k<arguments.length;k++){
params+=arguments[k]+" ";
}
console.log("utils."+methodName+"is called params is:",params);
return this[methodName].apply(this.arguments);
}
}
}

var utils = Java.use("com.xiaojianbang.hook.Utils");
var methods = utils.class.getDecalerdMethods();
for(var i = 0;i<menthos.length;i++){
var methodName = methods[i].getName();
hookFunc(methodName);
}

Frida注入dex

Java.openClassFile("/data/local/tmp/Testclasses.dex").load();
var use = Java.use("com.example.myapplication.Test");
use.test();

Frida写文件

var ios = new File("/data/data/com.xiaojianbang.app/xiaojianbang.txt","w");
ios.write("xiaojianbang is very good\n");
ios.flush();
ios.close();

Java.cast

  • 向上转型的,不能用toString直接得到i结果,比如Map、List类型的打印
var utils = Java.use("com.xiaojianbang.hook.Utils");
utils.shufferMap2.implementation = fuction(map){
console.log("map:",map);
var result = Java.cast(map.Java.use("java.util.HashMap"));
console.log("map:",result);
return this.shfferMap(result);
}

数组的构造

Java.perform(function(){
var Utils = Java.use("com.xiaojianbang.hook.Utils");

var strarr = Java.array(
"Ljava.lang.String;",
["xiaojianbang","QQ:12345678","VX:xiaojianbnang88888","共总好:放大放大"]
);

var retval = Utils.myPring(strarr);
console.log(retval);
});

hook动态加载的dex

Java.enumerrateClassLoaders({
onMatch:function(loader){
try{
console.log(loader);
Java.classFactory.loader=loader;
var dynamic = Java.use("com.xiaojianbang.app.Dynamic");
console.log("dynamic:",dynamic);
dynamic.sayHello.implementation = function(){
console.log("gook dynamic.ayHello is run!");
return "xiaojianbang";
}catch(e){
console.log(loader);
}
}
}
});

包装

var Bool = Java.use("java.lang.Integer");
var integer = Java.use("java.lang.Integer");
var objarr Java.array(
"Ljava.lang.Object;",
["xiaojianbang",integer.$new(100),Bool.$new(true),money]
);

hook定位接口的实现类

Java.perform(function(){
var classes = Java.enumerateLoadedClassesSync();
for(const index in classes){
let className = classes[index];
if(className.indexOf("com.xiaojianbang")===-1){
continue;
}
try{
let clazz = Java.use(className);
let resultArr = clazz.class.getInterfaces();
if(resultArr.length===0){
continue;
}
for(let i = 0;i < resultArr.length;i++){
if(resultArr[i].toString().indexof("com.xiaojianbang.app.TestRegisterClass")!=-1){
console.log(className,resultArr);
}
}
}catch(e){
console.log("Didn`t find class:"+className);
}

}
});