引子
我们已知,OC 中的类也是对象,且对象和类实际上是以结构体的形式存在的(可通过 clang 转换)。在 OC 运行时可以修改对象的方法和属性。那么,这些结论背后的机理是什么呢?
在这篇文章中,我将从类的内存布局以及内存结构方面入手,通过调试 objc runtime 的源代码来厘清上述问题(源代码版本为 objc4-706)。
在上一篇博文“Hook 原理之 CydiaSubstrate(一):MSHookMessageEx”中,我分析了 MSHookMessageEx 以前的老代码,也就是 iOS5 版本。那么在这一篇文中,我将通过逆向来分析新版的 MSHookMessageEx。
两个版本的大部分代码和流程都差不多,主要区别在于,当 hook 的方法不是本类方法的时候,老版本的代码是通过嵌入机器码来获取 IMP,新版本是通过构建 trampoline(蹦床)页来获取 IMP。
CydiaSubstrate,作者为 Jay Freeman(saurik),在iOS7越狱之前名为 MobileSubstrate,因此 CydiaSubstrate 框架中的大部分函数仍以 MS
为前缀。
在用 theos 开发中,control 文件中的 depend 字段依赖库为 mobilesubstrate,该工具是实现 CydiaSubstrate 注入的关键所在,整个工具主要分为 MobileHooker、MobileLoader 以及 Safe mode 三部分。
MobileHooker,是 CydiaSubstrate 的一个组件,对 C 和 Objective-C 均有效。
MobileHooker 组件主要提供了 MSHookMessageEx 和 MSHookFunction 两个函数针对不同语言的 inline hook 功能,其中 MSHookMessageEx 负责用来 hook Objective-C 函数,MSHookFunction 负责用来 hook C/C++ 函数。
————简书作者:HWenj《iOS HOOK》
Method Swizzling 其实就是利用了 runtime
机制,替换了调用的方法(method)的实现(imp)。很多人一看到有 runtime 就头疼了,跟 runloop 一样,由于被太多大牛提起,反而心生胆怯,觉得是一个很难理解的机制。
runtime 运行时机制,主要是在 OC 和 C 语言(或汇编语言)之间架了一座桥梁。比如我之前的文章 通过汇编解读 objc_msgSend 中提到的调用方法的本质是发送消息,方法调用是 OC 中的,而消息发送,找到方法的入口则是 C (或汇编)中的。这其中转换的过程,就是 runtime。