Mach-O详解

是一种文件格式

  • 就像png/jpg是存储图片的格式,avi/mov/mpeg4是存储视频的文件格式,txt存储字符 一样,就是一种按照固定格式存储数据的文件格式。
  • 主要用于存储 可执行文件Exec,动态库/静态库等

格式解析

  1. Header : 存储该Mach-O文件的基本信息,大小和Load Comand的个数等
//usr/include/mach-o/Loader.h
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 */
};

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 */
};
  1. Load Command : 加载命令指定了这个文件在虚拟内存中的逻辑结构和文件布局,紧随着Header,是连续存储的
- Segment command
LC_SEGMENT(__PAZEZERO) : 空指针陷阱,主要用作区分32位和64位指令数据
struct segment_command { /* for 32-bit architectures */
    uint32_t    cmd;        /* LC_SEGMENT */
    uint32_t    cmdsize;    /* includes sizeof section structs */
    char        segname[16];    /* segment name */
    uint32_t    vmaddr;     /* memory address of this segment */
    uint32_t    vmsize;     /* memory size of this segment */
    uint32_t    fileoff;    /* file offset of this segment */
    uint32_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 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 */
};

LC_DYLD_INFO_ONLY //动态链接时的信息
- ASLR(Slider)随机偏移值
- Rebase + ASLR = 函数地址  //rebase是根据ASLR偏移计算函数地址

LC_SYMTAB //符号表,字符串
LC_DYSYMTAB //动态符号表
LD_LOAD_DYLINKER //dyld地址
LC_UUID //uuid
LC_VERSION_MIN_IPHONEOS //最低支持版本
LC_SOURCE_VERSION //当前程序版本
LC_MAIN //main函数地址,快速定位到main函数很重要,有的app防护了会闪退
LC_ENCRYPTION_INFO_64 //加密信息
LC_LOAD_DYLIB //动态库,主要看这里改这里
LC_RPATH //地址
LC_FUNCTION_STARTS//方法开始地方
LC_DATA_IN_CODE
LD_CODE_SIGNATURE //代码签名

  1. Data:包含数据段具体数据
__TEXT //代码段
__stubs //符号绑定
__stub_helper //符号绑定

__DATA //数据段
__got //外部符号绑定,非懒加载
__la_symbol_ptr //外部符号,懒加载


__LINKEDIT

- VM Address //虚拟内存地址,看这个偏移值
- VM Size //虚拟内存大小
- File offset : 数据在文件中的偏移量
- File size :数据大小

胖二进制(Fat Binary)多种cpu架构的Mach-O 打包在一起

//合并二进制文件
lipo -create    -o 
//拆分二进制文件
lipo  -thin i386 -output 
//查看信息
lipo -info

工具推荐

  • MachOView(烂苹果)
  • Hopper Disassable

相关命令

//查看文件格式
file filename
//查看二进制文件
objdump 
objdump --macho --exports-trie 

//生成中间文件.0
clang -c 
clang -o  
// 查看二进制信息
otool -f 
//内存页大小
pagesize

你可能感兴趣的:(Mach-O详解)