MachO文件

1、MachO文件的概念

Mach-O 其實是Mach Object文件格式的縮寫,是 mac 以及 iOS 上可執(zhí)行文件的格式捆蜀, 類似于 windows 上的 PE 格式 (Portable Executable), linux 上的 elf 格式 (Executable and Linking Format) 。常?的 .o.a .dylib Framework踱阿,dyld .dsym

2钦铁、整體結(jié)構(gòu)如下圖

MachO結(jié)構(gòu)圖.png

2.1软舌、Header(頭部)

Header表明該文件是 Mach-O 格式,指定目標(biāo)架構(gòu)牛曹,還有一些其他的文件屬性信 息佛点,文件頭信息影響后續(xù)的文件結(jié)構(gòu)安排。
與 Mach-O 文件格式有關(guān)的結(jié)構(gòu)體定義都可以從xnu源碼loader.h中找到黎比。

32位和64位的mach_header的數(shù)據(jù)結(jié)構(gòu)如下

/*
 * The 32-bit mach header appears at the very beginning of the object file for
 * 32-bit architectures.
 */
struct mach_header {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
};

/* Constant for the magic field of the mach_header (32-bit architectures) */
#define MH_MAGIC    0xfeedface  /* the mach magic number */
#define MH_CIGAM    0xcefaedfe  /* NXSwapInt(MH_MAGIC) */

/*
 * The 64-bit mach header appears at the very beginning of object files for
 * 64-bit architectures.
 */
struct mach_header_64 {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
    uint32_t    reserved;   /* reserved */
};
  • magic 魔數(shù)(特征數(shù)字)超营,用來標(biāo)記當(dāng)前設(shè)備是大端序還是小端序。
  • cputype 標(biāo)識 CPU 的架構(gòu)阅虫,例如 ARM演闭、ARM64、X86_64 等书妻。
  • cpusubtype 標(biāo)識 CPU 的具體類型船响,區(qū)分不同版本的處理器躬拢。
  • filetype 由于 Mach-O 支持多種類型文件,所以此處引入了 filetype 字段來標(biāo)明( .o见间,.a .dylib Framework聊闯,dyld .dsym等)
  • ncmds Mach-O 文件中加載命令(load commands)的條數(shù)。
  • sizeofcmds Mach-O文件中加載命令(load commands)的總大小米诉。
  • flags 標(biāo)識著 Mach-O 文件的一些重要信息(可以 loader.h中查看結(jié)構(gòu)菱蔬,其中MH_PIE啟用ASLR)
  • reserved 64位預(yù)留字段

2.2、Load commands

Load commands 是一張包含很多內(nèi)容的表史侣。內(nèi)容包括區(qū)域的位置拴泌、符號表、動態(tài)符號表 等惊橱。用于告訴loader如何設(shè)置并加載二進制數(shù)據(jù),對系統(tǒng)內(nèi)核加載器和動態(tài)鏈接器(dyld)起指導(dǎo)作用蚪腐。
load_command的數(shù)據(jù)結(jié)構(gòu)

struct load_command {
    uint32_t cmd;       /* type of load command */
    uint32_t cmdsize;   /* total size of command in bytes */
};

前 4 個字節(jié)表示類型,不同類型的 load command 作用不一樣税朴,緊跟其后的 4 個字節(jié)表示該 load command 的大小.
可以通過MachOView軟件來查看類容(類型)

64位系統(tǒng)load command內(nèi)容.png

  • LC_SEGMENT_64 將文件中(32位或64位)的段映射到進程地 址空間中
  • LC_DYLD_INFO_ONLY 動態(tài)鏈接相關(guān)信息
  • LC_SYMTAB 符號地址
  • LC_DYSYMTAB 動態(tài)符號表地址
  • LC_LOAD_DYLINKER dyld加載
  • LC_UUID 文件的UUID
  • LC_VERSION_MIN_MACOSX 支持最低的操作系統(tǒng)版本
  • LC_SOURCE_VERSION 源代碼版本
  • LC_MAIN 設(shè)置程序主線程的入口地址和棧大小
  • LC_LOAD_DYLIB 依賴庫的路徑回季,包含三方庫
  • LC_FUNCTION_STARTS 函數(shù)起始地址表
  • LC_CODE_SIGNATURE 代碼簽名
  • LC_ENCRYPTION_INFOLC_ENCRYPTION_INFO_64:加密信息,如果是從App Store上下載的應(yīng)用正林,外面被加了一層殼泡一,對應(yīng)的加密標(biāo)記(Crypt ID)不為0,如果不是App Store上下載的應(yīng)用(例如PP助手上)觅廓,或這個已經(jīng)被脫過殼的鼻忠,加密標(biāo)記(Crypt ID)便為0

LC_SEGMENT(段)

LC_SEGMENT_64LC_SEGMENT(32位系統(tǒng))是加載的主要命令,翻譯成中文叫做“段”杈绸,它負(fù)責(zé)指導(dǎo)內(nèi)核來設(shè)置進程的內(nèi)存空間帖蔓,說白了,只要是這個類型的 load command蝇棉,系統(tǒng)會將其指示的內(nèi)容全部加載到指定的虛擬內(nèi)存地址上來讨阻。
MachOView看到的內(nèi)容

LC_SEGMENT_64.png

通過mach-o/loader.h 找到數(shù)據(jù)結(jié)構(gòu)

struct segment_command { /* for 32-bit architectures */
    uint32_t    cmd;        /* LC_SEGMENT */
    uint32_t    cmdsize;    /* includes sizeof section structs */
    char        segname[16];    /* segment name */
    uint32_t    vmaddr;     /* memory address of this segment */
    uint32_t    vmsize;     /* memory size of this segment */
    uint32_t    fileoff;    /* file offset of this segment */
    uint32_t    filesize;   /* amount to map from the file */
    vm_prot_t   maxprot;    /* maximum VM protection */
    vm_prot_t   initprot;   /* initial VM protection */
    uint32_t    nsects;     /* number of sections in segment */
    uint32_t    flags;      /* flags */
};

struct segment_command_64 { /* for 64-bit architectures */
    uint32_t    cmd;        /* LC_SEGMENT_64 */
    uint32_t    cmdsize;    /* includes sizeof section_64 structs */
    char        segname[16];    /* segment name */
    uint64_t    vmaddr;     /* memory address of this segment */
    uint64_t    vmsize;     /* memory size of this segment */
    uint64_t    fileoff;    /* file offset of this segment */
    uint64_t    filesize;   /* amount to map from the file */
    vm_prot_t   maxprot;    /* maximum VM protection */
    vm_prot_t   initprot;   /* initial VM protection */
    uint32_t    nsects;     /* number of sections in segment */
    uint32_t    flags;      /* flags */
};
  • cmd 該加載命令類型,為LC_SEGMENT_64(64位)或LC_SEGMENT(32位)
  • cmdsize 該加載命令大小篡殷,包括segement下session結(jié)構(gòu)所占大小
  • segname[16] segment 名字
  • vmaddr 為當(dāng)前segment分配的虛擬內(nèi)存地址
  • vmsize 為當(dāng)前segment分配的虛擬內(nèi)存大小
  • fileoff 當(dāng)前segment在 Mach-O 文件中的偏移量
  • filesize 當(dāng)前segment在 Mach-O 文件中占用的字節(jié)
  • maxprot segment所在頁所需要的最高內(nèi)存保護
  • initprot segment所在頁原始內(nèi)存保護
  • nsects segment中section數(shù)量
  • flags 標(biāo)識符

大致可以這么理解:系統(tǒng) Mach-O 從fileoff處加載filesie大小的內(nèi)容到虛擬內(nèi)存vmaddr處钝吮,大小為vmsizesegment頁權(quán)限initport進行初始化板辽,這些權(quán)限可以被修改奇瘦,但是不能超過maxprot的值。通俗來說就是劲弦,fileofffilesie指導(dǎo)和說明了內(nèi)容從哪里來耳标,vmaddrvmsize指導(dǎo)和說明了文件到哪里去。需要留意邑跪,對某些segment來說次坡,vmsize可能會大于 filesize呼猪,如__DATA、__LINKEDIT砸琅。

segname分類(用下劃線和大寫字母組成)

  • __PAGEZERO:靜態(tài)鏈接器創(chuàng)建了__PAGEZERO命名的段作為可執(zhí)行文件的第一個段宋距,該段在文件中所占大小為0,在 32 位系統(tǒng)上症脂,加載到虛擬內(nèi)存中是 0x4000谚赎,也就是 16kb阱飘,在 64 位系統(tǒng)上到千,加載到虛擬未存中是 0x100000000摩桶,也就是 4GB谒所。是一個不可讀、不可寫唬格、不可執(zhí)行的空間扳还,能夠在空指針訪問時拋出異常土浸。
  • __TEXT:代碼段橙凳,里面包含了可執(zhí)行代碼和其他一些只讀數(shù)據(jù)蕾殴,該段是可讀、可執(zhí)行岛啸,但是不可寫。
  • __DATA:數(shù)據(jù)段茴肥,里面主要是存放將會被更改的數(shù)據(jù)坚踩,該段是可讀、可寫瓤狐,但不可執(zhí)行瞬铸。
  • __LINKEDIT:包含需要被動態(tài)鏈接器使用的符號和其他表,包括符號表础锐、字符串表等嗓节,可讀,但不可寫不可執(zhí)行皆警。

segname下的section
segname__TEXT__DATA兩個segment可以進一步分解為section拦宣。之所以按照segment -> section的結(jié)構(gòu)組織方式,是因為在同一個segment下的section信姓,可以控制相同的權(quán)限鸵隧,也可以不完全按照Page的大小進行內(nèi)存對其,節(jié)省內(nèi)存的空間意推。而segment對外整體暴露豆瘫,在程序載入階段映射成一個完整的虛擬內(nèi)存,更好的做到內(nèi)存對齊菊值。

mach-o/loader.h文件中可以找到section的數(shù)據(jù)結(jié)構(gòu)

struct section { /* for 32-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint32_t    addr;       /* memory address of this section */
    uint32_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
};

struct section_64 { /* for 64-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint64_t    addr;       /* memory address of this section */
    uint64_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
    uint32_t    reserved3;  /* reserved */
};
  • sectname:section名字
  • segname:section所在的segment名稱
  • addr:section所在的內(nèi)存地址
  • size:section的大小
  • offset:section所在的文件偏移
  • align:section的內(nèi)存對齊邊界 (2 的次冪)
  • reloff:重定位信息的文件偏移
  • nreloc:重定位條目的數(shù)目
  • flags:標(biāo)志屬性
  • reserved:保留字段

使用 MachOView 進行查看OC工程的macho文件


oc的segname下的section.png

各個section作用如下:

  • __TEXT.__text:主程序代碼
  • __TEXT.__stubs外驱、__TEXT.__stub_helper:用于幫助動態(tài)鏈接器綁定符號
  • __TEXT.__const:const關(guān)鍵字修飾的常量
  • __TEXT.__objc_methodname:OC方法名
  • __TEXT.__cstring:只讀的C語言字符串
  • __TEXT.__objc_classname:OC類名
  • __TEXT.__objc_methtype:OC方法類型(方法簽名)
  • __TEXT.__gcc_except_tab育灸、__ustring__unwind_info:GCC編譯器自動生成昵宇,用于確定異常發(fā)生是棧所對應(yīng)的信息(包括棧指針描扯、返回地址及寄存器信息等)
  • __DATA.__got:全局非懶綁定符號指針表
  • __DATA.__la_symbol_ptr:懶綁定符號指針表
  • __DATA.__mod_init_func:C++類的構(gòu)造函數(shù)
  • __DATA.__const:未初始化過的常量
  • __DATA.__cfstring:Core Foundation字符串
  • __DATA.__objc_classlist:OC類列表
  • __DATA.__objc_nlclslist:實現(xiàn)+load方法的 OC 類列表
  • __DATA.__catlist:OC 分類(Category)列表
  • __DATA.__protolist:OC 協(xié)議(Protocol)列表
  • __DATA.__imageinfo:鏡像信息,可用它區(qū)別 OC 1.0與2.0
  • __DATA.__const:OC 初始化過的常量
  • __DATA.__selrefs:OC 選擇器(SEL)引用列表
  • __DATA.__protorefs:OC 協(xié)議引用列表
  • __DATA.__classrefs:OC 類引用列表
  • __DATA.__superrefs:OC 超類(即父類)引用列表
  • __DATA.__ivar:OC 類的實例變量
  • __DATA.__objc_data:OC 初始化過的變量
  • __DATA.__data:實際初始化數(shù)據(jù)段
  • __DATA.__common:未初始化過的符號申明
  • __DATA.__bss:未初始化的全局變量

使用 MachOView 進行查看Swift工程的macho文件

swift5的macho.png

在Swift的macho文件中趟薄,types是4字節(jié)存儲信息绽诚,存儲的是相對地址
注意:swift5的macho會多出幾個section(目前知道的就是下面幾個,后面了解再補充)

__swift5_types:存儲的是Class杭煎、Struct恩够、Enum的描述(Descriptor)偏移信息
__swift5_fieldmd:存儲的是屬性描述(屬性信息)的偏移信息
__swift5_reflstr:存儲的是屬性名稱
__swift5_protos:存儲的是代理的描述

2.3、Data

Data 區(qū)主要就是負(fù)責(zé)代碼和數(shù)據(jù)記錄的羡铲。Mach-O 是以 Segment 這種結(jié)構(gòu)來組織數(shù)據(jù) 的蜂桶,一個 Segment 可以包含 0 個或多個 Section。根據(jù) Segment 是映射的哪一個 Load Command也切,Segment 中 section 就可以被解讀為是是代碼扑媚,常量或者一些其他的數(shù)據(jù)類 型。在裝載在內(nèi)存中時雷恃,也是根據(jù) Segment 做內(nèi)存映射的疆股。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市倒槐,隨后出現(xiàn)的幾起案子旬痹,更是在濱河造成了極大的恐慌,老刑警劉巖讨越,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件两残,死亡現(xiàn)場離奇詭異,居然都是意外死亡把跨,警方通過查閱死者的電腦和手機人弓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來着逐,“玉大人崔赌,你說我怎么就攤上這事”踔觯” “怎么了峰鄙?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長太雨。 經(jīng)常有香客問我吟榴,道長,這世上最難降的妖魔是什么囊扳? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任吩翻,我火速辦了婚禮兜看,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狭瞎。我一直安慰自己细移,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布熊锭。 她就那樣靜靜地躺著弧轧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碗殷。 梳的紋絲不亂的頭發(fā)上精绎,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音锌妻,去河邊找鬼代乃。 笑死,一個胖子當(dāng)著我的面吹牛仿粹,可吹牛的內(nèi)容都是我干的搁吓。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼吭历,長吁一口氣:“原來是場噩夢啊……” “哼堕仔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毒涧,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤贮预,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后契讲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡滑频,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年捡偏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峡迷。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡银伟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绘搞,到底是詐尸還是另有隱情彤避,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布夯辖,位于F島的核電站琉预,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蒿褂。R本人自食惡果不足惜圆米,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一卒暂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娄帖,春花似錦也祠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至削葱,卻和暖如春奖亚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佩耳。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工遂蛀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人干厚。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓李滴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛮瞄。 傳聞我的和親對象是個殘疾皇子所坯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容

  • MachO文件 Mach-O是Mach Object文件格式的縮寫,是mac以及iOS上可執(zhí)行文件的格式挂捅。是一種用...
    忻凱同學(xué)閱讀 1,404評論 0 1
  • 前言 本篇文章主要分析MachO文件(也稱作二進制可執(zhí)行文件)芹助,相信大家在平時開發(fā)中都會碰到MachO文件這個概念...
    深圳_你要的昵稱閱讀 653評論 0 2
  • 在上一篇文章中,咱們已經(jīng)簡單的提到了MachO闲先,在用Framework做代碼注入的時候状土,必須先向MachO的Loa...
    螞蟻也瘋狂閱讀 1,797評論 1 4
  • MachO文件 Mach-O其實就是Mach Object文件格式的縮寫,是mac以及iOS上可執(zhí)行文件的格式伺糠,類...
    coder_feng閱讀 659評論 0 1
  • MachO文件 前言 Mach-O(Mach Object):Mach-O 文件是Mach object文件格式的...
    superFool閱讀 743評論 0 0