欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

AndroidHook相关基础实例

程序员文章站 2022-06-21 20:24:20
Android Hook基础例子前言Hook的流程Android Hook简单例子调用Hook后继续执行核心思想前言Hook是什么?举个例子,有一个人写了一封情书给你喜欢的女孩,在送信的路上你偷偷的把那封情书拿了换成你自己写的情书,再放了回去,那个人拿着你写的情书给了你喜欢的女孩。不要问为什么会有Hook。反正Hook是有广大的应用场景。Hook可以做很多常规开发中由于限制而认为不可能实现的事情。备注说明:前面写的《组件化》框架gradle部分源码已经被我改得面目全非,有空再写一篇文章说明一下。...

前言

Hook是什么?举个例子,有一个人写了一封情书给你喜欢的女孩,在送信的路上你偷偷的把那封情书拿了换成你自己写的情书,再放了回去,那个人拿着你写的情书给了你喜欢的女孩。

不要问为什么会有Hook。反正Hook是有广大的应用场景。

Hook可以做很多常规开发中由于限制而认为不可能实现的事情。

备注说明:前面写的《组件化》框架gradle部分源码已经被我改得面目全非,有空再写一篇文章说明一下。

Hook的流程

Hook 有3步
1.找到替换点
2.构建动态代理对象
3.替换

往往第一步会比较麻烦耗时,因为首先你得把你要Hook的整个流程,关键点都弄清楚,然后再分析出是否有可以Hook的点。

Android Hook简单例子

我们这个简单的例子是这样。
描述如下 (如何实现省略):
新建一个项目,里面很简单,添加一个按钮,点击按钮弹出 :我爱你


        Button button = findViewById(R.id.btn_test);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(DebugActivity.this,  "我爱你", Toast.LENGTH_SHORT).show();
            }
        });

我们通过Hook不修改上面的代码让点击按钮弹出:你是SB

如何分析代码部分省略找到Hook点部分省略。


    private void hookClick(View button) throws Exception {
        //获取到ListenerInfo
        Class mViewClass = Class.forName("android.view.View");
        Method mGetListenerInfoMethod = mViewClass.getDeclaredMethod("getListenerInfo");
        mGetListenerInfoMethod.setAccessible(true);
        Object mListenerInfo = mGetListenerInfoMethod.invoke(button);  
        //设置新OnClickListener的动态代理 
        Object mProxyOnClickListener = Proxy.newProxyInstance(getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Toast.makeText(DebugActivity.this, "你是SB", Toast.LENGTH_SHORT).show();
                return null;
            }
        }); 
        //替换
        mOnClickListenerField.set(mListenerInfo, mProxyOnClickListener);
    }

调用

调用上面这个方法把这个按钮传进去点击就弹出就变成了:你是SB

Hook后继续执行

如果你希望Hook后还能继续执行我爱你,


    private void hookClick(View button) throws Exception {
        //获取到ListenerInfo
        Class mViewClass = Class.forName("android.view.View");
        Method mGetListenerInfoMethod = mViewClass.getDeclaredMethod("getListenerInfo");
        mGetListenerInfoMethod.setAccessible(true);
        Object mListenerInfo = mGetListenerInfoMethod.invoke(button);  
        
        //获取原来已经设置好的mOnClickListener
        Class mListenerInfoViewClass = Class.forName("android.view.View$ListenerInfo");
        Field mOnClickListenerField = mListenerInfoViewClass.getDeclaredField("mOnClickListener");
        mOnClickListenerField.setAccessible(true);
        final Object mOnClickListener = mOnClickListenerField.get(mListenerInfo);
        //设置新OnClickListener的动态代理 
        Object mProxyOnClickListener = Proxy.newProxyInstance(getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Toast.makeText(DebugActivity.this, "我是XXX", Toast.LENGTH_SHORT).show();
                //继续调用这个是核心
                method.invoke(mOnClickListener, args);
                return null;//如果原来的调用是有返回值请  return method.invoke(mOnClickListener, args);
            }
        }); 
        //替换
        mOnClickListenerField.set(mListenerInfo, mProxyOnClickListener);
    }

核心思想

核心思想就是构建一个View.OnClickListener 的动态代理
然后把之前设置好的替换掉

本文地址:https://blog.csdn.net/muxaioxie/article/details/110205606