Mach-O文件的格式如下图所示,0x01  Mach-O格式简单介绍皇冠现金app

越多技术干货请戳:听云博客

iOS系统一分配析(二)Mach-O二进制文件分析,

➠越来越多技术干货请戳:听云博客

0x01  Mach-O格式不难介绍

Mach-O文件格式是 OS X 与 iOS 系统上的可执行文件格式,类似于windows的 PE
文件 与 Linux(其他 Unix like)的 ELF
文件,借使不彻底搞清楚Mach-O的格式与有关内容,那么透彻研商 xnu
内核就无从谈起。

Mach-O文件的格式如下图所示:

皇冠现金app 1

有如下多少个部分构成:

1.
Header:保存了Mach-O的有个别中坚消息,蕴含了阳台、文件类型、LoadCommands的个数等等。

2.
LoadCommands:这一段紧跟Header,加载Mach-O文件时会使用这里的数码来规定内部存款和储蓄器的遍布。

3.
Data:每几个segment的具体数据都封存在那里,那里带有了实际的代码、数据等等。

0x02 FAT二进制数据 ,数据结构定义在 \<mach-o/fat.h\>

皇冠现金app 2

皇冠现金app 3

  1. 第贰段为magic 魔数,这里注意大小端,读出来之后供给看下是0xCAFEBABE依然0xBEBAFECA(不然即为thin),须要基于这么些来转后续读取的字节的字节序。
     能够看出来 前4byte 为 0xBEBAFECA ,表达为fat。

  2. 第三段为arch
    count,也便是该App或dSYM中蕴藏哪些CPU架构,比如armv柒 、arm64等,那几个事例中为2(后4byte
     0x 00 00 00 02),表示包罗了三种cpu架构。  

      sizeof(struct fat-header) = 8byte

  3. 继承段中蕴藏cputype(0x  0C 00  00 01)、cpusubtype (0x 00 00 00
    00)、offset (0x 00 10 00  00)、size(0x 00  F0 27
    00)等数据,依照fat中的结构定义,依次读取,那里必要表明的是,如若只含有一种CPU架构的话,是没有这段fat头定义的,能够跳过那有些,直接读取Arch数据。

       sizeof(struct fat-arch) = 20byte

4.
基于fat头中读取的offset数据,大家能够跳到文件对应的arch数据的任务,当然假诺唯有一种架构的话就不要求总括偏移量了。
下图给出解析的函数

皇冠现金app 4

0x03 Mach Header二进制数据

因而magic大家得以分别出是32-bit照旧64-bit,64-bit多了伍个字节的保留字段,那里同样需求留意字节序的标题,也正是判断magic,来规定是或不是必要转移字节序。
 

`sizeof(struct mach-header-64) = 32byte`  ; `sizeof(struct mach-header) = 28byte`

皇冠现金app 5

根据mach-header与mach-header_64的定义,很显眼能够看到,Headers的主要效用正是协理系统飞快的定位Mach-O文件的运营条件,文件类型。

皇冠现金app 6

皇冠现金app,FileType 

因为Mach-O文件不但用来贯彻可执行文件,同时还用来落到实处了别样剧情

  1. 水源扩张

  2. 库文件

  3. CoreDump

  4.  其它

皇冠现金app 7

上边是部分能够用到的文件类型

  1. MH-OBJECT    编写翻译进度中生出的  obj文件 (gcc -c xxx.c 生成xxx.o文件)

  2. MH-EXECUTABLE  可进行二进制文件 (/usr/bin/ls)

  3. MH-CORE      CoreDump (崩溃时的Dump文件)

  4. MH-DYLIB  动态库(/usr/lib/里面包车型地铁那一个共享库文件)

  5. MH-DYLINKER  连接器linker(/usr/lib/dyld文件)

  6. MH-KEXT-BUNDLE   内核扩充文件 (自个儿付出的简练内核模块)

flags

Mach-O headers还包蕴了有的很重庆大学的dyld的加载参数。

皇冠现金app 8

  1. MH-NOUNDEFS   目的并未未定义的记号,不设有链接正视

  2. MH-DYLDLINK     该对象文件是dyld的输入文件,不可能被另行的静态链接

  3. MH-PIE      允许私下的地方空间(开启ASL大切诺基  -\>Address Space Layout
    Randomization)

  4. MH-ALLOW-STACK-EXECUTION   栈内部存款和储蓄器可执行代码,一般是默许关闭的。

  5. MH-NO-HEAP-EXECUTION   堆内部存款和储蓄器无法实施代码

皇冠现金app 9

0x04 LoadCommands

Load Commands 直接就跟在Header前边,全数command占用内部存款和储蓄器的总数在Mach-O
Header里面已经提交了。在加载过Header之后固然经过解析LoadCommand来加载接下去的数量了。定义如下:

皇冠现金app 10

cmd字段

依照cmd字段的档次分歧,使用了差别的函数来加载。不难的列出一张表看一看在基本代码中不一样的command类型都有如何功效。

  1. LC-SE庆大霉素ENT;LC-SE丙胺搏来霉素ENT-64   在基础中由load-segment
    函数处理(将segment中的数据加载并映射到进程的内部存款和储蓄器空间去)

  2. LC-LOAD-DYLINKE奥迪Q3    在根本中由load-dylinker
    函数处理(调用/usr/lib/dyld程序)

  3. LC-UUID 在根本中由load-uuid 函数处理 (加载128-bit的唯一ID)

  4. LC-THREAD  在根本中由load-thread 函数处理
    (开启3个MACH线程,不过不分红栈空间)

  5. LC-UNIXTHREAD 在基本中由load-unixthread 函数处理 (开启三个UNIX
    posix线程)

  6. LC-CODE-SIGNATURE 在基本中由load-code-signature 函数处理
    (举行数字签名)

  7. LC-ENCLANDYPTION-INFO 在根本中由 set-code-unprotect 函数处理
    (加密二进制文件)

UUID 二进制数据    128byte

UUID是十五个字节(128bit)的一段数据,是文件的唯一标识,前面提到的符号化时,那一个UUID必供给和App二进制文件中的UUID一致,才能被正确的符号化。dwarfdump查看的UUID正是那段数据。读取这一部分数目时经过Command结构读取的,也等于第二段(0x0000001B)表示接下去的数据类型,第三段(0x00000018)数据的深浅(包涵Command数据)。 

SymTab 二进制数据

1.
标志表数据块结构,前二段依然是Command数据。后面4段分别为标记在文件中的偏移量(0x001DF5E0)、符号个数(0x001DF5E0)、字符串在文件中的偏移量(0x0020C3A0)、字符串表大小(0x000729A8)。 

2.
接下去正是读取Segment和Section数据块了,和方面读取数据块结构同样是根据Command结构读取,下图突显的Segment数据和Section数据,它们在二进制文件中它们是连连的,也正是每一条Segment数据背后会跟随多条对应的Section数据,Section的数额总数是因此Segment结构中的nsects决定的。 

3.
那边小编写了一个简易地Mach-O解析工具 [https://github.com/liutianshx2012/Tmacho\](https://github.com/liutianshx2012/Tmacho)

皇冠现金app 11

Segment数据

加载数据时,首要加载的正是LC-SE地霉素ET活着LC-SEGMENT_64。其余的Segment的用途在此处不做探索。

LCSE创新霉素ENT以及LC-SE地霉素ENT-64 定义如下图。

 

皇冠现金app 12

皇冠现金app 13

能够看来,那里当先57%的多少是用来提携内核将Segment映射到虚拟内部存款和储蓄器的。

nsects 字段,标示了Segment中有个别许secetion
,section是切实有用的数码存放的地点。

TEXT的vmaddr也正是先后的加载地址;
—DWA科雷傲F中评释了DWATucsonF数据块的音信,表示dSYM是DWA奥德赛F格式的数据结构。 

` sizeof(struct segment-command) = 56byte   ;   sizeof(struct segment-command-64) = 72byte`

Section数据

皇冠现金app 14

从Section数据中,大家得以找到—debug-info、—debug-pubnames,
—debug-line等调节和测试消息,通过那些调节和测试新闻大家能够找到程序中符号的苗子地址、变量类型等消息。倘使大家要符号化的话,就可以通过分析这一个数据得到大家想要的音讯。

Symbol 数据

经过SymTab中的数据足以获取Symbol在文件中的地点和个数,Symbol块数据中涵盖了标记的开局部址、字符串的偏移量等数码,那部分数据结构能够参见\<nlist.h\>

\<stabl.h\>。在这一部分多少总体读取后,就能够读取全数的记号数据了,相当于接下去的数量。 

Symbol String 数据

1.
通过SymTab和Symbo中的数据足以得到每一个符号字符串在文件中的偏移量和尺寸,每一种符号数据是以0最终的字符串。 

2.
我们透过上述两部分数据的结合就足以拿走每一种symbo在程序中的加载地址了。这几个多少对于事后做标记工作都卓殊的有救助。

3.
到此,关于dSYM文件中尾部数据读取就达成了。尾部数据都有照应的数据结构定义,读取时相对会比较便于些,解析数据时要留意字节序的题材,32-bit和64-bit数据结构的差别、字节长度的异样,DWARAV4F版本的异样,各个数据块之间都以紧凑联系的,二个字节的读取偏差就会招致后续数据的读取错误,正所谓差之毫厘,失之千里。

 

初稿链接:http://blog.tingyun.com/web/article/detail/1341

http://www.bkjia.com/IOSjc/1172803.htmlwww.bkjia.comtruehttp://www.bkjia.com/IOSjc/1172803.htmlTechArticleiOS系统分析(二)Mach-O二进制文件解析,
越多技术干货请戳:听云博客 0x01 Mach-O格式不难介绍 Mach-O文件格式是 OS X
与 iOS 系统上的可执…

0x01
 Mach-O格式不难介绍

Mach-O文件格式是
OS X 与 iOS 系统上的可执行文件格式,类似于windows的 PE 文件 与
Linux(别的 Unix like)的 ELF
文件,即使不彻底搞清楚Mach-O的格式与相关内容,那么透彻钻研 xnu
内核就无从谈起。

Mach-O文件的格式如下图所示:

皇冠现金app 15

有如下几个部分组成:

1.
Header:保存了Mach-O的一对大旨消息,包罗了平台、文件类型、LoadCommands的个数等等。

2.
LoadCommands:这一段紧跟Header,加载Mach-O文件时会使用这里的多寡来显明内部存款和储蓄器的分布。

3.
Data:每2个segment的求实多少都保存在此处,那里包蕴了切实可行的代码、数据等等。

0x02
FAT二进制数据 ,数据结构定义在 \<mach-o/fat.h\>

皇冠现金app 16

皇冠现金app 17

1.
先是段为magic 魔数,那里注意大小端,读出来之后需求看下是0xCAFEBABE照旧0xBEBAFECA(不然即为thin),供给依照那么些来转后续读取的字节的字节序。
 能够看出来 前4byte 为 0xBEBAFECA ,说明为fat。

2.
次之段为arch
count,也等于该App或dSYM中包涵如何CPU框架结构,比如armv七 、arm64等,那个例子中为2(后4byte
 0x 00 00 00 02),表示蕴涵了二种cpu架构。  

  `sizeof(struct fat-header) = 8byte`

3.
继续段中包括cputype(0x  0C 00  00 01)、cpusubtype (0x 00 00 00
00)、offset (0x 00 10 00  00)、size(0x 00  F0 27
00)等数据,根据fat中的结构定义,依次读取,那里需求评释的是,假若只包涵一种CPU架构的话,是尚未那段fat头定义的,能够跳过那有的,间接读取Arch数据。

   `sizeof(struct fat-arch) = 20byte`

4.
基于fat头中读取的offset数据,大家得以跳到文件对应的arch数据的职位,当然假若唯有一种架构的话就不必要总括偏移量了。
下图给出解析的函数

皇冠现金app 18

0x03
Mach Header二进制数据

通过magic我们能够分别出是32-bit照旧64-bit,64-bit多了陆个字节的保存字段,那里同样要求小心字节序的题材,也正是判定magic,来规定是还是不是需求更换字节序。
 

`sizeof(struct mach-header-64) = 32byte`  ; `sizeof(struct mach-header) = 28byte`

皇冠现金app 19

根据mach-header与mach-header_64的定义,很明显能够见见,Headers的重要成效就是赞助系统迅速的定点Mach-O文件的运作环境,文件类型。

皇冠现金app 20

FileType 

因为Mach-O文件不仅用来兑现可执行文件,同时还用来贯彻了别的内容

1.
水源扩大

2.
库文件

3.
CoreDump

4.
 其它

皇冠现金app 21

上边是部分得天独厚用到的文件类型

1.
MH-OBJECT    编写翻译进度中发生的  obj文件 (gcc -c xxx.c
生成xxx.o文件)

2.
MH-EXECUTABLE  可实施二进制文件 (/usr/bin/ls)

3.
MH-CORE      CoreDump (崩溃时的Dump文件)

4.
MH-DYLIB  动态库(/usr/lib/里面包车型地铁那个共享库文件)

5.
MH-DYLINKER  连接器linker(/usr/lib/dyld文件)

6.
MH-KEXT-BUNDLE   内核扩大文件 (本人费用的简单内核模块)

flags

Mach-O
headers还包括了有的很重大的dyld的加载参数。

皇冠现金app 22

1.
MH-NOUNDEFS   指标并未未定义的记号,不存在链接注重

2.
MH-DYLDLINK     该对象文件是dyld的输入文件,不可能被另行的静态链接

3.
MH-PIE      允许专断的地点空间(开启ASLSportage  -\>Address Space Layout
Randomization)

4.
MH-ALLOW-STACK-EXECUTION   栈内部存款和储蓄器可执行代码,一般是暗中认可关闭的。

5.
MH-NO-HEAP-EXECUTION   堆内存无法执行代码

皇冠现金app 23

0x04
LoadCommands

Load
Commands 直接就跟在Header后边,全体command占用内部存款和储蓄器的总数在Mach-O
Header里面已经提交了。在加载过Header之后正是经过解析LoadCommand来加载接下去的多寡了。定义如下:

皇冠现金app 24

cmd字段

传说cmd字段的种类分化,使用了分化的函数来加载。简单的列出一张表看一看在基础代码中分裂的command类型都有如何成效。

1.
LC-SE威他霉素ENT;LC-SEGMENT-64   在根本中由load-segment
函数处理(将segment中的数据加载并映射到进度的内部存款和储蓄器空间去)

2.
LC-LOAD-DYLINKE奥迪Q3    在基本中由load-dylinker
函数处理(调用/usr/lib/dyld程序)

3.
LC-UUID 在基本中由load-uuid 函数处理 (加载128-bit的唯一ID)

4.
LC-THREAD  在基本中由load-thread 函数处理
(开启3个MACH线程,不过不分配栈空间)

5.
LC-UNIXTHREAD 在基本中由load-unixthread 函数处理 (开启三个UNIX
posix线程)

6.
LC-CODE-SIGNATURE 在基本中由load-code-signature 函数处理
(进行数字签名)

7.
LC-ENC路虎极光YPTION-INFO 在基本中由 set-code-unprotect 函数处理
(加密二进制文件)

UUID
二进制数据    128byte

UUID是1陆个字节(128bit)的一段数据,是文件的绝无仅有标识,前面提到的符号化时,这几个UUID必须求和App二进制文件中的UUID一致,才能被科学的符号化。dwarfdump查看的UUID正是那段数据。读取那有的数码时通过Command结构读取的,也正是首先段(0x0000001B)表示接下去的数据类型,第3段(0x00000018)数据的分寸(包括Command数据)。 

SymTab
二进制数据

1.
标志表数据块结构,前二段依然是Command数据。后面4段分别为标志在文书中的偏移量(0x001DF5E0)、符号个数(0x001DF5E0)、字符串在文件中的偏移量(0x0020C3A0)、字符串表大小(0x000729A8)。 

2.
接下去正是读取Segment和Section数据块了,和上边读取数据块结构同样是依照Command结构读取,下图呈现的Segment数据和Section数据,它们在二进制文件中它们是三番五次的,也等于每一条Segment数据背后会尾随多条对应的Section数据,Section的数目总数是透过Segment结构中的nsects决定的。 

3.
那里自个儿写了2个简便地Mach-O解析工具 [https://github.com/liutianshx2012/Tmacho\](https://github.com/liutianshx2012/Tmacho)

皇冠现金app 25

Segment数据

加载数据时,首要加载的就是LC-SE地霉素ET活着LC-SE罗红霉素ENT_64。别的的Segment的用处在那里不做探索。

LCSE地霉素ENT以及LC-SE青霉素ENT-64
定义如下图。

 

皇冠现金app 26

皇冠现金app 27

能够看出,那里当先二分之一的数码是用来帮忙内核将Segment映射到虚拟内部存储器的。

nsects
字段,标示了Segment中有微微secetion
,section是实际有用的数量存放的地方。

TEXT的vmaddr也正是程序的加载地址;
—DWALacrosseF中标明了DWARAV4F数据块的消息,表示dSYM是DWARubiconF格式的数据结构。 

` sizeof(struct segment-command) = 56byte   ;   sizeof(struct segment-command-64) = 72byte`

Section数据

皇冠现金app 28

从Section数据中,咱们能够找到—debug-info、—debug-pubnames,
—debug-line等调节和测试音信,通过那几个调节和测试消息大家得以找到程序中符号的苗头地址、变量类型等音信。假诺大家要符号化的话,就足以因而分析那一个数量获得大家想要的音信。

Symbol
数据

通过SymTab中的数据能够赢得Symbol在文书中的地方和个数,Symbol块数据中隐含了符号的起头地址、字符串的偏移量等数码,这一部分数据结构可以参照\<nlist.h\>

\<stabl.h\>。在那有的数据总体读取后,就足以读取全数的符号数据了,也便是接下去的多寡。 

Symbol
String 数据

1.
由此SymTab和Symbo中的数据能够取得每一个符号字符串在文件中的偏移量和大小,每一个符号数据是以0结尾的字符串。 

2.
大家经过上述两有个别数据的组合就能够收获每一种symbo在先后中的加载地址了。那几个数据对于现在做标记工作都格外的有扶助。

3.
到此,关于dSYM文件中尾部数据读取就做到了。尾部数据都有对应的数据结构定义,读取时相对会比较易于些,解析数据时要小心字节序的标题,32-bit和64-bit数据结构的异样、字节长度的歧异,DWA宝马X3F版本的歧异,各种数据块之间都以紧凑联系的,四个字节的读取偏差就会导致后续数据的读取错误,正所谓差之毫厘,失之千里。

 

原稿链接:http://blog.tingyun.com/web/article/detail/1341