美文网首页
hook安卓代码入门

hook安卓代码入门

作者: yuLiangC | 来源:发表于2020-12-27 15:41 被阅读0次

    hook定义
    hook,钩子。勾住系统的程序逻辑。
    在某段SDK源码逻辑执行的过程中,通过代码手段拦截执行该逻辑,加入自己的代码逻辑。
    原理其实很简单:就是通过动态代理拿到想要覆盖的接口方法,重写该方法,然后将该方法替换掉原来的执行方法就行了
    重要就是两点:1.使用反射知识。2.找到想要hook的源码方法。
    先来看一个简单例子,比如我们有一个点击方法是这么写的:

            TextView hookTv = findViewById(R.id.hookTv);
            hookTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(MainActivity.this,"hoot之前。。。",Toast.LENGTH_SHORT).show();
                }
            });
    

    现在想要覆盖掉这个点击方法,使得我们点击hookTV的时候弹出“我就是hook之后的方法”提示,该怎么做呢?废话不说,上代码先:

            TextView hookTv = findViewById(R.id.hookTv);
            hookTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(MainActivity.this,"hoot之前。。。",Toast.LENGTH_SHORT).show();
                }
            });
    
            //hook方法,覆盖掉原来的点击方法
            hookTextView(hookTv);
    

    如上,我们只加了一个hookTextView方法。想要覆盖掉原来的点击方法,就得反射找到新的点击方法。具体步骤如下:
    1.反射拿到View.OnClickListener()这个接口持有者的实例对象ListenerInfo。
    2.反射拿到点击事件mOnClickListener对象。
    3.创建我们自己的动态代理OnClickListener的实现方法 proxyOnClickListener 类。
    4.将我们自己的代理类设置到ListenerInfo中。

        private void hookTextView(TextView hookTv) {
            //找到View.OnClickListener()接口并重写该方法
            try {
                // 反射执行View类的getListenerInfo()方法,拿到v的mListenerInfo对象,这个对象就是点击事件的持有者
                Method method = View.class.getDeclaredMethod("getListenerInfo");
                method.setAccessible(true);//由于getListenerInfo()方法并不是public的,所以要加这个代码来保证访问权限
                Object mListenerInfo = method.invoke(hookTv);//这里拿到的就是mListenerInfo对象,也就是点击事件的持有者
    
                //要从这里面拿到当前的点击事件对象
                Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");// 这是内部类的表示方法
                Field field = listenerInfoClz.getDeclaredField("mOnClickListener");
                final View.OnClickListener onClickListenerInstance = (View.OnClickListener) field.get(mListenerInfo);//取得真实的mOnClickListener对象
    
                //2. 创建我们自己的点击事件代理类
                //   方式1:自己创建代理类
                //   ProxyOnClickListener proxyOnClickListener = new ProxyOnClickListener(onClickListenerInstance);
                //   方式2:由于View.OnClickListener是一个接口,所以可以直接用动态代理模式
                // Proxy.newProxyInstance的3个参数依次分别是:
                // 本地的类加载器;
                // 代理类的对象所继承的接口(用Class数组表示,支持多个接口)
                // 代理类的实际逻辑,封装在new出来的InvocationHandler内
                Object proxyOnClickListener = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Log.d("HookSetOnClickListener", "点击事件被hook到了");//加入自己的逻辑
                        return method.invoke(onClickListenerInstance, args);//执行被代理的对象的逻辑
                    }
                });
                //3. 用我们自己的点击事件代理类,设置到"持有者"中
                field.set(mListenerInfo, proxyOnClickListener);
                //完成
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    

    相关文章

      网友评论

          本文标题:hook安卓代码入门

          本文链接:https://www.haomeiwen.com/subject/mxyonktx.html