Mach-O文件內部揭秘

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

1、Mach與Mach-O

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

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

2、ios可執行文件初探

作為ios開發者,我們比較熟悉ipa包,這種文件格式,然而,實際上這只是一個變相的zip的壓縮包。我們將其解壓之后發現


這其實是一個Payload的包 打開這個包 不能發現 這是一個test1.app的文件 也就是xcode生成的product文件

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

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


這是一個64位的Mach-O 格式的可執行文件


3、Mach-O文件細究

根據蘋果官方文檔提供Mach-O文件的數據主體可分為三個部分


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

而數據部分則又被分割成了一段段的Segments。

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

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


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

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

在OS X上 可執行文件的標識有這樣幾個魔數: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的詳細編號命名 0代表ARM的格式都將支持

caps: 額 官網上都沒介紹 這個待查

filetype 2:代表可執行文件

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

sizeofcmds:表示要load的22個commands的總的大小

flags:可用來檢驗是否開啟了PIE,如開啟了則需要移除方能正常使用MachOView才能把文件結構檢測出來

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

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


Load command 0 :command編號

cmdLC_SEGMENT_64:即是將文件中的段映射進內存中的地址空間

segname:16字節段名稱

vmaddr:段虛擬內存的起始地址

vmsize:段虛擬內存的大小

fileoff:段在內存中的偏移量

filesize:段在文件中的大小

maxprot:段頁面所需要的最高內存保護

initprot:段頁面初始內存保護

nsects:段中包含section的數量

flags:其他雜項標志位

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


sectname:section的名字

segname:section歸屬為哪一個segment

addr:secction起始內存地址

size:section的大小

offset:該section的文件偏移量

align:字節大小對齊

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

nreloc:需要重定位的入口數量

flags:包含了section的類型和獨自的屬性

最后兩項保留用

了解了這些 才能根據Mach-O的文件結構 去分析類的名稱和類的方法 即是class-dump的實現原理,同時這也是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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容