Android 如何優雅的hook私有方法
最近在使用java寫反射進行hook系統的方法,但是每次都會寫一長串代碼,各種try catch,着實讓人的着急,偶然間想起來從一個開源庫裏看到的一個類,當時沒看懂,就保存了下來,現在回頭看看居然很有意思
就是這個類
有幾大特性
- 鏈式調用
- 簡潔,清晰
下面我們來看這個類的使用方法
首先放一個類,咱們就來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