Hook详解

写在前面

hook(钩子),通常是指对一些方法进行拦截。这样当这些方法被调用时,也能够执行我们自己的代码,从而达到监控或更改代码逻辑的目的。

实现方式

方式一、Java 反射实现Hook:

这种方式是最常见的,也是各种框架常采用的一种方式,直接上例子:

   /**
     * 利用Hook的方式修复Toast在7.1系统上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;
            }
        }
    }

总结一下,此方法的实现思路:

  • 找到需要Hook方法的系统类(最好是单例的情况)

  • 利用java的动态代理这个系统类

  • 使用反射的方法把这个系统类替换成你的动态代理类

方式二、更改方法体的内存指向:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容