IOS中如何Hook消息

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

IOS中如何Hook消息

  

  年过完了,该收心了,该开始学习了。

  我们都知道在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 <objc/objc.h>
11 #import <objc/runtime.h>
12 
13 @implementation TestHookObject
14 
15 // this method will just excute once
16 + (void)initialize
17 {
18     // 获取到UIWindow中sendEvent对应的method
19     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的sendEvent
33  * 我们可以先处理完以后,再继续调用正常处理流程
34  */
35 - (void)sendEventHooked:(UIEvent *)event
36 {
37     // do something what ever you want
38     NSLog(@"haha, this is my self sendEventMethod!!!!!!!");
39     
40     // invoke original implemention
41     [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
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[TestHookViewController alloc] initWithNibName:@"TestHookViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    
    
    //hook UIWindow‘s SendEvent method
    TestHookObject *hookSendEvent = [[TestHookObject alloc] init];
    [hookSendEvent release];
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    btn.center = CGPointMake(160, 240);
    btn.backgroundColor = [UIColor redColor];
    [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventAllEvents];
    [self.window addSubview:btn];
    [btn release];
    
    return YES;
}

 

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

  2013年写的第一篇博客,希望大家能喜欢!!!

 

注:欢迎转载,转载请注明出处!

 

参考资料:Objective-C运行时源代码

     Objective-C Runtime Reference

一片-枫叶

2013年2月28日

  

 

 


部门招人: 高级iOS、Android、前端开发,有意私聊,博主请你喝️
如果觉得本文帮到了你,记得点赞哦,当然也可以请博主喝一杯豆浆
o_IMG_2722.PNG o_qq.PNG
微信二维码 QQ二维码
目录
相关文章
|
iOS开发
iOS开发-聊天气泡的绘制和聊天消息列表
iOS开发-聊天气泡的绘制和聊天消息列表
169 0
iOS开发-聊天气泡的绘制和聊天消息列表
|
存储 缓存 开发者
iOS-底层原理 14:消息流程分析之 动态方法决议 & 消息转发
iOS-底层原理 14:消息流程分析之 动态方法决议 & 消息转发
272 0
iOS-底层原理 14:消息流程分析之 动态方法决议 & 消息转发
|
缓存 算法 C++
iOS-底层原理 13:消息流程分析之慢速查找
iOS-底层原理 13:消息流程分析之慢速查找
120 0
iOS-底层原理 13:消息流程分析之慢速查找
|
存储 缓存 自然语言处理
iOS-底层原理 12:消息流程分析之快速查找
iOS-底层原理 12:消息流程分析之快速查找
77 0
iOS-底层原理 12:消息流程分析之快速查找
|
搜索推荐 iOS开发
iOS小技能:消息推送扩展的使用
iOS小技能:消息推送扩展的使用
471 0
iOS小技能:消息推送扩展的使用
|
PHP 数据安全/隐私保护 iOS开发
分分钟搞定IOS远程消息推送(二)
分分钟搞定IOS远程消息推送
334 0
分分钟搞定IOS远程消息推送(二)
|
存储 Android开发 数据安全/隐私保护
分分钟搞定IOS远程消息推送(一)
分分钟搞定IOS远程消息推送
191 0
分分钟搞定IOS远程消息推送(一)
|
Android开发 数据安全/隐私保护 iOS开发
APNS IOS 消息推送
一.Apns简介: Apns是苹果推送通知服务。 二.原理: APNs会对用户进行物理连接认证,和设备令牌认证(简言之就是苹果的服务器检查设备里的证书以确定其为苹果设备);然后,将服务器的信息接收并且保存在APNs当中,APNs从其中注册的列表中查找该IOS设备(设备可以为iPhone、iPad、iPod Touch,版本是iOS3.
1650 0
|
iOS开发
APNS IOS 消息推送处理失效的Token
在开发苹果推送服务时候,要合理的控制ios设备的Token,而这个Token是由苹果服务器Apns产生的,就是每次app问Apns要Token,由苹果服务器产生的Token会记录到Apns里面,我们需要根据该Token进行制定设备的消息推送,所有Token需要我们自己去记录和管理,每个设备对应唯一的Token,而app的用户登录会有自己约束的别名,与该tokne进行关系绑定,这样按该别名进行推送,就可以找到对应的Token,进而推送到该iso设备上,对应失效的Token我们需要访问苹果的feedbackServer,拿取失效的Token,然后把本地记录的失效token进行移除。
1957 0