簡(jiǎn)介
Mach-O是iOS/OS可執(zhí)行文件。編譯成功后,找到app文件->顯示包內(nèi)容,即可找到可執(zhí)行文件。

常用指令
- 查看Mach-O格式
lipo -info <可執(zhí)行文件>

- 查看Mach-O架構(gòu)
lipo -info <可執(zhí)行文件>

- 查看Mach-O的Header
otool -h <可執(zhí)行文件>

otool -hv <可執(zhí)行文件>

- 查看Mach-O的Load Commands
otool -lv <可執(zhí)行文件>

Mach-O文件讀取工具M(jìn)achOView

Mach-O文件解析
- Mach64Header
magic(魔數(shù)):0xfeedface-32位、0xfeedfacf-64位、0xcafebabe-通用格式
(魔數(shù)的讀取:32位為小端讀取,低地址在低位,高地址在高位、64位為大端讀取,低地址在高位,高地址在低位)
cputype、cpusubtype:CPU的平臺(tái)與版本
armv7:cputype-12、cpusubtype-9
arm64:cputype-16777228、cupsubtype-0
filetype:可執(zhí)行文件(2)、庫(kù)文件、Core、內(nèi)核擴(kuò)展
OBJECT(目標(biāo)文件)-1、EXECUTE(可執(zhí)行文件)-2、DYLIB(動(dòng)態(tài)庫(kù))-6
ncmds、sizeofcmds:Load Commands的個(gè)數(shù)和長(zhǎng)度
flags:dyld加載時(shí)需要的標(biāo)志位,PIE表示開啟地址空間隨機(jī)化
Reserved:只有64位時(shí)才存在
-
Load Commands
image.png
LC_SEGMENT/LC_SEGMENT_64 - 將文件中(32位或64位)的段映射到進(jìn)程地址空間中
LC_SYMTAB - 符號(hào)表信息
LC_DYSYMTAB - 動(dòng)態(tài)符號(hào)表信息
LC_LOAD_DYLINKER - 加載動(dòng)態(tài)鏈接器(/usr/lib/dyld)
LC_UUID - 文件的唯一標(biāo)識(shí),crash解析中也會(huì)有,去匹配dysm文件和crash文件
LC_VERSION_MIN_IPHONEOS - 二進(jìn)制文件要求最低操作系統(tǒng)版本
LC_MAIN - 設(shè)置程序主線程的入口地址和棧大小
LC_ENCRYPTION_INFO - 加密信息,查看文件加密信息(otool -l <可執(zhí)行文件> | grep cryptid)
LC_LOAD_DYLIB - 加載的動(dòng)態(tài)庫(kù),包括動(dòng)態(tài)庫(kù)地址和名稱,當(dāng)前版本號(hào),兼容版本號(hào)(otool -l <可執(zhí)行文件>)
LC_FUNCTION_STARTS - 函數(shù)起始地址表
LC_CODE_SIGNATURE - 代碼簽名信息
main函數(shù)地址查看

某些Segment中包含Section,Section是具體數(shù)據(jù)存放的地方
__TEXT中節(jié)分類:
__text - 主程序代碼
__stub_helper - 用于動(dòng)態(tài)鏈接的存根
__picsymbolstub4 - 用于動(dòng)態(tài)鏈接的存根
__objc_methname - Object-C的方法名
__objc_classname - Object-C的類名
__objc_methtype - Object-C的方法類型
__cstring - 字符串
指令查看節(jié)的信息
otool -s __TEXT __text <可執(zhí)行文件>

顯示最上面的10行數(shù)據(jù)
otool -tv <可執(zhí)行文件名> |head -n 10

__DATA中節(jié)分類:
__la_symbol_ptr - 延遲加載節(jié),通過dyld_stub_binder輔助鏈接(程序在加載時(shí),符號(hào)的地址沒有對(duì)應(yīng)到真實(shí)的地址,只有在第一次使用這個(gè)符號(hào)時(shí),才會(huì)去匹配這個(gè)符號(hào)的地址,第二次使用時(shí)就可以直接找到)
__nl_symbol_ptr - 非延遲加載節(jié)(程序在加載時(shí),符號(hào)的地址已經(jīng)確定下來,使用時(shí)可以直接找到)
__mod_init_func - 初始化的全局函數(shù)的地址,會(huì)在main函數(shù)之前執(zhí)行
__mod__term_func - 結(jié)束函數(shù)地址
__cfstring - Core Foundation用到的字符串
__objc_classlist - Object-C的類列表
__objc_protollist - 協(xié)議的列表
__objc_nlclslist - Object-C的load函數(shù)列表,比__mod_init_func更早執(zhí)行
__objc_const - Object-C的常量
__data - 初始化的可變的變量
__bss - 未初始化的靜態(tài)變量
- 查看可執(zhí)行文件簽名信息
codesign -dvvv <可執(zhí)行文件名>

Mach-O解析案例
-
主程序代碼__text真實(shí)偏移的計(jì)算(以armv7為例)
將可執(zhí)行文件,拖入Mach-OView中
image.png
armv7起始偏移:16384->0x4000
image.png
Section Header偏移:24936->0x6168
image.png
Section(__TEXT,__text)真實(shí)偏移:0x4000+0x6168->0xA168 - 通過Mach-O查看類名、方法名、字符串
新建類MyObject,然后編譯,將mach-o文件拖入MachOView中
#import "MyObject.h"
@implementation MyObject
- (void)my_init {
char *cStr = "c string is there";
NSString *ocStr = @"oc String is there";
}
@end
新建的類

新增的方法

代碼中的字符串

__DATA,_cfstring中只有oc的字符串

生活如此美好,今天就點(diǎn)到為止。。。



