美文网首页
Hook技术 —— 拦截系统Intent

Hook技术 —— 拦截系统Intent

作者: 设计失 | 来源:发表于2018-09-11 17:03 被阅读47次

    首先说下什么是 Hook (钩子函数):

    钩子函数其实一段程序,在系统的调用中挂载到系统,在没有调用该函数之前,钩子程序先捕获该消息,这样钩子函数先得到控制权,这样钩子函数就可以加工处理该函数的执行从而改变消息的传递。


    Hook技术实现的过程:(java层)


    1) 找到Hook点

    ① hook的过程是一个找方法的过程,我们要找到微信怎么登录的,就需要找到微信登录的方法。

    ② 需要满足的条件 :对象一定是静态

    2)找到hook方法执行前的代码



    一、 找到拦截系统Intent 的 Hook点

    Activity的启动过程 我们了解到,在开启一个Activity的时候,会调用若干的方法,仔细一点我们发现其中有一个

    int result = ActivityManagerNative.getDefault()
                                        .startActivity(whoThread,
                                        who.getBasePackageName(),
                                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                                        token, 
                                        target, 
                                        0, 
                                        null, 
                                        options);
    

    在ActivityManagerNative.getDefault() 中返回了一个对象,虽然是一个静态方法,但是我们需要一个静态对象:

    static public IActivityManager getDefault() {
            return gDefault.get();
        }
    

    再来看下 gDefault 对象:

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                IBinder b = ServiceManager.getService("activity");
                if (false) {
                    Log.v("ActivityManager", "default service binder = " + b);
                }
                IActivityManager am = asInterface(b);
                if (false) {
                    Log.v("ActivityManager", "default service = " + am);
                }
                return am;
            }
        };
    

    看到 private static final 我们知道这是一个静态的final类型的成员变量,而Singleton是个什么呢?按照字面意思,该类是一个单例类,具体:

    public abstract class Singleton<T> {
        private T mInstance;
    
        protected abstract T create();
    
        public final T get() {
            synchronized (this) {
                if (mInstance == null) {
                    mInstance = create();
                }
                return mInstance;
            }
        }
    }
    

    通过单例的方式来让继承实现其中的create() 方法,返回IActivityManager,但是IActivityManager只是Singleton的成员变量,不过Singleton既然是静态单例,所以也能反射拿到其中的成员。

    好了,到此我们就找到了系统的hook点,下面实现:

    先还原 gDefault 对象
    try {
        // 还原 gDefault() 成员
        Class activityManagerNative = Class.forName("android.app.ActivityManagerNative");
        // 获取到成员变量
        Field gDefault = activityManagerNative.getDeclaredField("gDefault");
        gDefault.setAccessible(true);
        // 获取类成员变量,直接传空,因为是静态变量,所以获取到的是系统值,
        // 得到Singleton 静态类,
        Object defaultValue = gDefault.get(null);
        //mInstance对象
        Class<?> singletonClass=Class.forName("android.util.Singleton");
        Field mInstance = singletonClass.getDeclaredField("mInstance");
        mInstance.setAccessible(true);
        // 获取到成员变量
        Object iActivityManagerObject = mInstance.get(defaultValue);
    } catch (Exception e) {
      e.printStackTrace();
    }
    

    上面获取到了IActivityManager对象,接下来我们要将我们的代码插入到其中,相当于拦截系统的操作,执行我们的逻辑代码,而实现该操作有两种方式,一个是 动态代理, 另外一个是 实现接口的方式,而动态代理是万能的,实现接口需要将hook到的对象实现一个接口,但是我们获取到的IActivityManager对象本事就是一个接口,不能再实现接口,所以这里我们只能用动态代理的方式进行插入,这里我们用到系统的Proxy

    // 实现该接口
    Class iActivityManagerIntercept = Class.forName("android.app.IActivityManager");
    StartActivity startActivity = new StartActivity(iActivityManagerObject);
    /**
     * ClassLoader loader  当前的类加载器
     * Class<?>[] interfaces  返回的类将会实现的接口
     * InvocationHandler h 实现了InvocationHandler 接口的代理类,以便实现系统分发出来的方法,实现拦截操作
     */
    Object oldIActivityManager = Proxy.newProxyInstance(
                   Thread.currentThread().getContextClassLoader(),
                   new Class[]{iActivityManagerIntercept},
                   startActivity
    );
    // 将我们获取到的值设置进去
    mInstance.set(defaultValue, oldIActivityManager);
    

    看下StartActivity

      /**
         * 拦截类
         */
        class StartActivity implements InvocationHandler {
    
            private Object iActivityManager;
    
            public StartActivity(Object iActivityManager) {
                this.iActivityManager = iActivityManager;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Log.i("Ellison", " =========  invoke   =========");
    
                if ("startActivity".equals(method.getName())) {
                    Log.d("Ellison", "---------startActivity----------");
                }
    
                return method.invoke(iActivityManager, args);
            }
        }
    
    
    // 打印的结果:
     =========  invoke   =========getActivityDisplayId
     =========  invoke   =========setTaskDescription
     =========  invoke   =========checkPermission
     =========  invoke   =========checkPermission
     =========  invoke   =========getActivityOptions
     =========  invoke   =========getActivityOptions
    derer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
           
           [ 04-20 08:53:02.868  5687: 5687 D/         ]
           HostConnection::get() New Host Connection establi
     =========  invoke   =========activityResumed
     =========  invoke   =========activityIdle
     =========  invoke   =========getContentProvider
     =========  invoke   =========startActivity
     ---------startActivity----------
      =========  invoke   =========activityPaused
      =========  invoke   =========getActivityDisplayId
      =========  invoke   =========setTaskDescription
      =========  invoke   =========getActivityOptions
      =========  invoke   =========getActivityOptions
      =========  invoke   =========activityResumed
    nderer: endAllStagingAnimators on 0xb2b7c780 (RippleDrawable) with handle 0xae59
      =========  invoke   =========activityIdle
      =========  invoke   =========activityStopped
    

    到此,我们可以Hook到系统的API~~~

    相关文章

      网友评论

          本文标题:Hook技术 —— 拦截系统Intent

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