Android 进阶答疑:Hook

接下来深海会和大家逐步分享分析Android插件化相关的东西

要了解插件化首先要具备三个前提条件:

1.Android 系统源码阅读于理解

2.Java 反射机制

3.Hook技术

今天咱们就一起分析Hook的相关知识

一.Hook是什么?

      在事件执行的过程中截获并监控事件的执行流,将自身的代码融入其执行流中

二.简单举例: Hook 修改 View.OnClickListener 事件

首先阅读系统类View的源码,找到Hook点击事件的关键代码

看点击事件的方法:这边传入的事件赋给了ListenerInfo对象的mOnClickListener接口实例

public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }

追溯该方法:该方法返回了ListenerInfo对象

 @UnsupportedAppUsage
    ListenerInfo getListenerInfo() {
        if (mListenerInfo != null) {
            return mListenerInfo;
        }
        mListenerInfo = new ListenerInfo();
        return mListenerInfo;
    }

然后整理结构:

得出Hook路线:

1.拿到View对象中的mListenerInfo对象

2.然后拿到mOnClickListener接口实例

3.对该实例进行二次封装后替换该实例

具体实现代码:

/*
 *作者:赵星海
 *时间:2020/6/23 9:51
 *用途:Hook简单举例(View点击事件)
 */
public static void hookOnClickListener(View view) throws Exception {
        // 第一步:反射得到 ListenerInfo 对象
        Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
        getListenerInfo.setAccessible(true);
        Object listenerInfo = getListenerInfo.invoke(view);
        // 第二步:得到原始的 OnClickListener事件方法
        Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
        Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
        mOnClickListener.setAccessible(true);
        View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo);
        // 第三步:用 Hook代理类 替换原始的 OnClickListener
        View.OnClickListener hookedOnClickListener = new HookedClickListener(originOnClickListener);
        mOnClickListener.set(listenerInfo, hookedOnClickListener);
    }

    public static class HookedClickListener implements View.OnClickListener {

        private View.OnClickListener origin;

        public HookedClickListener(View.OnClickListener origin) {
            this.origin = origin;
        }

        @Override
        public void onClick(View v) {
            // Toast.makeText(v.getContext(), "你的点击事件被赵星海劫持了!", Toast.LENGTH_SHORT).show();
            if (origin != null) {
                origin.onClick(v);
            }
        }

    }

好了今天的分享就到这里哦,关于上诉内容,有任何的疑惑或者建议欢迎评论区沟通交流哦~

深海特别愿意和大家一起互相学习互相进步
 

猜你喜欢

转载自blog.csdn.net/qq_39731011/article/details/106937009
今日推荐