什么是Hook

时间:2021-7-4 作者:qvyue
Hook是什么?

Hook 又叫“钩子”,它可以在事件传送的过程中截获并监控事件的传输,将自身的代码与系统方法进行融入。

这样当这些方法被调用时,也就可以执行我们自己的代码,这也是面向切面编程的思想(AOP)。

示例:Hook 修改 View.OnClickListener 事件

点击事件的方法:

将OnClickListener对象赋予给了ListenerInfo对象的mOnClickListener。

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

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

ListenerInfo类是View的抽象内部类,声明了View的各种事件listener,而我们要找的mOnClickListener就在其中。

    static class ListenerInfo {

        @UnsupportedAppUsage
        ListenerInfo() {
        }
        protected OnFocusChangeListener mOnFocusChangeListener;

        private ArrayList mOnLayoutChangeListeners;

        protected OnScrollChangeListener mOnScrollChangeListener;

        public OnClickListener mOnClickListener;

        protected OnLongClickListener mOnLongClickListener;

        private OnKeyListener mOnKeyListener;

        private OnTouchListener mOnTouchListener;

        private OnHoverListener mOnHoverListener;

        private OnDragListener mOnDragListener;
实现思路:

1.利用反射获取 ListenerInfo 对象
2.获取原始的 OnClickListener事件方法
3.用 Hook代理类 替换原始的 OnClickListener

代码实现:

首先去创建自己需要hook的类:

class MyClickListener implements View.OnClickListener {
    private View.OnClickListener onClickListener;

    public MyClickListener(View.OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }

    @Override
    public void onClick(View v) {
        Toast.makeText(v.getContext(), "系统OnClickListener已经被我替换啦", Toast.LENGTH_SHORT).show();

        onClickListener.onClick(v);
    }
}

去实现偷梁换柱功能:

public class HookHelper {

    public static void hookOnClickListener(View view) throws Exception {
        Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");  //获取getListenerInfo方法
        getListenerInfo.setAccessible(true);

        Object mListenerInfo = getListenerInfo.invoke(view);  //执行完getListenerInfo方法即可返回ListenerInfo对象

        //去得到原始OnClickListener
        Class> aClass = Class.forName("android.view.View$ListenerInfo");
        Field mOnClickListener = aClass.getDeclaredField("mOnClickListener");
        mOnClickListener.setAccessible(true);
        View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(mListenerInfo);//从ListenerInfo中获取原始OnClickListener类对象

        View.OnClickListener hookClickListener = new MyClickListener(originOnClickListener);

        mOnClickListener.set(mListenerInfo, hookClickListener); //将原始的onClickListener替换成自己的
    }
}

最后用一个textView测试结果:

        findViewById(R.id.textView).apply {
            setOnClickListener {  }

            HookHelper.hookOnClickListener(this) 
        }
参考:

Android Hook 机制之简单实战

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。