本文讲解热插拔框架的使用笔记
以如下的java的activity类为例子
package com.marsdl.crawler.hookdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.score);
textView.append(isExcellent(40, 50) + "\n");
}
private boolean isExcellent(int chines, int math) {
textView.append("语文和数学成绩的总和:" +
String.valueOf(chines + math) + "\n");
if (chines + math >= 180) {
return true;
} else {
return false;
}
}
}
hook一个普通方法
var MainActivity = Java.use("com.marsdl.crawler.hookdemo.MainActivity");
MainActivity.isExcellent.implementation = function(chinese, math) {
console.log(chinese +" " + math);
var isTrueOrFalse = this.isExcellent(95, 90);
console.log("num:"+isTrueOrFalse);
return num;
};
如果我们想要hook isExcellent
方法后,不想对他做什么事情,只想打印他的形式参数(可以称呼入参)。
var MainActivity = Java.use("com.marsdl.crawler.hookdemo.MainActivity");
MainActivity.isExcellent.implementation = function(a, b) {
console.log(a);
console.log(b)
return this.isExcellent(a, b);
};
如果还想打印MainActivity类中某个方法的返回参数,那么需要用this调用MainActivity中的某个方法。如下的代码。
var MainActivity = Java.use("com.marsdl.crawler.hookdemo.MainActivity");
MainActivity.isExcellent.implementation = function(a, b) {
console.log(a);
console.log(b);
//调用该方法,获取该函数运行的结果,然后打印出来,并返回
var result = this.isExcellent(a, b);
console.log(result);
return result;
};
初始构造函数
如下的代码为例子,我们创建一个java类。
package com.marsdl.crawler.hookdemo;
public class Calculator {
private int a = 0;
private int b = 1;
private int sum;
public Calculator() {
}
public Calculator(int a, int b) {
this.a = a;
this.b = b;
}
public Calculator(int a, int b, int sum) {
this.a = a;
this.b = b;
this.sum = sum;
}
public int sum() {
return a+b;
}
public String content(String content) {
return content + ",附加内容";
}
}
那么此时想要初始化这个Calculator的Java类,需要hook构造方法;查看Java代码,我们看到有很多不同的构造方法,那么需要通过overload
重载参数,
var Calculator = Java.use("com.marsdl.crawler.hookdemo.Calculator");
Calculator.$init.overload("int", "int").implementation = function(a, b) {
console.log(a +" " + b);
return this.$init(a, b);
};
对某个类的初始化,然后调用方法
var calInstance = Calculator.$new();
var sum = calInstance.sum();
console.log(sum);
调用Java反射方法,并且修改其中的参数。通过反射获取某个对象的Class对象,然后获取该对象中的某个属性,然后修改值。
获取某个类然后对该类进行实例化
var Calculator = Java.use("com.marsdl.crawler.hookdemo.Calculator");
var calInstance = Calculator.$new();
获取某个对象的Class类对象,如下的代码是通过强转的方式进行
var clazz = Java.use("java.lang.Class");
var calobj = Java.cast(calInstance.getClass(), clazz);
var clazz = Java.use("java.lang.Class");
Calculator.$init.overload("int", "int").implementation = function(a, b) {
console.log("init:" + a +" " + b);
var calInstance = Calculator.$new();
console.log(calInstance.sum());
var calobj = Java.cast(calInstance.getClass(), clazz);
//获取calobj类对象中的a属性
var aField = calobj.getDeclaredField('a');
console.log(aField);
aField.setAccessible(true);
var avalue = aField.get(calInstance);
console.log("avalue:" + avalue);
aField.setInt(calInstance, 888);
//获取calobj类对象中的a属性值
var avalueAgain = aField.get(calInstance);
console.log("avalueAgain:" + avalueAgain);
var aafield = calobj.getDeclaredField('aa');
var aavalue = aafield.get(calInstance);
console.log("aavalue:" + aavalue);
aafield.set(calInstance, "dadade");
var aavalueAgain = aafield.get(calInstance);
console.log("aavalueAgain:" + aavalueAgain);
return this.$init(a, b);
};