最近在使用java写反射进行hook系统的方法,但是每次都会写一长串代码,各种try catch,着实让人的着急,偶然间想起来从一个开源库里看到的一个类,当时没看懂,就保存了下来,现在回头看看居然很有意思
Hack.java
就是这个类
有几大特性
下面我们来看这个类的使用方法
首先放一个类,咱们就来hack这个类
package com.utils.dddemo.hack;
import android.util.Log;
import com.utils.library.log.LogA;
public class HackDemo {
private int mIntField;
private String mStr;
private static String staticField = "dds";
// 构造方法
private HackDemo() {
Log.d("dds", "constructor");
}
private HackDemo(int x) {
mIntField = x;
Log.d("dds", "constructor " + x);
}
private HackDemo(int x, String str) {
mIntField = x;
mStr = str;
Log.d("dds", "constructor " + x);
}
// 成员方法
private int foo() {
Log.d("dds", "method :foo");
// 返回私有变量
return mIntField;
}
private int foo(int type, String str) {
Log.d("dds", "method :foo " + type + "," + str);
return 7;
}
// 静态成员方法
private static void bar() {
Log.d("dds", "static method :bar");
}
private static int bar(int type) {
Log.d("dds", "static method :bar " + type);
return type;
}
private static void bar(int type, String name, Bean bean) {
LogA.d("dds", "static method :bar type:%d,%s,%s", type, name, bean.toString());
}
// 打印静态成员变量
public void printStaticField() {
Log.d("dds_test", "printStaticField:" + staticField);
}
}
无参数构造方法
构造
Hack.HackedMethod0 constructor = Hack
.into("com.utils.dddemo.hack.HackDemo")
.constructor()
.withoutParams();
// check
assertNotNull(constructor);
// 调用
Object statically = constructor
.invoke()
.statically();
// check
assertNotNull(statically);
有参数构造方法
// 构造
Hack.HackedMethod1 constructor1 = Hack
.into("com.utils.dddemo.hack.HackDemo")
.constructor()
.withParam(int.class);
// check
assertNotNull(constructor1);
// 调用
Object statically1 = constructor1
.invoke(1222)
.statically();
// check
assertNotNull(statically1);
无参数成员方法
Hack.HackedMethod1 constructor1 = Hack
.into("com.utils.dddemo.hack.HackDemo")
.constructor()
.withParam(int.class);
// check
assertNotNull(constructor1);
// 构造方法
Object statically1 = constructor1.invoke(1222).statically();
// check
assertNotNull(statically1);
// 构造该方法
Hack.HackedMethod0 foo = Hack
.into("com.utils.dddemo.hack.HackDemo")
.method("foo")
.returning(int.class)
.withoutParams();
// check
assertNotNull(foo);
// check 返回值是否等于传入的值
assertEquals(1222, (int) foo.invoke().on(statically1));
有参数,有返回值方法
Hack.HackedMethod1 constructor1 = Hack
.into("com.utils.dddemo.hack.HackDemo")
.constructor()
.withParam(int.class);
assertNotNull(constructor1);
Object statically1 = constructor1.invoke(1222).statically();
assertNotNull(statically1);
Hack.HackedMethod2 foo = Hack
.into("com.utils.dddemo.hack.HackDemo")
.method("foo")
.returning(int.class)
.withParams(int.class, String.class);
assertNotNull(foo);
assertEquals(7, (int) foo.invoke(11, "dds_test").on(statically1));
无参数静态方法
Hack.HackedMethod0 method = Hack
.into("com.utils.dddemo.hack.HackDemo")
.staticMethod("bar")
.withoutParams();
assertNotNull(method);
// 方法调用
method.invoke().statically();
有参数静态方法
Hack.HackedMethod3 method
= Hack.into("com.utils.dddemo.hack.HackDemo")
.staticMethod("bar")
.throwing(IOException.class)
.withParams(int.class, String.class, Bean.class);
assertNotNull(method);
// 调用方法
method.invoke(-1, "xyz", new Bean()).statically();
下面重点来了,我们经常hook系统的方法都是hook的静态成员变量,那我们该如何修改静态成员变量的呢?
Hack.HackedTargetField field = Hack
.into("com.utils.dddemo.hack.HackDemo")
.staticField("staticField")
.ofType(String.class);
//设置新值
field.set("dds111111111");
//打印出新值
Hack.HackedMethod0 constructor = Hack
.into("com.utils.dddemo.hack.HackDemo")
.constructor()
.withoutParams();
assertNotNull(constructor);
Object statically = constructor.invoke().statically();
((HackDemo) statically).printStaticField();
打印出结果
D/dds_test: printStaticField:dds111111111
https://github.com/ddssingsong/AnyTool