博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IOS中如何Hook消息
阅读量:4110 次
发布时间:2019-05-25

本文共 2795 字,大约阅读时间需要 9 分钟。

我们都知道在windows下可以通过API轻松的hook很多消息,IOS里面貌似还没有现成的API(可能是我还没发现吧),前段时间碰巧看到Objective-C运行时的一些东西,于是心想着是不是可以尝试一下实现hook的功能。

  为什么要hook消息呢,因为有些时候我们可能无法直接去继承一个类,却又想先截获某些消息做一些处理,然后再接着进行正常的处理流程。今天使用运行时的一些API实现了基本的hook功能。

  下面先直接上源码:

1 // 2 //  TestHookObject.m 3 //  TestHookMessage 4 // 5 //  Created by mapleCao on 13-2-28. 6 //  Copyright (c) 2013年 mapleCao. All rights reserved. 7 // 8  9 #import "TestHookObject.h"10 #import 
11 #import
12 13 @implementation TestHookObject14 15 // this method will just excute once16 + (void)initialize17 {18 // 获取到UIWindow中sendEvent对应的method19 Method sendEvent = class_getInstanceMethod([UIWindow class], @selector(sendEvent:));20 Method sendEventMySelf = class_getInstanceMethod([self class], @selector(sendEventHooked:));21 22 // 将目标函数的原实现绑定到sendEventOriginalImplemention方法上23 IMP sendEventImp = method_getImplementation(sendEvent);24 class_addMethod([UIWindow class], @selector(sendEventOriginal:), sendEventImp, method_getTypeEncoding(sendEvent));25 26 // 然后用我们自己的函数的实现,替换目标函数对应的实现27 IMP sendEventMySelfImp = method_getImplementation(sendEventMySelf);28 class_replaceMethod([UIWindow class], @selector(sendEvent:), sendEventMySelfImp, method_getTypeEncoding(sendEvent));29 }30 31 /*32 * 截获到window的sendEvent33 * 我们可以先处理完以后,再继续调用正常处理流程34 */35 - (void)sendEventHooked:(UIEvent *)event36 {37 // do something what ever you want38 NSLog(@"haha, this is my self sendEventMethod!!!!!!!");39 40 // invoke original implemention41 [self performSelector:@selector(sendEventOriginal:) withObject:event];42 }43 44 @end

  下面我们来逐行分析一下上面的代码:

  首先我们来看19行,这一行主要目的是获取到UIWindow原生的sendEvent的Method(一个结构体,用来对方法进行描述),接着第20行是获取到我们自己定义的类中的sendEvent的Method(这两个方法的签名必须一样,否则运行时报错)。第23行我们通过UIWindow原生的sendEvent的Method获取到对应的IMP(一个函数指针),第24行使用运行时API Class_addMethod给UIWindow类添加了一个叫sendEventOriginal的方法,该方法使用UIWindow原生的sendEvent的实现,并且有着相同的方法签名(必须相同,否则运行时报错)。27行是获取我们自定义类中的sendEventMySelf的IMP,28行是关键的一行,这一行的主要目的是为UIWindow原生的sendEvent指定一个新的实现,我们看到我们将该实现指定到了我们自己定义的sendEventMySelf上。到了这儿我们就完成了偷梁换柱,大功告成。

  执行上面这些行以后,我们就成功的将UIWindow的sendEvent重定向到了我们自己的写的sendEventMySelf的实现,然后将其原本的实现重定向到了我们给它新添加的方法sendEventOriginal中。而sendEventMySelf中,我们首先可以对这个消息进行我们想要的处理,然后再通过41行调用sendEventOriginal方法转到正常的执行流程。

  这块儿你可能有个困惑 “我们自定义类中明明是没有sendEventOriginal方法的啊?” 

  为什么执行起来不报错,而且还会正常执行?因为sendEventMySelf是UIWindow的sendEvent重定向过来的,所以在运行时该方法中的self代表的就是UIWindow的实例,而不再是TestHookObject的实例了。加上sendEventOriginal是我们通过运行时添加到UIWindow的实例方法,所以可以正常调用。当然如果直接通过下面这种方式调用也是可以的,只不过编译器会提示警告(编译器没那么智能),因此我们采用了performSelector的调用方式。

[self sendEventOriginal:event];

  以上就是Hook的实现,使用时我们只需要让TestHookObject类执行一次初始话操作就可以了,执行完以后。UIWindow的sendEvent消息就会会hook到我们的sendEventMySelf中了。

  下面是调用代码:

 

Install Hook

 

  代码中我们还专门添加了一个button来验证,hook完以后消息是否正常传递。经验证消息流转完全正常。

转载地址:http://ujosi.baihongyu.com/

你可能感兴趣的文章
MFC实现五子棋游戏
查看>>
WPF实现蜘蛛纸牌游戏
查看>>
单例模式
查看>>
工厂方法模式
查看>>
模板方法模式
查看>>
数据结构之队列、栈
查看>>
数据结构之树
查看>>
数据结构之二叉树
查看>>
二叉树非递归遍历算法思悟
查看>>
红黑树算法思悟
查看>>
从山寨Spring中学习Spring IOC原理-自动装配注解
查看>>
实例区别BeanFactory和FactoryBean
查看>>
Spring后置处理器BeanPostProcessor的应用
查看>>
Spring框架的ImportSelector到底可以干嘛
查看>>
Mysql中下划线问题
查看>>
微信小程序中使用npm过程中提示:npm WARN saveError ENOENT: no such file or directory
查看>>
Xcode 11 报错,提示libstdc++.6 缺失,解决方案
查看>>
idea的安装以及简单使用
查看>>
Windows mysql 安装
查看>>
python循环语句与C语言的区别
查看>>