Mach-O

格式

Mash-O格式.gif
1. header

header 包含了,cpu类型,加载command的数量,文件类型等信息

/*
* The 32-bit mach header appears at the very beginning of the object file for
* 32-bit architectures.
32位 架构数据结构类型
*/
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.
64位架构数据结构类型
*/
struct mach_header_64 {
  uint32_t    magic;      /* mach magic number identifier */
// 识CPU的架构 arm x86, i386
  cpu_type_t  cputype;    /* cpu specifier */
// 体的CPU类型,区分不同版本的处理器
  cpu_subtype_t   cpusubtype; /* machine specifier */
// 文件类型
  uint32_t    filetype;   /* type of file */
//加载了多少command,每个LoadCommands代表了一种Segment的加载方式
  uint32_t    ncmds;      /* number of load commands */
//LoadCommand的大小,主要用于划分Mach-O文件的‘区域’
  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 */
#define MH_CIGAM_64 0xcffaedfe /* 

经常遇见的Mach-O文件类型:

  • MH_OBJECT,这种类型的文件有目标文件(.o)、静态库文件(.a) (静态库文件就是N个.o文件合并在一起的)

  • MH_EXECUTE,可执行文件,例如上面说的Super文件

  • MH_DYLIB,动态库文件,包括.dylib、.framework

  • MH_DYLINKER,动态链接编辑器,例如:位于手机这里的Device/usr/lib/的dyld程序

MH_DSYM,存储二进制符号信息的文件,dsym文件常用于分析APP的崩溃信息

loadCommands

用来描述文件在虚拟地址中的布局结构,就是存储着各段数据的大小,分段,地址等信息

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

这些加载指令清晰地告诉加载器如何处理二进制数据,有些命令是由内核处理的,有些是由动态链接器处理的。在源码中有明显的注释来说明这些是动态连接器处理的。
根据cmd字段的类型不同,使用了不同的函数来加载.看一看在内核代码中不同的command类型都有哪些作用。

  1. LC-SEGMENT;LC-SEGMENT-64 在内核中由load-segment 函数处理(将segment中的数据加载并映射到进程的内存空间去)

  2. LC-LOAD-DYLINKER 在内核中由load-dylinker 函数处理(调用/usr/lib/dyld程序)

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

  4. LC-THREAD 在内核中由load-thread 函数处理 (开启一个MACH线程,但是不分配栈空间)

  5. LC-UNIXTHREAD 在内核中由load-unixthread 函数处理 (开启一个UNIX posix线程)

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

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

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 */
};
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 */
};

section段

存放着各段的原始数据,就是Load commands区域描述的地址所指向的数据

注入dylib整体思路

1、读取Mach-O文件信息到内存中;

2、定义一个mach_header,将原来的mach_header写到新定义的mach_header中;

3、 在新定义的mach_header中依需将ncmds加1,sizeofcmds加上要注入的dylib库的大小;

4、将新定义并修改好的mach_header从Mach-O最开始部分覆盖原文件的mach_header;

5、指针跳过sizeofcmds大小内存;

6、定义一个dylib结构体并赋值,即注入的 dylib 信息;

7、回退(新mach_header中sizeofcmds已包含要注入dylib的大小)并覆盖、写入 path 信息。

命令 数据结构 用途
LC_UUID uuid_command(page 20) 指定图像或其对应的dSYM文件的128位UUID
LC_SEGMENT segment_command 加载此文件时,定义映射到进程地址空间中所需的文件段。而且每个段中包含了所有的节
LC_SYMTAB symtab_command 指定了文件的符号表。静态链接器和动态连接器连接文件的时候都需要用到这些信息,还可以通过调试器将符号映射到生成符号的原始源代码文件。
LC_DYSYMTAB dysymtab_command 指定了动态连接器用到的附带符号表信息
LC_THREAD LC_UNIXTHREAD thread_command 对于可执行文件,LC_UNIXTHREAD命令定义了进程主线程的线程状态。LC_THREAD和LC_UNIXTHREAD一样,但是LC_THREAD不会引起内核分配堆栈
LC_LOAD_DYLIB dylib_command 定义此文件链接的动态共享库的名称。
LC_ID_DYLIB dylib_command 定义了动态共享库安装名称
LC_PREBOUND_DYLIB prebound_dylib_command 对于此可执行文件链接预绑定的共享库,指定使用的共享库中的模块。
LC_LOAD_DYLINKER dylinker_command 指定内核执行加载文件所需的动态连接器
LC_ID_DYLINKER dylinker_command 标志这个文件可以作为动态连接器
LC_ROUTINES routines_command 包含共享库初始化例行程序的地址(由链接器的-init选项指定)。
LC_ROUTINES_64 routines_command_64 包含共享库64位初始化例行程序的地址(由链接器的-init选项指定)。
LC_TWOLEVEL_HINTS twolevel_hints_command 包含两级命名空间查询提示表。
LC_SUB_FRAMEWORK sub_framework_command 将此文件标识为伞形框架的子框架的实现。伞形框架的名称存储在字符串参数中。(伞形框架可以包含多个子框架,苹果不推荐这样使用)
LC_SUB_UMBRELLA sub_umbrella_command 指定此文件作为伞框架的子伞
LC_SUB_LIBRARY sub_library_command 标志这个文件可以作为伞框架的一个字库的实现。请注意,Apple尚未为子库定义受支持的位置。
LC_SUB_CLIENT sub_client_command 子框架可以明确地允许另一个框架或包链接到它,方法是包含一个LC_SUB_CLIENT load命令,该命令包含框架的名称或包的客户端名称。

1、(__TEXT,__text)

这里存放的是汇编后的代码,当我们进行编译时,每个.m文件会经过预编译->编译->汇编形成.o文件,称之为目标文件。汇编后,所有的代码会形成汇编指令存储在.o文件的(__TEXT,__text)区((__DATA,__data)也是类似)。链接后,所有的.o文件会合并成一个文件,所有.o文件的(__TEXT,__text)数据都会按链接顺序存放到应用文件的(__TEXT,__text)中。

2、(__DATA,__data)

存储数据的section,static在进行非零赋值后会存储在这里,如果static 变量没有赋值或者赋值为0,那么它会存储在(__DATA,__bss)中。

3、Symbol Table

符号表,这个是重点中的重点,符号表是将地址和符号联系起来的桥梁。符号表并不能直接存储符号,而是存储符号位于字符串表的位置。

4、String Table

字符串表所有的变量名、函数名等,都以字符串的形式存储在字符串表中。

5、动态符号表

动态符号表存储的是动态库函数位于符号表的偏移信息。(__DATA,__la_symbol_ptr) section 可以从动态符号表中获取到该section位于符号表的索引数组。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 概述   本文档描述了Mach-O文件格式的结构,它被用来存储程序和库到硬盘中,作为Mac OS X程序的二进制接...
    VenpleD阅读 1,408评论 0 5
  • 上一篇说到源码经过预处理、编译、汇编之后生成目标文件,这一章介绍一下iOS、Mac OS中目标文件的格式Mach-...
    Tenloy阅读 2,008评论 2 9
  • Mach-o文件 Mach-O 是iOS/macOS系统上应用程序的格式 通用二进制文件(胖二进制文件) 因为Ma...
    CharType阅读 951评论 0 2
  • 一、什么是Mach-O文件? Mach-O是 Mach Object文件格式的缩写,是 mac以及 iOS上可执行...
    黑白森林无间道阅读 1,022评论 1 2
  • 一、什么是Mach-O文件? Mach-O是Mach Object文件格式的缩写,是mac以及iOS上可执行文件的...
    yahibo阅读 482评论 0 1