iOS逆向学习笔记8(MachO文件)

1 什么是MachO文件

  Mach-O其实就是Mach Object文件格式的缩写,是Mac以及iOS上可执行文件的格式,类似于Windows上的PE格式(Portable Exectable)、linux上的elf格式(executable and Linking Format)。
  MachO是一种可执行文件、目标代码以及动态库等类型文件的格式。作为a.out格式的替代,Mach-O提供了更强的扩展性。
  属于MachO格式的常见文件:

  • 目标文件.o
  • 库文件[.a(静态库) .dylib(动态库) framework]
  • 可执行文件
  • dyld
  • .dsym
    可以通过File指令来查看文件的类型
    file指令使用格式:file 文件路径

2 查看各种MachO文件的信息

2.1查看一个.c文件生成的可执行文件的信息

  打开XCode使用快捷键command+N创建一个名为test的c文件,文件内容如下所示:

#include 

int main() {
    printf("test\n");
    
    return 0;
}

打开终端将这个.c文件使用clang命令编译为.o文件


iOS逆向学习笔记8(MachO文件)_第1张图片

再通过file指令查看编译之后生成的.o文件的信息


iOS逆向学习笔记8(MachO文件)_第2张图片

可以看到这个test.o文件是一个MachO格式,架构是x86_64的64位的object文件,架构是x86_64表示只有英特尔芯片的Mac电脑能读取这个文件。
再使用clang命令将这个.o文件链接成为可执行文件

使用file命令查看a.out文件的信息


image.png

可以看到这个a.out文件是一个MachO格式,架构是x86_64的64位的可执行文件,架构是x86_64表示只有英特尔芯片的Mac电脑能读取这个文件。
也可以直接将.c文件通过使用clang命令直接编译链接成为可执行文件,如下图所示:
iOS逆向学习笔记8(MachO文件)_第3张图片

还可以直接将.o文件通过使用clang命令直接链接成为可执行文件,如下图所示:
iOS逆向学习笔记8(MachO文件)_第4张图片

现在所生成的a.out、test以及test2文件是不是一样的呢?我们通过md5命令来查看这三个文件的hash值是否一致。


iOS逆向学习笔记8(MachO文件)_第5张图片

通过hash值对比我们可以得知这三个文件是一样的。因为这三个文件的源码文件test.c是一样的,clang编译时的编译方式是一样的,所有生成的可执行文件是一样的。

2.2 查看两个.c文件生成的可执行文件的信息

创建一个test.c文件,文件内容为:

#include 

void test2();

int main() {
    printf("test\n");
    
    return 0;
}

创建一个test2.c文件,文件内容为:

#include 

void test2() {
    printf("test2\n");
}

使用clang命令将两个.c文件(test.c在前)进行编译以及链接生成一个test可执行文件,文件信息如下:



使用clang命令将两个.c文件(test2.c在前)进行编译以及链接生成一个test可执行文件,文件信息如下:



再来看看生成的两个执行文件是否一样。
iOS逆向学习笔记8(MachO文件)_第6张图片

我们可以看到这两个可执行文件的hash值是不一样的,但使用的确是两个相同的.c文件编译链接而成的,这是为什么呢?
因为可执行文件实际上是多个.o文件的集合,链接时候的这些.o文件的顺序不一样,所生成的可执行文件的内容就不一样。
我们可以使用objdump命令来查看以下这两个执行文件的内容:


iOS逆向学习笔记8(MachO文件)_第7张图片
可执行文件test文件内容

iOS逆向学习笔记8(MachO文件)_第8张图片
可执行文件test2文件内容

就如同你在项目中改变.m文件的编译顺序,所生成的可执行文件的内容也是不一样的,如下图所示:
iOS逆向学习笔记8(MachO文件)_第9张图片

2.3 查看.a文件的信息

使用find命令在/usr目录下查找.a文件
find命令使用格式:find 文件路径 -name 文件名


iOS逆向学习笔记8(MachO文件)_第10张图片

查看.a文件的信息


2.4 查看.dylib文件的信息

iOS逆向学习笔记8(MachO文件)_第11张图片

iOS逆向学习笔记8(MachO文件)_第12张图片
image.png

2.5 查看dyld文件的信息

iOS逆向学习笔记8(MachO文件)_第13张图片

由上图我们得知dyld实际上是一个动态链接器(dynamic linker),它不是一个可执行文件,是一个通用二进制文件,当启动系统的时候,系统内核会触发这个文件。

2.6 查看dSYM文件的信息

将项目工程的iOS版本改到13.1以下,并且当前环境设置为release模式,编译之后


iOS逆向学习笔记8(MachO文件)_第14张图片

iOS逆向学习笔记8(MachO文件)_第15张图片



可以看到这个是一个Macho-O类型的arm64架构下64位的dSYM手册文件。

3 通用二进制(Universal binary)

  • 苹果公司提出的一种程序代码,能同时适用多种架构的二进制文件。
  • 同一个程序包中同时为多种架构提供最理想的性能。
  • 因为需要存储多种代码,通用二进制应用程序通常比单一平台二进制的程序要大
  • 由于执行中只调用一部分代码,运行起来也不需要额外的内存。
    iOS11以上的系统只支持64位以上的架构

3.1iOS11版本以上可执行文件的架构

iOS11版本以上可执行文件的架构

3.2 iOS11版本以下可执行文件的架构

iOS逆向学习笔记8(MachO文件)_第16张图片
iOS11版本以下可执行文件的架构

3.2 添加armv7s架构并查看iOS11版本以下可执行文件的架构

XCode中设置可执行文件的架构模式


iOS逆向学习笔记8(MachO文件)_第17张图片
XCode中设置可执行文件的架构

armv7s是生成iPhone5、iPhone 5c都能用的架构


iOS逆向学习笔记8(MachO文件)_第18张图片
添加架构

编译之后查看可执行文件支持的架构
iOS逆向学习笔记8(MachO文件)_第19张图片

4 使用lipo命令对MachO文件包含的架构进行合并以及拆分

4.1 使用lipo命令查看MachO文件的架构信息

命令格式:lipo -info MachO文件路径


4.2 使用lipo命令拆分MachO文件的某种架构

命令格式:lipo MachO文件 -thin 架构 -output 输出文件路径


剥离armv7架构

剥离arm64架构

4.3 使用lipo命令合并MachO文件的多种架构

命令格式:lipo -create MachO1 MachO2 -output 输出文件路径


iOS逆向学习笔记8(MachO文件)_第20张图片
合并arm64以及armv7两种架构

5 MachO文件结构

5.1 MachO文件基本结构

iOS逆向学习笔记8(MachO文件)_第21张图片
MachO文件结构

如上图所示:Mach-O的组成结构包括了

  • Header包含了该二进制文件的一般信息(字节顺序、结构类型、加载指令的数量等,使得可以快速确认一些信息,比如当前文件用于32位还是64位,对应的处理器是什么,文件类型是什么)
  • Load commands是一张包含了很多内容的表(内容包括区域的位置、符号表、动态符号表等)
  • Data是对象文件中最大的部分(包含Segement的具体数据)

5.1 使用otool命令查看MachO文件结构

5.1.1 使用otool命令查看MachO文件的header信息

命令格式:otool -f MachO文件路径


iOS逆向学习笔记8(MachO文件)_第22张图片

使用MachOView查看MachO文件信息


iOS逆向学习笔记8(MachO文件)_第23张图片

对比上下两张图我们可以发现:
cpuType 是12代码arm架构

cpuType 是16777228代表arm64架构
cpusubType为9对应的是arm_v7架构
cpusubType为11对应的是arm_v7s架构
cpusubType为0对应的是arm64架构
Offset代表的是这个类型架构的machO文件在整个MachO中首地址的偏移量,Size代表的是这个类型架构的machO文件大小
各个架构的MachO文件之间的空隙是因为分页原因造成的,mac中是2的12次方(4k)也就是4096,iOS中分页大小是2的14次方(16k)。


mac中分页大小

5.1.2 使用MachOView查看具体架构类型的MachO文件的header信息

iOS逆向学习笔记8(MachO文件)_第24张图片
/*
 * 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 */
};

fileType类型

#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     /* a file composed of other Mach-Os to
                       be run in the same userspace sharing
                       a single linkedit. */

iOS逆向学习笔记8(MachO文件)_第25张图片
image.png

iOS逆向学习笔记8(MachO文件)_第26张图片

iOS逆向学习笔记8(MachO文件)_第27张图片

iOS逆向学习笔记8(MachO文件)_第28张图片

iOS逆向学习笔记8(MachO文件)_第29张图片

iOS逆向学习笔记8(MachO文件)_第30张图片
MachO的四大组成

iOS逆向学习笔记8(MachO文件)_第31张图片
image.png

注意:第二行是外部符号绑定
iOS逆向学习笔记8(MachO文件)_第32张图片

iOS逆向学习笔记8(MachO文件)_第33张图片

你可能感兴趣的:(iOS逆向学习笔记8(MachO文件))