iOS攻防-序章(1)-Mach-O文件结构解析

前言:最近因为工作需要,一直在研究iOS的逆向工程。说起来,这个方面涉及到的的知识面实在太广,所以想开一个系列,从基础知识到实战攻防,系统的总结一下最近的所思所学。

第一篇,先从一个基础知识开始:Mach-O文件。

说起Mach-O文件,很多开发人员应该不陌生。即使你没有听过Mach-O,但你也肯定知道exe文件是什么。每个操作系统都有自己的可执行文件,比如Linux下的ELF,Windows下的exe。而Mach-O,就是Mac系统上的可执行文件。比如,每个iOS开发几乎都接触过dsym,dsym就是一种Mach-O文件。

这里先介绍一个工具:MachOView,一个观察Mach-O文件的利器,我们之后的后多观察都是使用这个工具来进行。

构成

Mach-O 主要包括了HeaderLoad commandsDataSegement和Section)等几个部分

用网上的一张图来描述下Mach-O的结构:

iOS攻防-序章(1)-Mach-O文件结构解析_第1张图片

Header:

iOS攻防-序章(1)-Mach-O文件结构解析_第2张图片

header是一些基础信息,比如魔数、CPU构架、文件类型等等

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 */
};
  • magic:魔数,用于快速确认该文件用于64位还是32位
  • cputype:CPU类型,比如 arm
  • cpusubtype:CPU具体类型,比如arm64、armv7
  • filetype:文件类型,比如可执行文件EXECUTE、库文件、Dsym文件等
* Constants for the filetype field of the mach_header
 */
#define MH_OBJECT   0x1     /* relocatable object file */
#define MH_EXECUTE  0x2     /* demand paged executable file */
#define MH_FVMLIB   0x3     /* fixed VM shared library file */
#define MH_CORE     0x4     /* core file */
#define MH_PRELOAD  0x5     /* preloaded executable file */
#define MH_DYLIB    0x6     /* dynamically bound shared library */
#define MH_DYLINKER 0x7     /* dynamic link editor */
#define MH_BUNDLE   0x8     /* dynamically bound bundle file */
#define MH_DYLIB_STUB   0x9     /* shared library stub for static */
#define MH_DSYM     0xa     /* companion file with only debug */
#define MH_KEXT_BUNDLE  0xb     /* x86_64 kexts */
  • ncmds :加载命令条数
  • sizeofcmds:所有加载命令的大小
  • reserved:保留字段
  • flags:标志位

这里特别提一下flags,它有4个标志位:

#define MH_NOUNDEFS 0x1     // 目前没有未定义的符号,不存在链接依赖
#define    MH_DYLDLINK  0x4     // 该文件是dyld的输入文件,无法被再次静态链接
#define MH_PIE 0x200000     // 加载程序在随机的地址空间,只在 MH_EXECUTE中使用
#define    MH_TWOLEVEL  0x80    // 两级名称空间

iOS攻防-序章(1)-Mach-O文件结构解析_第3张图片

注意MH_PIE这个值,为什么需要在进程启动时随机化程序加载的地址空间?有在pc时代玩过“金手指”的同学应该会有体会(不要问我这是啥,会暴露年龄),如果程序每次启动都是固定的静态地址,那要通过重写内存的方式来破解程序就相对容易的多。所以MH_PIE是iOS保护自己应用程序不被动态破解的重要手段。

Load commands

Heads之后就是Load commands,从字面意思理解,Load commands是告诉加载器如何处理二进制数据

iOS攻防-序章(1)-Mach-O文件结构解析_第4张图片

这里面是不是有很多熟面孔?

比如LC_LOAD_DYLIB(AFNetworking),还有LC_ENCRYPTION_INFO(代码加密)LC_CODE_SIGNATURE(代码签名)等等。

这里特别提一句:看到LC_LOAD_DYLIB(AFNetworking),大家应该能明白,我们读取的Mach-O文件有调用到AFNetworking这个三方库(其实我们开发iOS项目,打包出来的ipa文件就是个压缩包,解压缩之后会有一个和ipa文件名相同的可执行文件EXECUTE,这个就是我们解析的Mach-O)。实际上,项目依赖了多少库,都会在Load commands中有体现。反过来说,如果我们想要让一个打包好的ipa文件加载一个新的库,是否只要更改Load commands内容就行了?

这里还有一部分可以展开的,比如:LC_SEGMENT(_TEXT),文章开头提到的segment、section就是这部分了

segment

iOS攻防-序章(1)-Mach-O文件结构解析_第5张图片

  • Command:Load commands的类型
  • Command Size:代表load command的大小
  • Segment Name:段的名称
  • VM Address :段的虚拟内存地址
  • VM Size : 段的虚拟内存大小
  • File Offset:段在文件中偏移量
  • File Size:段在文件中的大小
  • Number of Sections:标示了Segment中有多少secetion

Section

iOS攻防-序章(1)-Mach-O文件结构解析_第6张图片

section和segment的结构类似

  • Section name:比如_textstubs
  • Segment Name :section所属的segment,比如__TEXT
  • Address :section在内存的起始位置
  • Size:section的大小
  • Offset:section的文件偏移
  • Alignment :字节大小对齐
  • Relocations Offset :重定位入口的文件偏移
  • Number of Relocations: 需要重定位的入口数量
  • Flags:包含sectiontypeattributes

你可能感兴趣的:(IOS,移动端开发,安全性)