Mach-o文件格式

Mach-O簡介:

Mach-O是Mach object的縮寫,是Mac\iOS上用于存儲程序、庫的標準格式.常見的Mach-O文件比如iOS開發(fā)好的代碼打包好后就是Mach-O格式的文件.

Apple中定義的Mach-O文件包含圖一中幾種:

1

常見的幾種Mach-O文件:

a、目標文件(.o)

b、靜態(tài)庫文件(.a),靜態(tài)庫其實就是N個.o合并在一起

MH_EXECUTE:可執(zhí)行文件

a、.app/xx

MH_DYLIB:動態(tài)庫文件

a、.dylib

b、.framework/xx

MH_DYLINKER:動態(tài)鏈接編輯器

a、/usr/lib/dyld

MH_DSYM:存儲著二進制文件符號信息的文件

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

Mach-O的基本結構:

主要包含三個部分:

Header部分:保存了該文件的一些基本信息,如平臺,文件類型,加載命令的個數(shù)等

loadCommends部分:根據這里的數(shù)據來確定內存的分布

Data部分:存放具體的代碼和數(shù)據,data部分是以段來劃分的,loadCommends部分的Segment command對應Data中的Segment

segment

Header:

1


2

Header的第一行的file offset為0,Data為4個字節(jié)(2個16進制代表一個字節(jié)),第二行file offset為4,Data為4個字節(jié)

Load Commands:

loadCommand是用于加載指令的,它的大小和數(shù)目在header中已經被提供,在Mach.h下以loadCommand結構體展示


1

load_commands緊跟mach_header

2

VM Address:虛擬內存的地址

VM Size:虛擬內存的size,這里轉為16進制為100000000

File Offset:相對于mach-o文件Data數(shù)據的偏移量

File Size:就是數(shù)據大小,就__PAGEZERO有些特殊,F(xiàn)ile Size為0代表實際占用mach-o為0,但是它描述了占用虛擬內存的大小,就是上面的4294967296


3

VM Address:虛擬內存的地址

VM Size:虛擬內存的size

File Offset:相對于mach-o文件Data數(shù)據的偏移量

File Size:File Size代表實際占用mach-o的大小


4

Address:該段在文件中的實際地址+adsr

Size:段大小

Offset:該段在文件中的實際地址

segment段類型如下:

1:__PAGEZERO段: 空指針陷阱段,映射到虛擬內存空間的第一頁,用于捕捉對NULL指針的引用;

2: __TEXT 段: 包含了執(zhí)行代碼以及其他只讀數(shù)據。 為了讓內核將它 直接從可執(zhí)行文件映射到共享內存, 靜態(tài)連接器設置該段的虛擬內存權限為不允許寫。當這個段被映射到內存后,可以被所有進程共享。(這主要用在frameworks, bundles和共享庫等程序中,也可以為同一個可執(zhí)行文件的多個進程拷貝使用)

3: __DATA段: 包含了程序數(shù)據,該段可寫;

4: __OBJC段: Objective-C運行時支持庫;

5: __LINKEDIT段: 含有為動態(tài)鏈接庫使用的原始數(shù)據,比如符號,字符串,重定位表條目等等。

每種類型的段又會按不同的功能劃分為幾個區(qū)(section, 名稱小寫,加兩個下橫線作為前綴)如下:

TEXT 段中的section具體類型和作用:

_text:只有可執(zhí)行機器碼(主程序代碼)

_cstring: 去重后的c字符串

_const: 初始化的常量

_stubs: 符號樁,本質上就是一小段會直接跳入到lazybinding的表的對應項指針指向的地址的代碼(???)

_stubs_helper: 輔助函數(shù),上述lazybinding表中沒有找到符號地址都指向這

_unwind_info:用于存儲異常請況信息>

_eh_frame 調試輔助信息

DATA 段中section的具體類型和作用

_data :初始化過得可變的數(shù)據,即全局變量和靜態(tài)變量的存儲是放在一塊的,都放在全局區(qū)(靜態(tài)區(qū)),初始化的全局變量和靜態(tài)變量在一塊區(qū)域

_const: 沒有初始化過得常量

_bss: 沒有初始化的靜態(tài)變量

_common: 沒有初始化過的符號聲明

_mod_init_func : 初始化函數(shù):在main之前調用

_mod_term_func: 終止函數(shù),在main返回之后調用

_nl_symbol_ptr:? 在非lazy-binding的指針表中 的每個表項中的指針都指向一個在裝載過程中,被動態(tài)鏈機器搜索完成的符號(符號的指針)

__la_symbol_ptr:lazy-binding的指針表,每個表項中的指針一開始指向stub_helper(沒有找到的符號指針)

注意: 雖然段類型是不一樣的,但是加載都是使用LC_SEGMENT_64 這個命令, 只是其中加載的段的信息不同

1

__text: 主程序代碼

__stubs, __stub_helper: 用于動態(tài)鏈接的樁

__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:動態(tài)鏈接器所需要使用的信息(重定向,符號綁定,懶加載綁定等..)

后續(xù)的信息就是函數(shù)起始位置,符號表,字符表,代碼簽名等.



查看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被攻擊的有效保護;進程每次啟動時,地址空間都會被簡單地隨機化——只是偏移,不是攪亂。實現(xiàn)方式是通過內核將Mach-O的段“平移”某個隨機數(shù);

真正的內存地址則是vmaddr?+?ALSR。

http://www.itdecent.cn/p/37f10bb70c50

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

相關工具:

Mach-OGUI查看工具Mach-OView

MachOView下載編譯即可.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容