Mach-o文件格式

Mach-O简介:

Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式.常见的Mach-O文件比如iOS开发好的代码打包好后就是Mach-O格式的文件.

Apple中定义的Mach-O文件包含图一中几种:

1

常见的几种Mach-O文件:

a、目标文件(.o)

b、静态库文件(.a),静态库其实就是N个.o合并在一起

MH_EXECUTE:可执行文件

a、.app/xx

MH_DYLIB:动态库文件

a、.dylib

b、.framework/xx

MH_DYLINKER:动态链接编辑器

a、/usr/lib/dyld

MH_DSYM:存储着二进制文件符号信息的文件

a、.dSYM/Contents/Resources/DWARF/xx(常用于分析APP的崩溃信息)

Mach-O的基本结构:

主要包含三个部分:

Header部分:保存了该文件的一些基本信息,如平台,文件类型,加载命令的个数等

loadCommends部分:根据这里的数据来确定内存的分布

Data部分:存放具体的代码和数据,data部分是以段来划分的,loadCommends部分的Segment command对应Data中的Segment

segment

Header:

1


2

Header的第一行的file offset为0,Data为4个字节(2个16进制代表一个字节),第二行file offset为4,Data为4个字节

Load Commands:

loadCommand是用于加载指令的,它的大小和数目在header中已经被提供,在Mach.h下以loadCommand结构体展示


1

load_commands紧跟mach_header

2

VM Address:虚拟内存的地址

VM Size:虚拟内存的size,这里转为16进制为100000000

File Offset:相对于mach-o文件Data数据的偏移量

File Size:就是数据大小,就__PAGEZERO有些特殊,File Size为0代表实际占用mach-o为0,但是它描述了占用虚拟内存的大小,就是上面的4294967296


3

VM Address:虚拟内存的地址

VM Size:虚拟内存的size

File Offset:相对于mach-o文件Data数据的偏移量

File Size:File Size代表实际占用mach-o的大小


4

Address:该段在文件中的实际地址+adsr

Size:段大小

Offset:该段在文件中的实际地址

segment段类型如下:

1:__PAGEZERO段: 空指针陷阱段,映射到虚拟内存空间的第一页,用于捕捉对NULL指针的引用;

2: __TEXT 段: 包含了执行代码以及其他只读数据。 为了让内核将它 直接从可执行文件映射到共享内存, 静态连接器设置该段的虚拟内存权限为不允许写。当这个段被映射到内存后,可以被所有进程共享。(这主要用在frameworks, bundles和共享库等程序中,也可以为同一个可执行文件的多个进程拷贝使用)

3: __DATA段: 包含了程序数据,该段可写;

4: __OBJC段: Objective-C运行时支持库;

5: __LINKEDIT段: 含有为动态链接库使用的原始数据,比如符号,字符串,重定位表条目等等。

每种类型的段又会按不同的功能划分为几个区(section, 名称小写,加两个下横线作为前缀)如下:

TEXT 段中的section具体类型和作用:

_text:只有可执行机器码(主程序代码)

_cstring: 去重后的c字符串

_const: 初始化的常量

_stubs: 符号桩,本质上就是一小段会直接跳入到lazybinding的表的对应项指针指向的地址的代码(???)

_stubs_helper: 辅助函数,上述lazybinding表中没有找到符号地址都指向这

_unwind_info:用于存储异常请况信息>

_eh_frame 调试辅助信息

DATA 段中section的具体类型和作用

_data :初始化过得可变的数据,即全局变量和静态变量的存储是放在一块的,都放在全局区(静态区),初始化的全局变量和静态变量在一块区域

_const: 没有初始化过得常量

_bss: 没有初始化的静态变量

_common: 没有初始化过的符号声明

_mod_init_func : 初始化函数:在main之前调用

_mod_term_func: 终止函数,在main返回之后调用

_nl_symbol_ptr:  在非lazy-binding的指针表中 的每个表项中的指针都指向一个在装载过程中,被动态链机器搜索完成的符号(符号的指针)

__la_symbol_ptr:lazy-binding的指针表,每个表项中的指针一开始指向stub_helper(没有找到的符号指针)

注意: 虽然段类型是不一样的,但是加载都是使用LC_SEGMENT_64 这个命令, 只是其中加载的段的信息不同

1

__text: 主程序代码

__stubs, __stub_helper: 用于动态链接的桩

__cstring: 程序中c语言字符串

__const: 常量

__TEXT,__objc_methname:OC方法名称

__TEXT__objc_methtype:OC方法类型

__TEXT__objc_classname:OC类名

__DATA,__objc_classlist:OC类列表

__DATA,__objc_protollist:OC原型列表

__DATA,__objc_imageinfo:OC镜像信息

__DATA,__objc_const:OC常量

__DATA,__objc_selfrefs:OC类自引用(self)

__DATA,__objc_superrefs:OC类超类引用(super)

__DATA,__objc_protolrefs:OC原型引用

__DATA, __bss: 没有初始化和初始化为0 的全局变量

Dynamic Loader Info:动态链接器所需要使用的信息(重定向,符号绑定,懒加载绑定等..)

后续的信息就是函数起始位置,符号表,字符表,代码签名等.



查看Mach-O信息:

1.查看Mach-O的文件类型

$ file Mach-O文件路径

例如查看APP支持的架构(arm64或者32)如图


1

2.查看Mach-O的特定部分如图四(头信息或者段信息)

$ otool -h Mach-O文件路径//查看头信息

$ otool -l Mach-O文件路径 | grep cryptid//查看Mach-O文件路径文件是否加密


1

3.多架构Mach-O文件的处理,可以将arm64和32分开,合并

$ lipo -info 文件路径//看架构信息

$ lipo 文件路径 -thin 架构类型 -output 输出文件路径//导出某种特定架构

$ lipo 文件路径1文件路径2-output 输出文件路径//合并多种架构

Mach-o文件详解:

ASLR:

地址空间布局随机化,是一种避免app被攻击的有效保护;进程每次启动时,地址空间都会被简单地随机化——只是偏移,不是搅乱。实现方式是通过内核将Mach-O的段“平移”某个随机数;

真正的内存地址则是vmaddr + ALSR

https://www.jianshu.com/p/37f10bb70c50

https://www.exchen.net/mach-o-文件格式解析.html

相关工具:

Mach-OGUI查看工具Mach-OView

MachOView下载编译即可.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容