Mach-O是Mach object的缩写,是Mac\iOS上用来存储程序、库的标准格式html
xun是苹果MacOS\iOS等操做系统的内核git
Mach-O类型 | 示例文件 |
---|---|
MH_OBJECT | 目标文件(.o) 静态库文件(.a)注: |
MH_EXECUTE | 可执行文件,存放App的全部源码信息,在.app/xx |
MH_DYLIB | 动态库文件.dylib 或者 .framework/xx |
MH_DYLINKER | 动态连接编辑器,也就是以前所说的/usr/lib/dyld工具 |
MH_DSYM | 此文件中存储这二进制文件符号信息,在开发中,咱们常用此文件来分析App的崩溃信息 |
能够点击官网查看Mach-O的介绍。github
Mach-O由3个部分组成缓存
Raw segment data存放了全部的原始数据,而Load commands至关于Raw segment data的索引目录sass
file 文件路径
复制代码
#查看Mach-O文件的header信息
otool -h 文件路径
#查看Mach-O文件的load commands信息
otool -l 文件路径
复制代码
更多使用方法,终端输入otool -help查看bash
#查看架构信息
lipo -info 文件路径
#导出某种类型的架构
lipo 文件路径 -thin 架构类型 -output 输出文件路径
#合并多种架构类型
lipo 文件路径1 文件路径2 -output 输出文件路径
复制代码
通用二进制文件就是同时适用于多种架构的二进制文件,它包含了多种不一样架构的独立的二进制文件,它有如下特色网络
dyld是iOS中用来加载可执行文件、动态库的工具,其实它自己也是一个Mach-O文件。架构
dyld能够用来加载如下三种类型的Mach-O文件app
经过查看dyld的源码能够看到加载文件时的类型校验框架
想要了解Mach-O文件,首先要了解从编写代码,开发App到App打包并安装到手机上的整个过程。
初步了解了什么是Mach-O文件,以及App从开发到安装的过程,咱们就能够来学习如何逆向一款App
静态分析的工具备MachOView、class-dump、Hopper Disassembler、ida等等,后面会一一学习
动态调试的工具备debugserver、LLDB等等
class-dump的做用就是把Mach-O文件的class信息给导出来,生成对应的.h头文件
在Mac中,终端执行的全部指令都会去/usr/bin目录和/usr/local/bin目录下寻找
# -H表示须要生成头文件 -o用于指定头文件的存放目录
class-dump -H Mach-O文件路径 -o 头文件存放目录
复制代码
Hopper Disassmbler能够将Mach-O文件的机器语言反编译成汇编代码、OC伪代码或者是Swift伪代码。最常使用的快捷键有
#找出哪里引用了这个方法
Shift + Option + X
复制代码
下载地址:pan.baidu.com/s/1yP_VcBlQ…
在iOS开发中,有不少功能都是现成可用的,不关你的App在用,其它的App也在用,好比UIKit框架、GUI框架、I/O、网络等等。这些库都是经过连接器连接到Mach-O文件中的。
静态库是编译时连接的库,须要链接进入Mach-O文件中,若是须要更新就必须从新编译一次,没法作到动态加载和更新
Mach-O是文件编译以后的产物,因此动态库并无参与Mach-O文件的编译和连接。因此Mach-O文件中没有包含动态库的符号定义,也就是说这些符号会直接显示未定义,可是他们的名字和对应库的路径会被记录下来。在运行时经过dlopen和dlsym导入动态库时,会根据记录的路径找到对应的库,再经过记录的名字符号找到绑定的地址。
从iOS3.1开始,为了提升性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache),缓存路径是/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
dyld_shared_cache_armX里面的X表明ARM处理器指令集的架构
ARM指令集(CPU指令的集合)有如下几种
ARM指令集 | 支持的设备 |
---|---|
armv6 | iPhone、iPhone3G iPod Touch、iPod Touch2 |
armv7 | iPhone3GS、iPhone四、iPhone4S iPad、iPad二、iPad3(The New iPad)、iPad mini iPod、Touch3G、iPod Touch四、iPod Touch5 |
armv7s | iPhone五、iPhone5C、iPad4 |
arm64 | iPhone5S、iPhone六、iPhone6 Plus、iPhone6S、iPhone6S Plus iPhoneSE、iPhone七、iPhone7Plus、iPhone八、iPhone8 Plus、iPhoneX iPad五、iPad Air、iPad Air二、iPad Pro、iPad Pro2 iPad mini with Retina display、iPad mini三、iPad mini4 iPod Touch6 |
以上全部的指令集都是向下兼容的 为何要使用动态库共享缓存呢?最大的好处就是节省内存。
因为动态库共享缓存太大,若是想获取其中某个动态库,例如UIKit,就须要从动态库共享缓存中抽取对应的动态库
使用dyld源码中提供的方式来进行抽取,工具在源码中的launch-cache/dsc_extractor.cpp文件中
clang++ -o dsc_extractor dsc_extractor.cpp
复制代码
此处是将dsc_extractor.cpp编译生成可执行文件dsc_extractor
./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的目录
复制代码
建议抽取armv7s架构的动态库,arm64抽取时会报以上错误,缘由是dsc_extractor.bundle不能在Xcode10以后使用