Aspects 是iOS老牌的AOP库
Aspects主要是利用了forwardInvocation进行转发,Aspects其实利用和kvo类似的原理,通过动态创建子类的方式,把对应的对象isa指针指向创建的子类,然后把子类的forwardInvocation的IMP替成__ASPECTS_ARE_BEING_CALLED__,假设要hook的方法名XX,在子类中添加一个Aspects_XX的方法,然后将Aspects_XX的IMP指向原来的XX方法的IMP,这样方便后面调用原始的方法,再把要hook的方法XX的IMP指向_objc_msgForward,这样就进入了消息转发流程,而forwardInvocation的IMP被替换成了__ASPECTS_ARE_BEING_CALLED__,这样就会进入__ASPECTS_ARE_BEING_CALLED__进行拦截处理
消息转发流程图
Stinger 是饿了么开源的AOP库
没有使用手动消息转发。解析原方法签名,使用libffi中的
ffi_closure_alloc构造与原方法参数一致的”函数” —_stingerIMP,以替换原方法函数指针;此外,生成了原方法和Block的调用的参数模板cif和blockCif。方法调用时,最终会调用到void _st_ffi_function(ffi_cif *cif, void *ret, void **args, void *userdata), 在该函数内,可获取到方法调用的所有参数、返回值位置,主要通过ffi_call根据cif调用原方法实现和切面block。
Method Swizzling
Method originalMethod = class_getInstanceMethod([self class], originalSelector);
Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
BOOL didAddMethod =
class_addMethod([self class],
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod([self class],
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
fishhook
通过fishhook:除了可以hook c函数,fishhook+汇编还可以hook objc_msgSend实现全打点.
Cydia Substrate
Cydia Substrate是一个基于Hook的代码修改框架,可以在Android、iOS平台使用,并实现修改系统默认代码。
method swizzling/Aspects/Stinger对比
| 对比项 | swizzling | Aspects | Stinger |
|---|---|---|---|
| 速度 | 极快 | 慢 | 非常快 |
| Api友好度 | 非常差 | 非常好 | 非常好 |
| 类的hook | 支持 | 支持 | 支持 |
| 实例对象的hook | 不支持 | 支持 | 支持 |
| 调用原方法时改变selector | 修改 | 修改 | 不修改 |
| 方法可能因命名冲突 | 会 | 不会 | 不会 |
| 兼容其他hook方式(RAC, JSPactch…) | 兼容 | 不兼容 | 兼容 |
| 支持多线程增加hook | 自己加锁 | 支持 | 支持 |
| hook可预见性,可追溯性 | 非常差 | 好 | 非常好 |
| 修改父类方法实现 | 可能会 | 不会 | 不会 |
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21722.html
