Mach-O文件详解

424 阅读3分钟

常用命令

file

查看文件格式

➜  InHouse.app file InHouse
InHouse: Mach-O 64-bit executable arm64

lipo

查看文件有哪些架构

➜  InHouse.app lipo -info InHouse
Non-fat file: InHouse is architecture: arm64

otool

查看Mach-O头部信息

➜  InHouse.app otool -h InHouse
InHouse:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          0  0x00           2    95      10720 0x00a18085

➜  InHouse.app otool -hv InHouse
InHouse:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64        ALL  0x00     EXECUTE    95      10720   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE MH_HAS_TLV_DESCRIPTORS

查看Load Command区域信息

➜  InHouse.app otool -lv InHouse

查看是否加密

otool -l InHouse | grep cryptid

查看某个节的信息

otool -s __TEXT __text InHouse
otool -s __TEXT __stubs InHouse

查看代码段反汇编的前10行

otool -tv InHouse | head -n 10

Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式。

MachOView下载地址:sourceforge.net/projects/ma…

MachOView源码地址:github.com/gdbinit/Mac…

常见的Mach-O格式

image.png

属于Mach-O格式的文件类型有。

#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 */
/*  linking only, no section contents */
#define MH_DSYM 0xa /* companion file with only debug */
/*  sections */
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
#define MH_FILESET 0xc /* set of mach-o's */
  • MH_OBJECT: 目标文件 .o文件
  • MH_EXECUTE: 普通的可执行文件
  • MH_DYLIB: .a、.dylib、.framework
  • MH_DYLINKER: 动态库链接编译器 比如iPhone目录/usr/lib/dyld属于MH_DYLINKER类型的Mach-O格式文件。
  • MH_DSYM: 存储着二进制文件符号信息的文件。项目编译生成的不仅有程序还有一个与之对应的.dsym文件。

image.png

image.png

针对该MachO文件我们做几个操作,利用lipo命令拆分合并架构

利用lipo-info查看MachO文件架构

lipo -info libLeaksAtExit.dylib

Architectures in the fat file: libLeaksAtExit.dylib are: x86_64 arm64e

瘦身MachO文件,拆分

lipo libLeaksAtExit.dylib -thin arm64e -output lib_arm64e

lipo -info lib_arm64e

Non-fat file: lib_arm64e is architecture: arm64e

增加架构,合并

lipo -create lib_arm64e  lib_x86_64 -output lib

lipo -info lib

Architectures in the fat file: lib are: x86_64 arm64e

Mach-O文件格式

从loader.h中查看具体的定义:

image.png

Header

magic: 0xCAFEBABE表示FAT,0xFEEDFACF表示ARM64(多数文件起始固定的数据,标识文件格式)

image.png

image.png

LoadCommands

说明操作系统如何加载文件中的数据,对系统内核加载器和动态连接器起知道作用

image.png

image.png

段名作用
__PAGEZERO空指针陷阱段,映射到虚拟内存空间的第一页,用于捕获对NULL指针的引用
__TEXT包含了执行代码和其他只读数据,可读可执行,不可修改
__DATA程序数据,可读可写,不可执行
__LINKEDIT链接器使用的符号以及其他表,只读

SEGMENT:

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

SECTION:

struct section { /* for 32-bit architectures */
    char sectname[16]; /* name of this section */
    char segname[16]; /* segment this section goes in */
    uint32_t addr; /* memory address of this section */
    uint32_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) */
};


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

Data

image.png

image.png