Mach-O文件介绍之mach_header

Mach-O文件介绍之mach_header

Mach-O是OSX和iOS上的可执行二进制文件格式:Mach-Object。使用Mach-O(Mach对象)文件实现内核扩展,命令行工具,应用程序,框架和库(共享和静态)。

Mach-O文件具有以下数据区域(完整格式在OS X ABI Mach-O文件格式参考中描述):
标题(Header):指定文件的目标体系结构,如PPC,PPC64,IA-32或x86-64。
加载命令(Load commands):在虚拟内存中指定文件的逻辑结构和文件的布局。
原始段数据(Raw segment data):包含在加载命令中定义的段的原始数据。主要包含代码、数据,例如符号表,动态符号表等等。

iOS和OSX有两种类型的目标文件:Mach-O文件和通用二进制文件(胖文件)。它们之间的区别是:Mach-O文件包含一种架构(i386、x86_64、arm64等等)的对象代码,而胖文件可能包含若干不同架构对象代
码的对象文件。
Mach-O文件和胖文件的文件结构如下:
Mach-O文件.jpg
胖文件.jpg

Mach-O有一个固定的文件头mach_header,格式如下图:

magic用于加载器判断该二进制文件用于32位还是64位。
cputype、cpusubtype作用是一样的,用于确保二进制文件适合并且可以在当前架构下运行。
filetype的可取值定义在头文件中。常见的值如下表。

flags定义在

上表中可以看出,有两个flags和“执行”相关:MH_ALLOW_STACK_EXECUTIONMH_NO_HEAP_EXECTION.这两个flags都用于防止某些数据的执行,通常称为NX(Non-eXecutable).通过将数据所在的内存页面标记为不可执行,(一般情况下)可以防止黑客进行代码注入,因为黑客不能方便的执行数据段中的代码。如果试图执行数据段中的代码,则会引发一个硬件异常,进程会终止——让进程崩溃,从而避免执行注入的代码。
由于代码注入的常见方法时使用栈变量(即自动变量),因此默认情况下栈都标记为不可执行,而flags可以用于覆盖这种行为(非常危险)。堆则默认可执行。但是通过堆注入代码相对困难一些。
这两个flags的设置可以在系统级别进行:通过sysctl修改vm.allow_stack_exec和vm.allow_heap_exec变量。
在iOS中堆和栈都默认是不可执行的。

Mach-O的Header在Objective-C中定义为了如下结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * 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 */
};
/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */

本文作者: ctinusdev
本文链接: https://ctinusdev.github.io/2017/08/20/Mach-OBasis_Header/
转载请注明出处!

坚持原创技术分享,您的支持将鼓励我继续创作!