免注册的Activity
先思考一个问题,为什么我们的Activity需要在AndroidManifest.xml文件中注册?如果不注册能不能启动呢?
我们知道是AMS负责调起Activity。在启动之前他做了些什么事情呢?前面我们说过实际上AMS是给Zygote发送了消息,由Zygote进程fork一个虚拟机进程来。
那么其实在开机时Zygote进程在运行时第一个fork的进程是system_server的进程,这个服务用于管理系统级别的服务启动。
System_server进程包含了以下顶级的系统服务
ActivityManagerService
PowerManagerService
MountService
NetworkManagementService
InputManagerService
WindowManagerService
既然AMS承载了调用逻辑。我们是否可以对AMS动刀子来做到不注册Activity也能直接启动呢?
这里为什么我们前面要讲system_server服务,原因是我们要知道AMS进程不在我们自己的应用内,而是独立的远程服务进程。java层的上的反射是无法做到跨进程的。所以我们可以在自己的应用内利用AIDL的特性拿代理对象,去欺骗AMS服务。
流程如下:
1.我们使用 startActivity(intent);来启动一个Activity。
2.hook住ActivityManager内的本地binder对象,拦截startActivity方法。
3.用动态代理方式将未被注册Activity的Intent替换成已注册的Activity的Intent,并将未被注册的Intent带过去。(替换壳Activity,躲避AMS服务的检查,也就是欺骗AMS)
4.对ActivityThread中的handle进行hook。因为前面替换的是壳子,替换真正要启动的Intent。
5.发送handleMessage消息,启动未被注册的Activity。
实现欺骗:
这里我们通过反射获取到AMS的代理本地代理对象Hook以后动态串改Intent为已注册的来躲避检测
通过动态代理实现对startActivity中的Intent串改,具体逻辑见代码和注释。
hook ActivityThread 中的 handle 在这里我们需要替换我们未被注册的Activity Intent
拦截启动消息
替换我们真实要被启动的Intent
封装以后我们ASMHook将变得非常简单,简单到一行代码就可以实现不注册的情况下启动Activity。
其中HostActivity是我们的壳,OtherActivity是未被注册的。我们可以像平时正常调用API的条件下直接使用startActivity了。
结果 启动了。
哎妈呀,好腻害的样子,喘口气看看刚刚发生了什么事情。
献上封装好的HookAMS菊花(GitHubDemo)