iOS逆向安防从入门到秃头--MachO中的符号

1,771 阅读4分钟

小谷秃头合集

  • 小谷最近生病了几天,借此机会也研究了下符号~

  • 今天来小叙一下符号。(这个东西大家应该都不会陌生~)

1. 符号的定义

1.1. 什么是符号

  • 小谷说下自己的理解吧~

    • 其实符号的概念比较广,我们开发中,编写的函数、变量等等都可以成为符号
  • 这个时候不得不提一下符号表

    • 我们通过烂苹果(MachOView)可以知道:MachO中有个总表·Symbol Table·(符号表),符号都被保存在这里.

    • 还有个他的子集,叫·Indirect Symbol Table·(间接符号表),保存的是间接符号(我们通常使用的NSLog就属于间接符号,有时候我们也称他为外部符号).

    • 还有String table ,保存的是符号的名称.

1.png

这几张表的联系,我一会会说~

2. 符号绑定

说到绑定,不得不提一嘴dyld

2.1. dyld的加载流程(应用程序的启动~)

不知道大家有没有看过dyld的加载流程(我直接就阐述下吧。兄弟们有时间可以去看看,验证下

  • 首先, dyld(dynamic linker,动态链接器)最开始的地方,_dyld_start

  • 然后通过 dyldbootstrap::start进入dyldmain函数

  • 主要流程开始了~

  1. 配置所需环境、重定向dyld(由于应用程序运行时都在内存中(磁盘中的镜像(所以我们通常都会说image)),由于苹果的安全协议,出现了一个ASLR,所以需要重定向
  1. 加载共享缓存(这个其实不用多说了。我们用到了系统的库,有可能之前已经加载过了~)
  1. 实例化主程序(之前会判断是dyld或者dyld3.都是一样的。dyld3是苹果为了提高效率新增的,采用的是回调函数模式(通常也成为闭包模式))
  1. 加载动态库(之前一篇博客,动态库的注入,大家也已经了解了,其实首先加载的是注入的动态库。)
  1. 链接主程序,绑定符号(这个是很关键的~,这个操作的主要是非懒加载中的符号,一会说到的,dyld_stub_binder就是这一步操作绑定的,在load方法之前)
  1. 然后就是初始化方法:initializeMainExecutable(剩下的就是调用,链接objc_init之类的了,然后调用load,然后c++,然后main了,这就不多说了~)
  • 本来想给大家展示代码的,感觉其实不重要,这流程就够用了~

2.2. 符号绑定

    1. 我们用NSLog举例吧(直接写代码)
    // 我们都知道NSLog是外部符号,在间接符号表里面~
    
    NSLog(@" 第一次调用外部符号~ ");
    
    NSLog(@" 第二次调用外部符号~ ");
    1. 我直接画了个简易的流程图(要是一步步写,文章就太长了,图片解决一切~)

2.png

由于dyld_stub_binder是在很早之前就加载好了(上面提到的~).外部符号的绑定看来是通过dyld_stub_binder,下次再调用时候就不需要在次绑定了

    1. 我们从MachOView中观察到:在绑定之前NSLog中已经有值了,这个称为NSLog的桩

3.png

3. 通过字符串查找符号

兄弟们应该都用过fishhook技术

4.png

fishhook有一句:log.name = "NSLog";

  • 那么通过字符串,如何找到的这个函数呢?

  • 我们先看看fishhook的官方解释

5.png

是不是有点小懵逼。小谷陪兄弟们看一下~

  • 我通过MachOView。以NSLog举例~(他用的close,其实流程差不多~)

6.png

这样是不是清楚很多了~

4. 脱符号

关于脱符号和恢复符号,我就简单说一下。

7.png

5. 恢复符号

恢复符号的原理主要是通过OC方法的动态性

  • 虽然符号去掉了,但是保存在methodlist里面的方法,用到都会存在的(如果没有就么有办法调用了~)

8.png

有个工具叫做,restore-symbol就是通过方法名和类名称,然后生成符号表插入到MachO的。

6. 总结

    1. 其实做逆向安防的话,大多数都是用的工具-比较方便,但是我感觉还是要稍微懂一点原理比较好点~
    1. 这篇博客可能不是特别的细,就当给兄弟们开个口子。
    1. 最后希望和兄弟们共同进步~😆