运行时Hook所有Block方法调用的技术实现

本文探讨了如何在运行时Hook所有Block方法调用,通过Method Swizzling替换Block的invoke函数,利用保留字段保存原始invoke,并用汇编实现统一的Hook函数。详细介绍了Block的内存布局、类型及其实现原理,以及Hook Block对象的挑战和解决方案。提供了一个名为YSBlockHook的项目作为示例。
摘要由CSDN通过智能技术生成

本技术实现在YSBlockHook中。

1.方法调用的几种Hook机制

iOS系统中一共有:C函数、Block、OC类方法三种形式的方法调用。Hook一个方法调用的目的一般是为了监控拦截或者统计一些系统的行为。Hook的机制有很多种,通常良好的Hook方法都是以AOP的形式来实现的。

当我们想Hook一个OC类的某些具体的方法时可以通过Method Swizzling技术来实现、当我们想Hook动态库中导出的某个C函数时可以通过修改导入函数地址表中的信息来实现(可以使用开源库fishhook来完成)、当我们想Hook所有OC类的方法时则可以通过替换objc_msgSend系列函数来实现。。。

那么对于Block方法呢而言呢?找ios马甲包技术大大上架 Q  51259559 诚信长期合作

2.Block的内部实现原理和实现机制简介

这里假定你对Block内部实现原理和运行机制有所了解,如果不了解则请参考文章《深入解构iOS的block闭包实现原理》或者自行通过搜索引擎搜索。

源程序中定义的每个Block在编译时都会转化为一个和OC类对象布局相似的对象,每个Block也存在着isa这个数据成员,根据isa指向的不同,Block分为__NSStackBlock、__NSMallocBlock、__NSGlobalBlock 三种类型。也就是说从某种程度上Block对象也是一种OC对象。下面的类图描述了Block类的层次结构。

image.png

Block类层次结构图

Block类以及其派生类在CoreFoundation.framework中被定义和实现,并且没有对外公开。

每个Block对象在内存中的布局,也就是Block对象的存储结构被定义如下(代码出自苹果开源出来的库实现libclosure中的文件Block_private.h):

//需要注意的是下面两个只是模板,具体的每个Block定义时总是按这个模板来定义的。//Block描述,每个Block一个描述并定义在全局数据段struct Block_descriptor_1 {    uintptr_t reserved;   //记住这个变量和结构体,它很重要!!    uintptr_t size;};//Block对象的内存布局struct Block_layout {    void *isa;    volatile int32_t flags; // contains ref count    int32_t reserved;    uintptr_t invoke;   //Block对象的实现函数    struct Block_descriptor_1 *descriptor;    // imported variables,这里是每个block对象的特定数据成员区域};

这里要关注一下struct Block_descriptor_1中的reserved这个数据成员,虽然系统没有用到它,但是下面就会用到它而且很重要!

在了解了Block对象的类型以及Block对象的内存布局后,再来考察一下一个Block从定义到调用是如何实现的。就以下面的源代码为例:

int main(int argc, char *argv[]){   //定义    int a = 10;    void (^testblock)(void) = ^(){        NSLog(@"Hello world!%d", a);    };        //执行    testblock();        retu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值