寫在前面
hook(鉤子),通常是指對一些方法進(jìn)行攔截。這樣當(dāng)這些方法被調(diào)用時,也能夠執(zhí)行我們自己的代碼,從而達(dá)到監(jiān)控或更改代碼邏輯的目的。
實(shí)現(xiàn)方式
方式一、Java 反射實(shí)現(xiàn)Hook:
這種方式是最常見的,也是各種框架常采用的一種方式,直接上例子:
/**
* 利用Hook的方式修復(fù)Toast在7.1系統(tǒng)上BadTokenException
* Created by conghongjie on 2018/3/28.
*/
public class ToastCompat extends Toast{
private static final String TAG = "ToastCompat";
public ToastCompat(Context context) {
super(context);
}
@Override
public void show() {
if(Build.VERSION.SDK_INT==Build.VERSION_CODES.N_MR1){
tryToHack();
}
super.show();
}
private void tryToHack(){
try {
Object mTN=getFieldValue(this,"mTN");
if(mTN!=null){
Object rawHandler=getFieldValue(mTN,"mHandler");
if(rawHandler!=null){
//替換為封裝后的mHandler
setFieldValue(rawHandler,"mCallback",new InternalHandlerCallback((Handler)rawHandler));
}
}
}catch (Throwable e){
e.printStackTrace();
}
}
private class InternalHandlerCallback implements Handler.Callback{
private final Handler mHandler;
public InternalHandlerCallback(Handler mHandler) {
this.mHandler = mHandler;
}
@Override
public boolean handleMessage(Message msg) {
try {
// 捕獲BadTokenException
mHandler.handleMessage(msg);
}catch (BadTokenException e) {
e.printStackTrace();
}
return true;
}
}
}
總結(jié)一下,此方法的實(shí)現(xiàn)思路:
找到需要Hook方法的系統(tǒng)類(最好是單例的情況)
利用java的動態(tài)代理這個系統(tǒng)類
使用反射的方法把這個系統(tǒng)類替換成你的動態(tài)代理類
方式二、更改方法體的內(nèi)存指向: