iOS App Hook 杂谈-绝口不再提Hook

  Hello大家好,上一篇我们聊到了《Android App Hook 杂谈》 里面介绍了我在工作中接触或者学习到的各种Hook的技术,按照国际惯例既然写了Android那我肯定不会抛弃iOS的小伙伴,那么我们今天就来看看iOS在开发中有哪些Hook可以去学习探索的呢,那么我会以我视角来带大家去看看这些常用的Hook技术。

  首先声明,本人并非是做底层架构出身,也并非是从事App安全相关的工作,之所以对于Hook有这么多的了解只不过是兴趣使然,再加上本人有扎实的计算机底层的基础,对于一些Hook技术可以去弄明白他的缘由而已,另外这篇文章也为了我也是为了我对于Hook这个主题做一个自我的总结,以后可能都不会多花时间去涉及这一块的内容了,好的让我们愉快的开始吧。

本着该文是杂谈属性的又一篇“杰作”,熟悉我博客的小伙伴就知道这一篇肯定也是轻松愉快的文章,代码量肯定不大,大家只需放松心态即可,那么大家知道iOS主要是基于OC、Swift语言的开发的,熟悉OC语言的小伙伴都知道,OC本身就是一门带动态特性的静态语言,所以我们单从iOS的应用层就有很多的Hook技术可以用来玩的,

  首先使用OC语言runtime的特性就很容易的写出一种简单的一般称作方法交换的Hook,如下:

#import "UIViewController+swizzling.h"
#import <objc/runtime.h>
@implementation UIViewController (swizzling)
 
+ (void)load {
    // 通过class_getInstanceMethod()函数从当前对象中的method list获取method结构体,如果是类方法就使用class_getClassMethod()函数获取。
    Method fromMethod = class_getInstanceMethod([self class], @selector(viewDidLoad));
    Method toMethod = class_getInstanceMethod([self class], @selector(swizzlingViewDidLoad));
    /**
     *  我们在这里使用class_addMethod()函数对Method Swizzling做了一层验证,如果self没有实现被交换的方法,会导致失败。
     *  而且self没有交换的方法实现,但是父类有这个方法,这样就会调用父类的方法,结果就不是我们想要的结果了。
     *  所以我们在这里通过class_addMethod()的验证,如果self实现了这个方法,class_addMethod()函数将会返回NO,我们就可以对其进行交换了。
     */
    if (!class_addMethod([self class], @selector(swizzlingViewDidLoad), method_getImplementation(toMethod), method_getTypeEncoding(toMethod))) {
        method_exchangeImplementations(fromMethod, toMethod);
    }
}
@end

使用的时候注意方法替换class_replaceMethod以及方法交换method_exchangeImplementations的区别即可

既然提到了runtime,那我就不得不提一下很早以前有一个大量使用了runtime特性去做热更新的一个框架那就是JSpatch。

  JSpatch用iOS内置的JavaSriptCore.framework作为JavaScript的执行引擎,但是他并没有直接使用JavaScript-OC的互相调用,而是通过OC Runtime从JavaScript传递调用的类名和函数名到OC,再使用NSInvocation反射去进行动态的调用OC的方法。

  这个在当年是一个很不错的热修复框架,但是好景不长最后被禁用了,但是这里顺便提一句很多人一知半解认为苹果公司禁用热更新所以禁用掉了了JSPatch,其实不然,苹果公司真正拒绝JSPatch的原因是JSPatch可以理解为所有的 Objective-C 的 API 进行了映射,允许开发者在 JS 端调用任意原生代码。这显然是极其危险的。假设这段代码是通过热更新技术下载执行的,如果在中间存在黑客,把这段代码动态替换掉,比如修改为获取用户通讯录并上传到黑客的服务器,就会造成重大的安全问题

  最主要的是JSPatch可以任意对于所有的 Objective-C 的 API 进行了映射,而React Native不能,这就是为什么React Native能够活下来的原因;

下一个要介绍的就是基于Got的hook,在iOS里面可以找到到一个成熟的框架去使用(这点比Android要好),那就是大名鼎鼎的fish Hook,那么他是怎么工作的呢

  首先我们要知道的是在C/C++语言里面模块间的数据访问和函数调用,都是用间接寻址,主模块将要访问动态库里的数据符号地址放在got(也称Non-Lazy Symbol Pointers)数据段,调用动态库的函数的地址放在la_symbol_ptr数据段。而数据段是可读写的,所以程序运行期间我们可以通过修改got(nl_symbol_ptr)和la_symbol_ptr数据段,来替换函数跟全局变量的地址。这个就是fishhook的原理。

说白了fishhook 的本质是遍历 image 中的非懒加载 nl_symbol_ptr和懒加载 la_symbol_ptr 数据段,将里面的函数地址替换成自定义的函数地址;

fish Hook涉及内容比较多,给大家推荐两篇文章 :

看完这两篇文章相信你对于fish Hook应该是可以掌握了

fish Hook在iOS中比Android要多一点点,但是他也并不是全能的,网络上很多的博客以及up主的视频都提到了主要他是用来Hook外部方法的,但是其实这种说法是不正确的,这里没有针对那些博主的以及up主,因为大家知道C/C++语言里面方法默认就是外部方法,难道都是可以被Got Hook的吗,显然是不可能的,熟悉fish Hook的都知道这种应该是在动态库里面Hook才会有效果的,所以应该是在动态库里面的强符号方法才可以被Hook,因为Got Hook这种方式本身就是只针对于动态库而言的。

  现在fish Hook已经很底层了,那还有没有更底层的Hook呢,还真有那就是称之为终极Hook的inline Hook,目前据了解支持inline Hook的框架有Cydia Substrate,Dobby这两个框架,老实讲这种Hook的作用范围非常广,不限于iOS底层,只要是C/C++语言相关的他都可以Hook,而且几乎没有限制条件,那么他是怎么Hook的呢,先来看一张图

image.png

  它属于是运行时指令替换,假设目标方法内有ins0, ins1, ins2三条指令,首先将起始指令(实际上是前2条指令)替换为等长的跳转指令jump_ins,jump_ins负责跳转到hook方法执行,而hook操作后,往往还需要保留调用原方法的能力以保证功能可用性,所以hook方法内还有一个跳转指令来调回原方法继续执行(jump ins1),调回前需要先补充执行目标方法已被替换的原始指令(图中ins0),保证原方法完整性。综上,inline hook需要完成的工作就是图中绿色的部分,即跳转指令的替换、补充执行原指令、跳回原方法继续执行这三步。

这个原理也是比较复杂,具体给大家分享一个链接 https://www.jianshu.com/p/2684e251124d

  好了已经介绍了很多种,下面再来给大家最后介绍一种Hook最为结束的开胃菜吧,那就是通过ptrace的Hook,这种方式比较少见一来是实现比较复杂,二来稳定性也不是最高的,而且需要root的权限去实现,所以用得很少,但是我们还是来看看他是怎么实现的吧

他的原理就是利用ptrace附加进程进行调试,利用ARM汇编底层修改替换寄存器来实现Hook,可以简单的分为以下步骤:

  • 1.先找到被注入进程的pid
  • 2.附加当前进程到被注入进程
  • 3.保存原寄存器的值
  • 4.找到需要Hook的系统调用函数
  • 5.修改目标进程寄存器
  • 6.执行目标函数调用
  • 7.恢复寄存器的值
  • 8.分离附加进程

原理也是比较复杂的,细节大家可以看看我这两篇博客:

已经讲得很到位了,绝对能帮助到大家了

  介绍得差不多了,这篇博客也是把我这几年接触到的Hook基本上都写出来了,因为这些对于我来说在工作中都不是直接主要的技能,所以以后可能都不会再去写关于Hook的内容了,这个也是为什么副标题叫“绝口不再提”的原因,一开始是凭着兴趣入门摸索,一腔热血,没有任何人指导也坚持到了现在,今天也算是为了自己这么多年的做的总结吧

  好了对于iOS的Hook我们就介绍到这里了,上面的这些Hook技术都是我在工作中积累的内容了,如果能帮助到也是喜欢Hook技术的你的话那么我很是欣慰了,如果你还喜欢的话请帮忙点赞加关注,你的一键三连是我持续写作的动力。

image.png

  今天是2023年的第二天了,送给大家一张萌兔的照片,祝大家2023兔年心想事成,天天开心,今天也是我家小的生日,不多说了,我要去给她过生日了,2023年大家后会有期😁···

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容