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