-
小谷最近生病了几天,借此机会也研究了下符号~
-
今天来小叙一下符号。(这个东西大家应该都不会陌生~)
1. 符号的定义
1.1. 什么是符号
-
小谷说下自己的理解吧~
- 其实
符号的概念比较广,我们开发中,编写的函数、变量等等都可以成为符号。
- 其实
-
这个时候不得不提一下
符号表-
我们通过
烂苹果(MachOView)可以知道:MachO中有个总表·Symbol Table·(符号表),符号都被保存在这里. -
还有个他的子集,叫
·Indirect Symbol Table·(间接符号表),保存的是间接符号(我们通常使用的NSLog就属于间接符号,有时候我们也称他为外部符号). -
还有
String table,保存的是符号的名称.
-
这几张表的联系,我一会会说~
2. 符号绑定
说到绑定,不得不提一嘴
dyld
2.1. dyld的加载流程(应用程序的启动~)
不知道大家有没有看过
dyld的加载流程(我直接就阐述下吧。兄弟们有时间可以去看看,验证下)
-
首先,
dyld(dynamic linker,动态链接器)最开始的地方,_dyld_start -
然后通过
dyldbootstrap::start进入dyld的main函数 -
主要流程开始了~
配置所需环境、重定向dyld(由于应用程序运行时都在内存中(磁盘中的镜像(所以我们通常都会说image)),由于苹果的安全协议,出现了一个ASLR,所以需要重定向)
加载共享缓存(这个其实不用多说了。我们用到了系统的库,有可能之前已经加载过了~)
实例化主程序(之前会判断是dyld或者dyld3.都是一样的。dyld3是苹果为了提高效率新增的,采用的是回调函数模式(通常也成为闭包模式))
加载动态库(之前一篇博客,动态库的注入,大家也已经了解了,其实首先加载的是注入的动态库。)
链接主程序,绑定符号(这个是很关键的~,这个操作的主要是非懒加载中的符号,一会说到的,dyld_stub_binder就是这一步操作绑定的,在load方法之前)
然后就是初始化方法:initializeMainExecutable(剩下的就是调用,链接objc_init之类的了,然后调用load,然后c++,然后main了,这就不多说了~)
- 本来想给大家展示代码的,感觉其实不重要,这流程就够用了~
2.2. 符号绑定
-
- 我们用
NSLog举例吧(直接写代码)
- 我们用
// 我们都知道NSLog是外部符号,在间接符号表里面~
NSLog(@" 第一次调用外部符号~ ");
NSLog(@" 第二次调用外部符号~ ");
-
- 我直接画了个简易的流程图(要是一步步写,文章就太长了,图片解决一切~)
由于
dyld_stub_binder是在很早之前就加载好了(上面提到的~).外部符号的绑定看来是通过dyld_stub_binder,下次再调用时候就不需要在次绑定了
-
- 我们从
MachOView中观察到:在绑定之前NSLog中已经有值了,这个称为NSLog的桩
- 我们从
3. 通过字符串查找符号
兄弟们应该都用过
fishhook技术
fishhook有一句:log.name = "NSLog";
-
那么通过字符串,如何找到的这个函数呢?
-
我们先看看
fishhook的官方解释
是不是有点小懵逼。小谷陪兄弟们看一下~
- 我通过
MachOView。以NSLog举例~(他用的close,其实流程差不多~)
这样是不是清楚很多了~
4. 脱符号
关于
脱符号和恢复符号,我就简单说一下。
5. 恢复符号
恢复符号的原理主要是通过OC方法的动态性。
- 虽然
符号去掉了,但是保存在methodlist里面的方法,用到类都会存在的(如果没有就么有办法调用了~)
有个工具叫做,
restore-symbol就是通过方法名和类名称,然后生成符号表插入到MachO的。
6. 总结
-
- 其实做
逆向安防的话,大多数都是用的工具-比较方便,但是我感觉还是要稍微懂一点原理比较好点~
- 其实做
-
- 这篇博客可能不是特别的细,就当给兄弟们开个口子。
-
- 最后希望和兄弟们共同进步~😆