天天看点

iOS小技能:对symbol的理解

前言

  1. 对symbol table 的symbol的理解(public symbol 、private symbol 、stripped symbol)
  2. Mach-O 初识
  3. hook方式汇总

I 对symbol的理解

1.1 什么是symbol?

计算机中,一个函数的指令被存放在一段内存中,当进程需要执行这个函数的时候,它必须知道要去内存的哪个地方找到这个函数,然后执行它的指令。

也就是说,进程要根据这个函数的名称,找到它在内存中的地址,而这个名称与地址的映射关系,是存储在 “symbol table”中。

“symbol table”中的 ​

​symbol ​

​​ 就是这个函数的名称,

进程会根据这个 ​​

​ symbol ​

​ 找到它在内存中的地址,然后跳转过去执行。

symbol 跟函数名不同。

1.2 symbol的分类

为了避免其他app利用symbol,执行其他app库的函数symbol 被分为2类

public symbol 和private symbol

第三类 stripped symbol

symbol的来源: symbol通常由 IDA 对二进制文件的分析结果中提取。

II MSHookFunction 和 MSFindSymbol

2.1 MSHookFunction

MSHookFunction 作用于C 和C++函数通过编写汇编指令,在进行执行到 function 时 转而执行 replacement,同时保存在 function 的指令及其返回地址,使得用户可以选择性的执行 function ,并保证进程能够在执行完 replacement 后继续正常运行。

CydiaSubstrate(由MobileHooker、 MobileLoader 、Safe mode组成) 是对MSHookMessageEx进行封装。

iOS 的底层是用 C C++ 实现的,编译之后生成的大都是 subroutine, class-dump 拿它没办法,只能使用IDA 工具。——-​

​ 因此在OC 开发中使用C 语言实现算法相关的功能,代码更具安全性。​

2.2 MSFindSymbol

​​MSHookFunction 直接作用private symbol是无效的,因此saurik 提供 MSFindSymbol 的 API 来访问private symbol。​​

void *MSFindSymbol(MSImageRef image, const char      
MSImageRef image;
image = MSGetImageByName("/usr/lib/libSystem.B.dylib");

void *(*palloc)(size_t);
palloc = (void *(*)(size_t)) MSFindSymbol(image, "_malloc");

void *data = (*palloc)(1024);
free(data);      

III Mach-O

iOS小技能:对symbol的理解

​​Mach-O 是针对不同运行时可执行文件的文件类型。​​

3.1 文件类型:

  • Executable: 应用的主要二进制
  • Dylib: 动态链接库(又称 DSO 或 DLL)
  • Bundle: 不能被链接的 Dylib,只能在运行时使用 dlopen() 加载,可当做 macOS 的插件。
  • Image: executable,dylib 或 bundle
  • Framework: 包含 Dylib 以及资源文件和头文件的文件夹

3.2 Mach-O 镜像文件

iOS 可执行文件是 Mach-O 格式,主要由 Header、Load Commands、Data 三部分

​Header 头部​

​​,包含可以执行的CPU架构,比如x86,arm64

​​

​Load commands 加载命令​

​​,包含文件的组织架构和在虚拟内存中的布局方式

​​

​Data数据​

​,存储了实际的内容,主要是程序的指令和数据,它们的排布完全依照 Load Commands 的描述.

包含load commands中需要的各个段(segment)的数据

Mach-O 文件中的 Data 部分主要是以 Segment(段)和 Section (节)的方式来组织内容的, 被划分成一些 segement,每个 segement 又被划分成一些 section。

  • segment 的名字都是大写的,​

    ​且空间大小为页的整数​

    ​。页的大小跟硬件有关,在 arm64 架构一页是 16KB,其余为 4KB。
  • section 虽然没有整数倍页大小的限制,但是 section 之间不会有重叠。

3.3 几乎所有 Mach-O 都包含这三个segment(支持用户自定义Segment)

​__TEXT,__DATA 和 __LINKEDIT​

  • __TEXT 代码段,只读可执行(r-x)
被执行的代码包括函数,和只读的字符串,类似__TEXT,__text的都是代码段 、包含 Mach header
  • __DATA 数据段,包括可读写的全局变量、静态变量

类似中的__DATA,__data都是数据段

可读写(rw-)

  • __LINKEDIT :包含启动 App 需要的信息【方法和变量的​

    ​元数据(位置,偏移量)​

    ​】(比如函数的名称、bind & rebase地址)以及代码签名、符号表等信息。
只读(r–)

3.4 ASLR地址空间布局随机化

  • Address Space Layout Randomization

    地址空间布局随机化,镜像会在随机的地址上加载。这其实是一二十年前的旧技术了。

3.5 代码签名

可能我们认为 Xcode 会把整个文件都做加密 hash 并用做数字签名。

其实为了在运行时验证 Mach-O 文件的签名,并不是每次重复读入整个文件,而是把每页内容都生成一个单独的加密散列值,并存储在 __LINKEDIT 中。这使得文件每页的内容都能及时被校验确并保不被篡改。

IV hook 的方式