Mach-O文件介紹之mach_header
Mach-O是OSX和iOS上的可執(zhí)行二進(jìn)制文件格式:Mach-Object。使用Mach-O(Mach對象)文件實現(xiàn)內(nèi)核擴(kuò)展,命令行工具,應(yīng)用程序,框架和庫(共享和靜態(tài))。
Mach-O文件具有以下數(shù)據(jù)區(qū)域(完整格式在OS X ABI Mach-O文件格式參考中描述):
? 標(biāo)題(Header):指定文件的目標(biāo)體系結(jié)構(gòu),如PPC,PPC64,IA-32或x86-64。
? 加載命令(Load commands):在虛擬內(nèi)存中指定文件的邏輯結(jié)構(gòu)和文件的布局。
? 原始段數(shù)據(jù)(Raw segment data):包含在加載命令中定義的段的原始數(shù)據(jù)。主要包含代碼、數(shù)據(jù),例如符號表,動態(tài)符號表等等。
iOS和OSX有兩種類型的目標(biāo)文件:Mach-O文件和通用二進(jìn)制文件(胖文件)。它們之間的區(qū)別是:Mach-O文件包含一種架構(gòu)(i386、x86_64、arm64等等)的對象代碼,而胖文件可能包含若干不同架構(gòu)對象代
碼的對象文件。
Mach-O文件和胖文件的文件結(jié)構(gòu)如下:


Header
Mach-O有一個固定的文件頭mach_header,格式如下圖:

magic用于加載器判斷該二進(jìn)制文件用于32位還是64位。
cputype、cpusubtype作用是一樣的,用于確保二進(jìn)制文件適合并且可以在當(dāng)前架構(gòu)下運(yùn)行。
filetype的可取值定義在<mach-o/loader.h>頭文件中。常見的值如下表。

flags定義在<mach-o/loader.h>中

上表中可以看出,有兩個flags和“執(zhí)行”相關(guān):MH_ALLOW_STACK_EXECUTION和MH_NO_HEAP_EXECTION.這兩個flags都用于防止某些數(shù)據(jù)的執(zhí)行,通常稱為NX(Non-eXecutable).通過將數(shù)據(jù)所在的內(nèi)存頁面標(biāo)記為不可執(zhí)行,(一般情況下)可以防止黑客進(jìn)行代碼注入,因為黑客不能方便的執(zhí)行數(shù)據(jù)段中的代碼。如果試圖執(zhí)行數(shù)據(jù)段中的代碼,則會引發(fā)一個硬件異常,進(jìn)程會終止——讓進(jìn)程崩潰,從而避免執(zhí)行注入的代碼。
由于代碼注入的常見方法時使用棧變量(即自動變量),因此默認(rèn)情況下棧都標(biāo)記為不可執(zhí)行,而flags可以用于覆蓋這種行為(非常危險)。堆則默認(rèn)可執(zhí)行。但是通過堆注入代碼相對困難一些。
這兩個flags的設(shè)置可以在系統(tǒng)級別進(jìn)行:通過sysctl修改vm.allow_stack_exec和vm.allow_heap_exec變量。
在iOS中堆和棧都默認(rèn)是不可執(zhí)行的。
Mach-O的Header在Objective-C中定義為了如下結(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 */
};
/* 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/
轉(zhuǎn)載請注明出處!