区块链技术博客
www.b2bchain.cn

iOS HOOK 总结求职学习资料

本文介绍了iOS HOOK 总结求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

这篇博客总结下iOS中常用的hook方法和原理,所谓hook也就是侵入原有的方法实现,在运行时改变方法
持续更新ing…

原始Method Swizzling

参考nshipster的文章,感觉都是上个世纪的文章了。。

最基本的Method Swizzling就是写一个新的实现,然后将selector映射到新的实现上:

+ (void)load {     SEL originalSelector = (viewDidLoad);     SEL newSelector = (swizzle_viewDidLoad);      Method originalMethod = class_getInstanceMethod(ViewController.class, originalSelector);     Method newMethod = class_getInstanceMethod(ViewController.class, newSelector);      method_exchangeImplementations(originalMethod, newMethod); }  - (void)viewDidLoad {     [super viewDidLoad];  }  - (void)swizzle_viewDidLoad {     [self swizzle_viewDidLoad];     NSLog(@"swizzle yes"); }

那么上面的viewDidLoadswizzle_viewDidLoad的实现就被替换了,当View加载完成调用viewDidLoad时,内部实现换成了[self swizzle_viewDidLoad];NSLog(@"swizzle yes");,当内部实现又调用swizzle_viewDidLoad时,swizzle_viewDidLoad的内部实现又被换成了[super viewDidLoad];,所以最后相当于调用了[super viewDidLoad];NSLog(@"swizzle yes");

上面简简单单的几行代码,涉及了多个runtime用法:

load

+(void) load{}NSObject带的方法,执行时机是当一个类被首次加载时,在main.m之前执行

Invoked whenever a class or category is added to the Objective-C runtime;

load的加载顺序:

  • A class’s +load method is called after all of its superclasses’ +load methods.

  • A category +load method is called after the class’s own +load method.

所以当一个类(非category)开始执行load方法时,这个类(非category)和它的父类及其父类们(非category)的属性和方法已经加载到runtime里了

知道上面的load加载顺序就可以在category里再进行一次Method Swizzling:

 ViewController (XYCategory)  + (void)load {      Method originalMethod = class_getInstanceMethod(ViewController.class, (viewDidLoad));     Method newMethod = class_getInstanceMethod(ViewController.class, (category_viewDidLoad));      method_exchangeImplementations(originalMethod, newMethod); }  - (void)category_viewDidLoad {     [self category_viewDidLoad];     NSLog(@"category_viewDidLoad"); }

此时的输出:

2020-08-18 17:15:17.632097+0800 HookDemo[47773:7027151] swizzle yes 2020-08-18 17:15:17.632200+0800 HookDemo[47773:7027151] category_viewDidLoad

但多个category之间 和 父类的cateogry和子类主类 的load加载顺序是不定的

load 和 dyld

这里要细讲下dyld(其实也不是特别细,源码我没看懂。。),是因为遇到了一个问题:【父类的+(void) load方法】和【子类结构加载进runtime】哪个先执行,按照官方文档的解释很容易得出错误结论,但实际上是【子类加载进runtime】要比【父类的+(void) load方法】先执行,下面进行源码解析:

以下内容参考自参考博客和这一篇博客

dyld(动态链接器):就是在应用被编译打包成可执行文件格式的 Mach-O 文件之后 ,交由 dyld 负责链接 , 加载程序;实际上就是点以下APP图标,系统内核会给你开一个进程,然后dyld就开始加载工程的可执行文件了(Mach-O)

此外像UIKit/Foundation这些系统库并不会存在每一个应用的Mach-O文件中,比如对于iOS系统来说每一个APP用到的这些系统库都是同一份,这些库都存放在动态库共享缓存区(dyld shared cache)

Foundation库的NSLog方法为例子,我们代码中使用NSLog到底是如何调用NSLog的实现的:

  • 在工程编译时 , 所产生的 Mach-O 可执行文件中会预留出一段空间 , 这个空间其实就是符号表 , 存放在 _DATA 数据段中 ( 因为 _DATA 段在运行时是可读可写的 )

  • 编译时 : 工程中所有引用了共享缓存区中的系统库方法 , 其指向的地址设置成符号地址 , ( 例如工程中有一个 NSLog , 那么编译时就会在 Mach-O 中创建一个 NSLog 的符号 , 工程中的 NSLog 就指向这个符号 )

  • 运行时 : 当 dyld将应用进程加载到内存中时 , 根据 load commands 中列出的需要加载哪些库文件 , 去做绑定的操作 ( 以 NSLog 为例 , dyld 就会去找到 Foundation 中 NSLog 的真实地址写到 _DATA 段的符号表中 NSLog 的符号上面 )

runtime

nshipste给的事例在load里加了dispatch_once,但我认为没有啥必要,load是只会运行一次的

对于Method的结构:

struct objc_method {     SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;     char * _Nullable method_types                            OBJC2_UNAVAILABLE;     IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE; } typedef struct objc_method *Method;

可以看到objc_method结构体就定义了一个完整的方法实现:

  1. method_name:方法名
  2. method_types:方法的参数和返回值类型
  3. method_imp:方法的具体实现指针

method_exchangeImplementations就是调换两个objc_methodmethod_imp

RSSwizzle

这篇博客总结下iOS中常用的hook方法和原理,所谓hook也就是侵入原有的方法实现,在运行时改变方法
持续更新ing…

原始Method Swizzling

参考nshipster的文章,感觉都是上个世纪的文章了。。

最基本的Method Swizzling就是写一个新的实现,然后将selector映射到新的实现上:

+ (void)load {     SEL originalSelector = (viewDidLoad);     SEL newSelector = (swizzle_viewDidLoad);      Method originalMethod = class_getInstanceMethod(ViewController.class, originalSelector);     Method newMethod = class_getInstanceMethod(ViewController.class, newSelector);      method_exchangeImplementations(originalMethod, newMethod); }  - (void)viewDidLoad {     [super viewDidLoad];  }  - (void)swizzle_viewDidLoad {     [self swizzle_viewDidLoad];     NSLog(@"swizzle yes"); }

那么上面的viewDidLoadswizzle_viewDidLoad的实现就被替换了,当View加载完成调用viewDidLoad时,内部实现换成了[self swizzle_viewDidLoad];NSLog(@"swizzle yes");,当内部实现又调用swizzle_viewDidLoad时,swizzle_viewDidLoad的内部实现又被换成了[super viewDidLoad];,所以最后相当于调用了[super viewDidLoad];NSLog(@"swizzle yes");

上面简简单单的几行代码,涉及了多个runtime用法:

load

+(void) load{}NSObject带的方法,执行时机是当一个类被首次加载时,在main.m之前执行

Invoked whenever a class or category is added to the Objective-C runtime;

load的加载顺序:

  • A class’s +load method is called after all of its superclasses’ +load methods.

  • A category +load method is called after the class’s own +load method.

所以当一个类(非category)开始执行load方法时,这个类(非category)和它的父类及其父类们(非category)的属性和方法已经加载到runtime里了

知道上面的load加载顺序就可以在category里再进行一次Method Swizzling:

 ViewController (XYCategory)  + (void)load {      Method originalMethod = class_getInstanceMethod(ViewController.class, (viewDidLoad));     Method newMethod = class_getInstanceMethod(ViewController.class, (category_viewDidLoad));      method_exchangeImplementations(originalMethod, newMethod); }  - (void)category_viewDidLoad {     [self category_viewDidLoad];     NSLog(@"category_viewDidLoad"); }

此时的输出:

2020-08-18 17:15:17.632097+0800 HookDemo[47773:7027151] swizzle yes 2020-08-18 17:15:17.632200+0800 HookDemo[47773:7027151] category_viewDidLoad

但多个category之间 和 父类的cateogry和子类主类 的load加载顺序是不定的

load 和 dyld

这里要细讲下dyld(其实也不是特别细,源码我没看懂。。),是因为遇到了一个问题:【父类的+(void) load方法】和【子类结构加载进runtime】哪个先执行,按照官方文档的解释很容易得出错误结论,但实际上是【子类加载进runtime】要比【父类的+(void) load方法】先执行,下面进行源码解析:

以下内容参考自参考博客和这一篇博客

dyld(动态链接器):就是在应用被编译打包成可执行文件格式的 Mach-O 文件之后 ,交由 dyld 负责链接 , 加载程序;实际上就是点以下APP图标,系统内核会给你开一个进程,然后dyld就开始加载工程的可执行文件了(Mach-O)

此外像UIKit/Foundation这些系统库并不会存在每一个应用的Mach-O文件中,比如对于iOS系统来说每一个APP用到的这些系统库都是同一份,这些库都存放在动态库共享缓存区(dyld shared cache)

Foundation库的NSLog方法为例子,我们代码中使用NSLog到底是如何调用NSLog的实现的:

  • 在工程编译时 , 所产生的 Mach-O 可执行文件中会预留出一段空间 , 这个空间其实就是符号表 , 存放在 _DATA 数据段中 ( 因为 _DATA 段在运行时是可读可写的 )

  • 编译时 : 工程中所有引用了共享缓存区中的系统库方法 , 其指向的地址设置成符号地址 , ( 例如工程中有一个 NSLog , 那么编译时就会在 Mach-O 中创建一个 NSLog 的符号 , 工程中的 NSLog 就指向这个符号 )

  • 运行时 : 当 dyld将应用进程加载到内存中时 , 根据 load commands 中列出的需要加载哪些库文件 , 去做绑定的操作 ( 以 NSLog 为例 , dyld 就会去找到 Foundation 中 NSLog 的真实地址写到 _DATA 段的符号表中 NSLog 的符号上面 )

runtime

nshipste给的事例在load里加了dispatch_once,但我认为没有啥必要,load是只会运行一次的

对于Method的结构:

struct objc_method {     SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;     char * _Nullable method_types                            OBJC2_UNAVAILABLE;     IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE; } typedef struct objc_method *Method;

可以看到objc_method结构体就定义了一个完整的方法实现:

  1. method_name:方法名
  2. method_types:方法的参数和返回值类型
  3. method_imp:方法的具体实现指针

method_exchangeImplementations就是调换两个objc_methodmethod_imp

RSSwizzle

这篇博客总结下iOS中常用的hook方法和原理,所谓hook也就是侵入原有的方法实现,在运行时改变方法
持续更新ing…

原始Method Swizzling

参考nshipster的文章,感觉都是上个世纪的文章了。。

最基本的Method Swizzling就是写一个新的实现,然后将selector映射到新的实现上:

+ (void)load {     SEL originalSelector = (viewDidLoad);     SEL newSelector = (swizzle_viewDidLoad);      Method originalMethod = class_getInstanceMethod(ViewController.class, originalSelector);     Method newMethod = class_getInstanceMethod(ViewController.class, newSelector);      method_exchangeImplementations(originalMethod, newMethod); }  - (void)viewDidLoad {     [super viewDidLoad];  }  - (void)swizzle_viewDidLoad {     [self swizzle_viewDidLoad];     NSLog(@"swizzle yes"); }

那么上面的viewDidLoadswizzle_viewDidLoad的实现就被替换了,当View加载完成调用viewDidLoad时,内部实现换成了[self swizzle_viewDidLoad];NSLog(@"swizzle yes");,当内部实现又调用swizzle_viewDidLoad时,swizzle_viewDidLoad的内部实现又被换成了[super viewDidLoad];,所以最后相当于调用了[super viewDidLoad];NSLog(@"swizzle yes");

上面简简单单的几行代码,涉及了多个runtime用法:

load

+(void) load{}NSObject带的方法,执行时机是当一个类被首次加载时,在main.m之前执行

Invoked whenever a class or category is added to the Objective-C runtime;

load的加载顺序:

  • A class’s +load method is called after all of its superclasses’ +load methods.

  • A category +load method is called after the class’s own +load method.

所以当一个类(非category)开始执行load方法时,这个类(非category)和它的父类及其父类们(非category)的属性和方法已经加载到runtime里了

知道上面的load加载顺序就可以在category里再进行一次Method Swizzling:

 ViewController (XYCategory)  + (void)load {      Method originalMethod = class_getInstanceMethod(ViewController.class, (viewDidLoad));     Method newMethod = class_getInstanceMethod(ViewController.class, (category_viewDidLoad));      method_exchangeImplementations(originalMethod, newMethod); }  - (void)category_viewDidLoad {     [self category_viewDidLoad];     NSLog(@"category_viewDidLoad"); }

此时的输出:

2020-08-18 17:15:17.632097+0800 HookDemo[47773:7027151] swizzle yes 2020-08-18 17:15:17.632200+0800 HookDemo[47773:7027151] category_viewDidLoad

但多个category之间 和 父类的cateogry和子类主类 的load加载顺序是不定的

load 和 dyld

这里要细讲下dyld(其实也不是特别细,源码我没看懂。。),是因为遇到了一个问题:【父类的+(void) load方法】和【子类结构加载进runtime】哪个先执行,按照官方文档的解释很容易得出错误结论,但实际上是【子类加载进runtime】要比【父类的+(void) load方法】先执行,下面进行源码解析:

以下内容参考自参考博客和这一篇博客

dyld(动态链接器):就是在应用被编译打包成可执行文件格式的 Mach-O 文件之后 ,交由 dyld 负责链接 , 加载程序;实际上就是点以下APP图标,系统内核会给你开一个进程,然后dyld就开始加载工程的可执行文件了(Mach-O)

此外像UIKit/Foundation这些系统库并不会存在每一个应用的Mach-O文件中,比如对于iOS系统来说每一个APP用到的这些系统库都是同一份,这些库都存放在动态库共享缓存区(dyld shared cache)

Foundation库的NSLog方法为例子,我们代码中使用NSLog到底是如何调用NSLog的实现的:

  • 在工程编译时 , 所产生的 Mach-O 可执行文件中会预留出一段空间 , 这个空间其实就是符号表 , 存放在 _DATA 数据段中 ( 因为 _DATA 段在运行时是可读可写的 )

  • 编译时 : 工程中所有引用了共享缓存区中的系统库方法 , 其指向的地址设置成符号地址 , ( 例如工程中有一个 NSLog , 那么编译时就会在 Mach-O 中创建一个 NSLog 的符号 , 工程中的 NSLog 就指向这个符号 )

  • 运行时 : 当 dyld将应用进程加载到内存中时 , 根据 load commands 中列出的需要加载哪些库文件 , 去做绑定的操作 ( 以 NSLog 为例 , dyld 就会去找到 Foundation 中 NSLog 的真实地址写到 _DATA 段的符号表中 NSLog 的符号上面 )

runtime

nshipste给的事例在load里加了dispatch_once,但我认为没有啥必要,load是只会运行一次的

对于Method的结构:

struct objc_method {     SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;     char * _Nullable method_types                            OBJC2_UNAVAILABLE;     IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE; } typedef struct objc_method *Method;

可以看到objc_method结构体就定义了一个完整的方法实现:

  1. method_name:方法名
  2. method_types:方法的参数和返回值类型
  3. method_imp:方法的具体实现指针

method_exchangeImplementations就是调换两个objc_methodmethod_imp

RSSwizzle

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » iOS HOOK 总结求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们