移动端Hook技术:从编译到运行的全生命周期应用和案例
最新资讯 • 产品资讯
2513
2024-4-26
摘要:
Hook又叫“钩子”,是一项历史悠久的技术。早在PC时代,Hook技术就已存在,并和反Hook技术不断相互促进和迭代。


大家好,为了能与开发者们共同进步,我们今年会新增一个技术专栏,持续分享SDK、前端、数据等相关内容。希望可以和大家一起深入探讨,共同进步。


今天来跟大家分享终端Hook技术。

———————————————————————————————————————————————————————————————————————————

终端上的Hook技术从编译/构建阶段到应用进程内运行时,再到操作系统底层,种类多种多样。如静态编译期间的ASM、Javassist、AspectJ等,运行期间的ART/Dalvik虚拟机Hook、GOT/PLT Hook、Inline Hook等等。
目前友盟+SDK使用Hook技术主要应用于UAPM、反作弊和合规场景中。

HOOK是什么?

Hook又叫“钩子”,是一项历史悠久的技术。早在PC时代,Hook技术就已存在,并和反Hook技术不断相互促进和迭代。在移动端,Hook技术最早应用于安全领域,后续随着移动端发展慢慢也应用和渗透到了其他业务领域。
Android平台Hook技术比较复杂且多样,下面是从App编译/构建期间到上线运行时整个生命周期为线索,汇总和梳理目前不同方式的Hook技术。


从编译阶段将源码编译构建成目前产物(如.apk),到运行时阶段从应用层->Framework层->Native层+Runtime层->linux+kernel层。整个流程中涉及到的Hook技术切点。比如编译期hook(静态hook)、运行时hook(动态hook)、java层hook、native层hook甚至系统层hook。

Hook应用场景

在移动端,Hook的应用场景多种多样,这里列举几个SDK业务涉及的应用场景。

APM启动监控中的插桩实现-利用ASM方式实现的hook

实现效果
Hook技术应用到APM启动分析中,通过ASM方式实现启动监控中的代码插桩。
使用Hook技术前,需要手动埋点方式实现启动分析,埋点代码如下



使用Hook插件方式实现启动分析,只需如下配置即可,避免代码编写,如下:


技术原理
静态Hook实现方法:通过ASM方式实现

1. 依赖内容:
a. Gradle:一个开源的项目构建工具,基于Apache Ant和Apache Maven,并引入基于Groovy的特定领域语言(DSL)而不在使用XML形式管理构建脚本;
b. Groovy:一种开源的脚本语言,在Java基础上进行了扩展,支持闭包、动态类型、元编程等特性,几乎兼容所有Java语法;
c. Transfrom:Gradle Transform API是Android官方提供给开发者用于在项目构建阶段(也就是由.class到.dex转换期间)修改.class文件的一套API。关键API TransformInput是输入文件的抽象,包含1)DirectoryInput集合:以源码方式参与项目编译的所有目录结构及其目录下源码文件;2)JarInput集合:以jar包方式参与项目编译的所有本地jar包和远程jar包;
d. ASM:一个操作和分析java字节码的框架。关键API:ClassVisitor用于访问类成员信息,其中包括标记在类上的注解、类的构造方法、类的字段、类的方法、静态代码块;ClassWriter用于重新构建编译后的类,比如修改类名、属性、方法,以及生成新的类字节码文件。

2. 实现原理:
自定义Gradle Plugin注册Transform对象,在transform方法里分别遍历目录和jar包获取所有的.class文件,然后利用ASM的相关API加载、解析、匹配相应的.class文件以及相关的方法,匹配后修改相应的方法从而达到动态插入代码的效果。

需要注意:
1. 保证原始性:插桩后要保证和插桩前的业务代码逻辑一致,也就是要保证整个编译链条的链式调用不能使其中断,要尽可能早地拿到起始点并找到输入节点,处理完成后将编译产物对接上下一个节点,保证整个过程中不丢失和错误写入文件。如果出现错误,很可能编译通过但安装运行时出现错误,如下:

这时反编译查看dex为空。
2. 保证效率:开发者使用插件会比之前编译更加耗时些,尤其对于比较大的项目工程。如果插件中有二次遍历、组装类的树形结构等,则编译时间会更长甚至翻倍增长。这时需要考虑增量编译和高效的处理jar文件的解压、class文件的IO等,后续还会考虑加入并发的处理。同时如果项目中会涉及多个transform流程,需要提取出一个通用的transform基类。
3. 保证兼容性:包括兼容不同的Java版本(如Java7、Java8等);兼容不同的Gradle版本;兼容asm版本;甚至兼容其他插件等。
4. 保证智能性:一般开发者使用插桩插件是为了降低研发成本提升效率,比如自动插入要写入的预定代码而非手动实现API,这时就需要插件可以自动识别Actiity(需要区分页面展示activity并非节点activity)、application、抽象/空方法等。

类似方案:
其他实现方式:Javassist(一个处理Java字节码的类库)、AspectJ(AOP的实现)、AST(抽象语法树)。
此场景考虑需要对三方库的支持以及对D8等的兼容,放弃了通过AspectJ实现,同时考虑后续支持Lambda语法以及方法插桩位置的通用性,放弃了通过AST实现,最终考虑业界通用性我们选择使用ASM来实现代码的插入。

黑产模拟-虚拟机Hook

实现效果
正常获取IMEI的代码逻辑:


通过Hook技术后,运行在同样的设备上时返回的结果差异如下,行业中部分低成本黑产厂商会采用此方法在刷量等场景中使用。
正常调用系统API返回的IMEI结果


使用Hook技术后调用系统API返回的IMEI结果


技术原理
Xposed等方式实现
1. 一种是root权限下的hook,直接hook系统从而可以hook所有应用,如Xposed框架、Substrate框架等;另一种是非root权限下的hook,只能hook加载进程应用的自身,如legend框架等。当然也包括阿里的Dexposed以及后来的AndFix,主要应用到了阿里的热修复能力上;
2. 由于涉及修改ART/Dalvik虚拟机,所以每次Android系统的更新迭代都会需要升级适配,从而导致稳定性相对较差,但由于灵活度相对较高,目前已成为hook Java层很普及的方式;
3. 在自动化测试中有很好的应用;
4. 友盟SDK侧主要实践:主要用于反作弊产品的黑产模拟和测试。

APM中线程、内存等监控的实现-Native Hook

实现效果
以线程监控为例


在如上代码中,通过Hook技术就可以实现该线程的监控,参考日志如下:


技术原理
GOT/PLT Hook
GOT(The Global Offset Table)保存着全局的偏移量表。简单来说就是在数据段的地址表,假定有一些代码段的指令引用一些地址变量,编译器会引用 GOT 表来替代直接引用绝对地址,因为绝对地址在编译期是无法知道的,只有重定位后才会得到 ,GOT 自己本身将会包含函数引用的绝对地址。
PLT(The Procedure Linkage Table)该节保存过程链接表。PLT 不同于 GOT,它位于代码段,动态库的每一个外部函数都会在 PLT 中有一条记录,每一条 PLT 记录都是一小段可执行代码。 一般来说,外部代码都是在调用 PLT 表里的记录,然后 PLT 的相应记录会负责调用实际的函数。

详细可参考《ELF文件装载链接过程及hook原理》

Android进程(linux进程)加载动态链接库的时候,都是通过dlopen()函数去把SO读入到当前进程中的一个内存区域中。当调用so代码时可以直接跳转到so的内存区域去执行,也就是包含了so对外提供的函数表及函数地址,所以可以修改函数地址从而达到hook的能力。
这种hook只能hook .so的入口函数,无法hook 内部函数。

Inline Hook
函数内部的hook。将函数开始(Prologue)处的指令更替为跳转指令,使得原函数直接跳转到 Hook 的目标函数函数,并保留原函数的调用接口以完成后续再调用回来的目的。
与 GOT/PLT Hook 相比,Inline Hook 可以不受 GOT/PLT 表的限制,几乎可以 Hook 任何函数。不过其实现十分复杂,目前还没有可以用在生产环境的实现(因为是直接去改so,所以和指令平台强相关,armv7,armv8,arm64,x86, Thumb指令集都需要去针对性的实现)。

合规检测的实现-系统Hook

实现效果




技术原理
1、Linux Kernel Hook通过编写LKM(Loadable Kernel Modules 可加载内核模块)来扩展Linux内核的功能,LKM相对于直接在内核中添加代码而言,具有可插拔,无需重新编译内核的特点,也就是说内核系统调用Hook的代码需要通过内核模块的方式加载进入内核中;
2、系统调用流程;
3、从用户层到内核层的最关键的一个点在于sys_call_table中的内容,如果修改了sys_call_table中调用号对应的地址到所插入的LKM中函数的地址,就可以完成对特定系统调用的Hook。

✍️如果大家喜欢这篇干货并有想要探讨的技术内容,欢迎点赞、留言哦。

———————————————————————————————————————————————————————————————————————————

友盟+企业采购季,全场低至8折,新客买一年再送1个月,全面助力开发者高效管理数据,用好数据!点击图片,了解详情↓