36

iOS逆向 MachO文件

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI0MTcwNDcyMw%3D%3D&%3Bmid=2247484316&%3Bidx=1&%3Bsn=715004f28ec4b8361366ffb81bb6cb44
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者: 我是好宝宝

链接:

https://juejin.im/post/5df47aebe51d4558483d9717

一、MachO初探

1.定义

MachO 其实是 Mach Object 文件格式的缩写,是mac以及iOS上可执行文件的格式,类似于Windows上的PE格式(Portable Executable)、Linux上的elf格式(Executable and Linking Format)

它是一种用于可执行文件、目标代码、动态库的文件格式,作为.out格式的替代,MachO提供了更强的扩展性

2.常见的MachO文件

  • 目标文件.o

  • 库文件

    • .a

    • .dylib

    • .Framework

  • 可执行文件

  • dyld(动态链接器)

  • .dsym(符号表:Relese环境运行生成

3.查看文件类型

$ file xxx.xx


EJFbEnm.jpg!web

二、关于架构

1.架构表

其实iPhone不同的型号对应的架构是不一样的

QVviM37.png!web

2.生成多种架构

新建一个工程,真机运行,查看可执行文件仅仅是一个arm64架构的

将项目最低适配系统调为iOS9.0,真机运行 Relese环境

rYfAzuu.jpg!web

为什么要改为iOS9.0呢 ?是因为iPhone5c等armv7、armv7s架构不支持iOS11.0

为什么要Relese环境运行呢 ?因为Xcode默认Debug只生成单一架构

mU7Fby6.jpg!web

怎么生成所有架构 ?Xcode10中只包含了v7和64,需要在 Architectures 中添加

vAJjumv.jpg!web

aMNzYrQ.jpg!web

三、通用二进制文件

1.定义

通用二进制文件(Universal binary)也被叫做 胖二进制(Fat binary)

  • 苹果公司提出的一种程序代码,能同时适用多种架构的二进制文件

  • 同一个程序包中同时为多种架构提供最理想的性能

  • 因为需要储存多种代码,通用二进制应用程序通常比单一平台二进制的程序要大

  • 但是由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多

  • 而且由于执行中只调用一部分代码,运行起来也不需要额外的内存

2.拆分/合并架构

架构拆分

A3iAZ3b.jpg!web

合并架构

VryeauQ.jpg!web

通用二进制 大小为342kb,四个架构大小为80+80+80+81=321kb

What!为什么不是单纯的1+1=2?

因为不同架构之间代码部分是不共用的 (因为代码的二进制文件不同的组合在不同的 cpu 上可能会是不同的意义),而公共资源文件是公用的

利用上述方法可以给我们的app瘦身

结论:

胖二进制 拆分后再重组会得到原始 胖二进制

通用二进制 的大小可能大于子架构大小之和,也可能小于,也可能等于,取决于 公共资源文件 的多少

3.终端命令行

// 查看二进制文件

$ lipo -info xx

// 通用二进制文件

// 拆分二进制文件

lipo xxx -thin armv7 -output xxx

// 组合二进制文件

lipo -create x1 x2 x3 x4 -output xxx


四、MachO文件

1.整体结构

MachOView 打开会看到 通用二进制文件Fat Header四个可执行文件 组成

6ZZBvaf.jpg!web

可执行文件 是由 Header Load commands Data 组成

yUVfMjq.jpg!web

我们可以这么理解,把 通用二进制文件 看作四本翻译语言不同的书,每本书有 标题(header) 目录(load commands) 内容(data)

  • header:

  • load commands:

  • data:

另外我们也可以通过 otool 命令行查看MachO文件结构

$ otool -f universe


3M7ruua.jpg!web

2.header

header 包含了该二进制文件的字节顺序、架构类型、加载指令的数量等,使得可以快速确认一些信息,比如当前文件用于 32 位 还是 64 位 ,对应的处理器是什么、文件类型是什么

Xcode中 shift+command+O -> load.h ->如下信息

struct mach_header_64 {

uint32_t magic; /* 魔数,快速定位64位/32位 */

cpu_type_t cputype; /* cpu 类型 比如 ARM */

cpu_subtype_t cpusubtype; /* cpu 具体类型 比如arm64 , armv7 */

uint32_t filetype; /* 文件类型 例如可执行文件 .. */

uint32_t ncmds; /* load commands 加载命令条数 */

uint32_t sizeofcmds; /* load commands 加载命令大小*/

uint32_t flags; /* 标志位标识二进制文件支持的功能 , 主要是和系统加载、链接有关*/

uint32_t reserved; /* reserved , 保留字段 */

};


mach_header_64(64位)对比mach_header(32位)只多了一个保留字段

3.load commands

load commands 是一张包括区域的位置、符号表、动态符号表等内容的表。它详细保存着加载指令的内容,告诉链接器如何去加载这个 Mach-O 文件。通过查看内存地址我们发现,在内存中 load commands 是紧跟在 header 之后的

Y7juayr.jpg!web

4.data

data 是MachO文件中最大的部分,其中 _TEXT段_DATA段 能给到很多信息

load commandsdata 之间还留有不少空间,给我们留下了注入代码的冲破口

amamyaQ.jpg!web

_TEXT段

Mzyyi27.png!web

_DATA段

mInmEnz.png!web

五、dyld

dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统的一个重要组成部分,在系统内容做好程序准备工作之后,交由dyld负责余下的工作

系统库的方法由于是公用的,存放在共享缓存中,那么我们的MachO在调用系统方法时,dyld会将MachO里调用存放在共享缓存中的方法进行符号绑定。这个符号在 release环境 是会被自动去掉的,这也是我们经常使用收集 bug 工具时需要恢复符号表的原因

Fn6j6re.gif如果感觉这篇文章不错可以点击在看:point_down:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK