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文件和胖文件的文件结构如下:
Header
Mach-O有一个固定的文件头mach_header,格式如下图:
magic用于加载器判断该二进制文件用于32位还是64位。
cputype、cpusubtype作用是一样的,用于确保二进制文件适合并且可以在当前架构下运行。
filetype的可取值定义在<mach-o/loader.h>头文件中。常见的值如下表。
flags定义在<mach-o/loader.h>中
上表中可以看出,有两个flags和“执行”相关:MH_ALLOW_STACK_EXECUTION和MH_NO_HEAP_EXECTION.这两个flags都用于防止某些数据的执行,通常称为NX(Non-eXecutable).通过将数据所在的内存页面标记为不可执行,(一般情况下)可以防止黑客进行代码注入,因为黑客不能方便的执行数据段中的代码。如果试图执行数据段中的代码,则会引发一个硬件异常,进程会终止——让进程崩溃,从而避免执行注入的代码。
由于代码注入的常见方法时使用栈变量(即自动变量),因此默认情况下栈都标记为不可执行,而flags可以用于覆盖这种行为(非常危险)。堆则默认可执行。但是通过堆注入代码相对困难一些。
这两个flags的设置可以在系统级别进行:通过sysctl修改vm.allow_stack_exec和vm.allow_heap_exec变量。
在iOS中堆和栈都默认是不可执行的。
Mach-O的Header在Objective-C中定义为了如下结构体:
/*
* 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/
转载请注明出处!