想要了解Mach-O文件,首先要了解从编写代码,开发App到App打包并安装到手机上的整个过程
首先代码经过编译、链接、签名获得一个“xxx.app”包,app包里面就装着nib文件、资源文件以及可执行文件(Mach-O文件),我们编写的代码其实就放在这个Mach-O文件里面
然后经过zip压缩,将app包转成ipa包,而ipa包就可通过以下几个途径可以装到手机里
主要是以下四个步骤:
1、界面分析,通过Cycript、Reveal等工具窥探UI界面
2、 代码分析,用MachOView、class-dump、Hopper Disassembler、ida等对Mach-O文件静态分析
3、 动态调试、用debugserver、LLDB对运行中的App进行代码调试
4、代码编写,注入代码到App中,必要时还需要重新签名、打包ipa
接下来介绍几个Mach-O的静态分析工具
class-dump的作用就是把Mach-O文件的class信息给导出来(把类信息导出来),生成对应的.h头文件,下载完成需要将其中的class-dump可执行文件复制到Mac上的/usr/local/bin目录中,终端就能识别class-dump命令
在Mac中,终端执行的所有指令都会去/usr/bin目录和/usr/local/bin目录下寻找,但是在Mac OS 10.11之后,usr/bin/目录下是不可写的,因此只能放到/usr/local/bin目录下
class-dump的常用命令如下:
class-dump -H Mach-O文件路径 -o 头文件存放目录
Hopper Disassmbler可以将Mach-O文件的机器语言反编译成汇编代码、OC伪代码或者是Swift伪代码
如果想分析一下类似UIKit等系统框架的Mach-O文件,那么如何找到该文件呢?
其实从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache),缓存路径为/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX(X代表ARM处理器指令集的架构),其用处多个App共享一份内存,可以节省内存
ARM指令集有以下几种:
ARM指令集 | 支持的设备 |
---|---|
armv6 | iPhone、iPhone3G iPod Touch、iPod Touch2 |
armv6 | iPhone3GS、iPhone4、iPhone4S iPad、iPad2、iPad3(The New iPad)、iPad mini iPod、Touch3G、iPod Touch4、iPod Touch5 |
armv6 | iPhone5、iPhone5C、iPad4 |
armv6 | iPhone5S、iPhone6、iPhone6 Plus、iPhone6S、iPhone6S Plus iPhoneSE、iPhone7、iPhone7Plus、iPhone8、iPhone8 Plus、iPhoneX iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2 iPad mini with Retina display、iPad mini3、iPad mini4 iPod Touch6 |
然而由于动态库共享缓存太大,想要分析单个动态库,就需要从动态库共享缓存中抽取对应的动态库。在Mac/iOS中,是使用了/usr/lib/dyld程序来加载动态库,dyld程序名称为dynamic link editor(动态链接编辑器)或dynamic loader(动态加载器),其源码地址在这里
提取步骤为:
clang++ -o dsc_extractor dsc_extractor.cpp
./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的目录
此时动态库就被抽取出来,然后使用Hopper Disassmbler打开动态库,就可以看到动态库中的源码信息了
接下来从几个方面介绍Mach-O文件,Mach-O是Mach object的缩写,是Mac\iOS上用来存储程序、库的标准格式
在xnu源码(点击下载源码)中,可以查看到Mach-O格式的详细定义,具体代码在EXTERNAL_HEADERS/mach-o/loader.h 文件中
常见的Mach-O文件文件类有:
想要查看某个具体的Mach-O文件类型,在终端中输入指令:
# 需要在文件所属目录下
file 文件名
dyld是iOS中用来加载可执行文件、动态库的工具,其实它本身也是一个Mach-O文件,其类型为MH_DYLINKER,可以用来加载以下三种类型的Mach-O文件
通用二进制文件适用于多种架构,包含了多种不同架构的独立的二进制文件,有如下特点:
可以用如下指令来处理多架构Mach-O文件:
#查看架构信息
lipo -info 文件路径
#导出某种类型的架构
lipo 文件路径 -thin 架构类型 -output 输出文件路径
#合并多种架构类型
lipo 文件路径1 文件路径2 -output 输出文件路径
一个Mach-O文件包含三个主要区域:
想要查看Mach-O文件的结构,可以使用otool命令和MachOView工具
#查看Mach-O文件的header信息
otool -h 文件路径
#查看Mach-O文件的load commands信息
otool -l 文件路径
#更多用法直接输入
otool