Hook技术实现绕过AMS对Activity的检查实现集中登录框
2022-06-10 本文已影响0人
carlwu_186
动态代理方式HOOk到系统的ActivityManager
-
Activity.startActivity最终会调用到ActivityManager里面的IActivityManager的startActivity方法,IActivityManager是一个android.os.IInterface,系统的IActivityManager.aidl生成,里面声明了startActivity等方法。它里面的Stub就是一个android.os.Binder,所以启动Activity就是调用到了Binder驱动。 -
ActivityManager里面有一个static的成员Singleton<IActivityTaskManager> IActivityTaskManagerSingleton 里面存放了IActivityManager的Binder实现,所以可以通过反射, 重写对这个IActivityManager赋值为原IActivityManager对象的一个动态代理,在代理方法执行原本方法前,篡改startActivity的Intent参数Component为一个已在Manifest中注册过的空壳Activity:ProxyActivity,同时把真是的Component作为ExtraData保存在Intent中备用(realIntent),再把这个Intent发送给系统,系统就会去打开我们的空壳ProxyActivity。 - Binder驱动收到了startActivity事件后,转发给AMS,AMS进行检查(比如是否在Manifest注册过了)后,将事件包装成一个HandlerMessage,发送给目标程序UI线程的Looper.MessageQueue。
给ActivityThread的sMainThreadHandler指定mCallback的方式Hook,修改Message内容
- Android应用程序的入口
ActivityThread.main中,启动了UI线程的Looper,ActivityThread有自己的Handler实例,它内部的handleMessage方法就处理系统发送给它的各种Message。 - 研究Handler的
dispatchMessage方法,发现它优先使用mCallback处理msg,然后才会使用Handler自身的handleMessage方法。
image.png
所以可以反射拿到ActivityThread里面的sMainThreadHandler,对它设置mCallback,就可以篡改msg的内容后再通知sMainThreadHandler正常处理。 - 我们就可以在自己实现的
mCallback中,当msg是开启Activity时,判断是否有登录过,修改Intent的内容,让程序跳转到一个登录Activity、或者取出realIntent还原Intent,跳转到真正的目标Activity。 - Hook到
mCallback中修改开启的Activity的Intent,即使目标Activity没有在Manifest中注册过,也可以正常跳转过去。因为系统的检查过程是调用者发送Binder事件给AMS,AMS检查时我们用动态代理方式修改了Intent目标为一个注册过了的ProxyActivity,骗过了AMS,ActivityThread的Handler实例收到来自Binder驱动的事件,只负责执行,不会再去检验Intent内容是否注册过。
Hook技术总结
- 前面的第一种Hook方式,我们抓住了系统的ActivityManager中
IActivityManager被静态成员持有的特性,就可以直接通过ActivityManager.class反射取出IActivityManager对象。我们的目的是干预IActivityManager对象内部方法的执行,所以必须要替换ActivityManager中IActivityManager对象,但是我们不能直接new一个IActivityManager对象替换进去,因为它来自系统的创建,里面方法的实现调用到了系统,我们自己new没办法做到。这时就可以考虑用代理的方式来做。 - 第一种是静态代理,比如我们自己new出对象替换系统的,自己new的对象在实现方法时,最后也可以调用到原本对象对应的方法上去。程序员需要编写好静态代理类的源代码参与编译。
- 第二种时动态代理,我们没办法自己或者不方便new出对象,可以用
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
我们可以在InvocationHandler 里面对方法的执行进行干预,最后也可以调用到原本对象对应的方法上去。动态代理要求代理对象必须是接口的实现,程序在运行时通过反射机制动态的生成代理类。