如何应对Andriod面试官 -> 如何 Hook Activity 的启动流程?

💡 原文中文,约15600字,阅读约需38分钟。
📝

内容提要

本章继续解说AMS相关的知识点,包括Hook Activity的发动流程和AndroidManifest.xml中的Activity注册。在发动Activity时,如果没有在AndroidManifest中注册,会抛出异常。Hook Activity的本质是绕过AMS的检查,可以发动未在AndroidManifest中声明的Activity。在发动流程中,需要找到Hook点,一般找public static的方法。可以通过Hook IActivityManager和Hook Handler来实现。

🔎

延伸解读

Hook 的核心思路:绕过 AMS 校验

文章指出,Hook Activity 的本质是绕过 AMS 对 Activity 是否在 AndroidManifest 中注册的检查。具体做法是在 startActivity 时,将目标 Activity 替换为已在 Manifest 中注册的假 Activity,待 AMS 验证通过并返回应用进程后,再替换回真实 Activity。这一过程需要至少两个 Hook 点:一个在 AMS 验证前,一个在验证后。

两个关键 Hook 点:Instrumentation 与 IActivityM

文章提到,Instrumentation 和 IActivityManager 是常用的 Hook 点,分别对应滴滴 VirtualAPK 和 360 DroidPlugin 的方案。寻找 Hook 点时,一般优先选择 public static 的方法,便于反射修改。文中给出了 360 方案中 Hook IActivityManager 的代码示例,通过动态代理替换 startActivity 的参数,将真实 Intent 替换为占位 Intent。

AMS 验证后的恢复:Hook Handler

在 AMS 验证通过后,需要将占位 Activity 替换回目标 Activity。文章展示了通过 Hook ActivityThread 中的 mH Handler 来实现:在 handleMessage 中拦截消息,当消息类型为 159 且包含 LaunchActivityItem 时,从 Intent 中取出之前保存的真实 Intent,并重新设置 Component。这样,最终启动的仍是未在 Manifest 中注册的目标 Activity。

未注册 Activity 的报错来源

文章分析了 Activity 未注册时抛出 ActivityNotFoundException 的流程:在 ActivityStarter 的 executeRequest 中,若无法从 Intent 解析到 ActivityInfo,则返回 START_CLASS_NOT_FOUND,最终在 checkStartActivityResult 中抛出异常。解析 ActivityInfo 依赖于 PackageManagerService 对 AndroidManifest.xml 的解析,若解析不到对应组件,则返回

❓

Q&A

什么是Hook Activity的本质?

Hook Activity的本质是绕过AMS的检查,可以发动未在AndroidManifest中声明的Activity。

如果Activity未在AndroidManifest中注册,会发生什么?

如果Activity未注册,将抛出ActivityNotFoundException异常。

如何实现Hook Activity的过程?

实现Hook Activity的过程需要替换真实的Activity为假的Activity,待AMS验证后再替换回真实Activity。

在Hook Activity时,常用的Hook点有哪些?

常用的Hook点包括Instrumentation和IActivityManager。

如何在AndroidManifest.xml中注册Activity?

Activity的注册是通过解析AndroidManifest.xml文件来完成的。

在启动Activity时,如何处理Intent?

在启动Activity时,需要通过AMS的startActivity方法进行Intent的处理,并检查返回结果。

➡️

继续阅读