Mach-O文件內(nèi)部揭秘

在windows上可執(zhí)行文件的格式是exe,在Linux上ELF是可執(zhí)行文件,而在蘋果系統(tǒng)上,Mac OS X和ios系統(tǒng)上,可執(zhí)行文件的格式是Mach-O格式。官方解釋地址:https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/index.html

1、Mach與Mach-O

這里先提醒大家一下,Mach不是Mac,Mac是蘋果電腦Macintosh的簡稱,而Mach則是一種操作系統(tǒng)內(nèi)核。Mach內(nèi)核被NeXT公司的NeXTSTEP操作系統(tǒng)使用。在Mach上,一種可執(zhí)行的文件格是就是Mach-O(Mach Object file format)。Mac OS X是Unix的“后代”,但所主要支持的可執(zhí)行文件格式是Mach-O。

iOS是從OS X演變而來,所以同樣是支持Mach-O格式的可執(zhí)行文件。

2、ios可執(zhí)行文件初探

作為ios開發(fā)者,我們比較熟悉ipa包,這種文件格式,然而,實(shí)際上這只是一個(gè)變相的zip的壓縮包。我們將其解壓之后發(fā)現(xiàn)


這其實(shí)是一個(gè)Payload的包 打開這個(gè)包 不能發(fā)現(xiàn) 這是一個(gè)test1.app的文件 也就是xcode生成的product文件

而這其實(shí)也就是一個(gè)文件夾,打開這個(gè)文件夾(顯示包含內(nèi)容)發(fā)現(xiàn)其中有一個(gè)同名的test1的可執(zhí)行文件,這就是我們最終要尋找的在ios上的可執(zhí)行文件

我們用file命令來查看這個(gè)文件的文件類型


這是一個(gè)64位的Mach-O 格式的可執(zhí)行文件


3、Mach-O文件細(xì)究

根據(jù)蘋果官方文檔提供Mach-O文件的數(shù)據(jù)主體可分為三個(gè)部分


頭部(Header)、加載命令(Load Commands)、數(shù)據(jù)(Data)

而數(shù)據(jù)部分則又被分割成了一段段的Segments。

下面我們使用otool工具來一探究竟

a) 先來查看下這個(gè)可執(zhí)行文件的頭部是怎樣的


一堆看不明白的東西,分別予以解釋

magic:0xfeedfacf 。這個(gè)東西是Mach-O的魔數(shù)。簡單介紹下什么叫做魔數(shù):很多類型的文件,其起始的幾個(gè)字節(jié)的內(nèi)容是固定的(或是有意填充,或是本就如此)。根據(jù)這幾個(gè)字節(jié)的內(nèi)容就可以確定文件類型,因此這幾個(gè)字節(jié)的內(nèi)容被稱為魔數(shù) (magic number)。

在OS X上 可執(zhí)行文件的標(biāo)識有這樣幾個(gè)魔數(shù):cafebabe、feedface、feadfacf、還有就是以#!開頭的。

cputype、cpusubtype:指的是CPU類型和CPU子類型

在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/mach里找到machine.h的定義 如下圖


這里有支持的cpu的詳細(xì)編號命名 0代表ARM的格式都將支持

caps: 額 官網(wǎng)上都沒介紹 這個(gè)待查

filetype 2:代表可執(zhí)行文件

ncmds:指的是加載命令(load commands)的數(shù)量,例子中一共22個(gè),編號0-21

sizeofcmds:表示要load的22個(gè)commands的總的大小

flags:可用來檢驗(yàn)是否開啟了PIE,如開啟了則需要移除方能正常使用MachOView才能把文件結(jié)構(gòu)檢測出來

它有這么幾種定義值:我們的文件無未定義引用?(MH_NOUNDEFS),是為動(dòng)態(tài)鏈接器(MH_DYLDLINK),使用two-level名Cheng綁定(MH_TWOLEVEL)且應(yīng)被加載到隨機(jī)地址?(MH_PIE).

b)再來看加載命令(Load Commands) 截取其中一個(gè)Commands來分析


Load command 0 :command編號

cmdLC_SEGMENT_64:即是將文件中的段映射進(jìn)內(nèi)存中的地址空間

segname:16字節(jié)段名稱

vmaddr:段虛擬內(nèi)存的起始地址

vmsize:段虛擬內(nèi)存的大小

fileoff:段在內(nèi)存中的偏移量

filesize:段在文件中的大小

maxprot:段頁面所需要的最高內(nèi)存保護(hù)

initprot:段頁面初始內(nèi)存保護(hù)

nsects:段中包含section的數(shù)量

flags:其他雜項(xiàng)標(biāo)志位

c)接下來看data,注意到command和data都是以segment為大單元字節(jié),但是在data里還有section字節(jié) 所以重點(diǎn)介紹section的組織格式 截取一個(gè)section供分析


sectname:section的名字

segname:section歸屬為哪一個(gè)segment

addr:secction起始內(nèi)存地址

size:section的大小

offset:該section的文件偏移量

align:字節(jié)大小對齊

reloff:重定位入口的文件偏移

nreloc:需要重定位的入口數(shù)量

flags:包含了section的類型和獨(dú)自的屬性

最后兩項(xiàng)保留用

了解了這些 才能根據(jù)Mach-O的文件結(jié)構(gòu) 去分析類的名稱和類的方法 即是class-dump的實(shí)現(xiàn)原理,同時(shí)這也是MachOView等的分析原理

參考自:http://turingh.github.io/2016/03/07/mach-o%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E5%88%86%E6%9E%90/

附上otool命令大全

-f print the fat headers

-a print the archive header

-h print the mach header

-l print the load commands

-L print shared libraries used

-D print shared library id name

-t print the text section (disassemble with -v)

-p ? start dissassemble from routine name

-s print contents of section

-d print the data section

-o print the Objective-C segment

-r print the relocation entries

-S print the table of contents of a library

-T print the table of contents of a dynamic shared library

-M print the module table of a dynamic shared library

-R print the reference table of a dynamic shared library

-I print the indirect symbol table

-H print the two-level hints table

-G print the data in code table

-v print verbosely (symbolically) when possible

-V print disassembled operands symbolically

-c print argument strings of a core file

-X print no leading addresses or headers

-m don't use archive(member) syntax

-B force Thumb disassembly (ARM objects only)

-q use llvm's disassembler (the default)

-Q use otool(1)'s disassembler

-mcpu=arg use `arg' as the cpu for disassembly

-j print opcode bytes

-P print the info plist section as strings

-C print linker optimization hints

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容