Mach O文件 - wanshanhu79/Study GitHub Wiki
APP开发的代码及相关资源被编译、链接、签名后是.app
格式文件,被zip
压缩后是.ipa
(zip压缩后改格式为ipa)格式文件,其中的代码成为了可执行文件,文件格式是Mach-O
。
通过AppStore、PP助手、iFunBox、Xcode等工具安装到手机上
- 界面分析:Cycript(命令行打出视图层级)、Reveal(图形化界面)
- 代码分析:对Mach-O文件的静态分析
- MachOView、class-dump、Hopper Disassembler、ida等
- 动态调试
- 对运行中的APP进行代码调试
- debugserver、LLDB
- 代码编写
- 注入代码到APP中
- 必须时还可能需要重新签名、打包ipa
它的作用就是把Mach-O文件里的class信息给dump出来(把类信息给导出来),生成对应的.h头文件
官方地址 下载完后工具包后将class-dump文件复制到Mac的 /usr/local/bin 目录,这样在终端就能识别 class-dump 指令了
-
常用格式 :
class-dump -H Mach-O文件路径 -o 头文件存放路径
-H :表示要生成头文件
-o 用于指定头文件的存储目录
备注:1.在mac上命令行敲某个指令,系统会去 /usr/bin
(常用的cd指令就在这个目录,从mac 11开始这个目录只能读,不能写)目录和 /usr/local/bin
(可以增加和删除)目录下。
2. 如果命令不在这两个指令下,需要进入到指令所在的文件夹,./指令名
,./
表明从当前文件开夹
源代码 -> 汇编代码 -> 机器语言(Mach-O),通过编译,实现转化。
在同一种架构平台下,每一条汇编指令都有与之对应的唯一的机器指令。机器指令可以反编译成汇编指令
Hopper Disassmbler 能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码
-
常用快捷键 Shift + Option + X :找出哪里引用了这个方法
找到相应的方法,右键菜单选择“References to selector loadview”,和快捷键作用相同
Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混合物。可以用来探索、修改、调试正在运行的Mac/iOS APP。
通过Cydia安装Cycript,即可在iPhone上调试运行的APP。
从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache),公用部分头信息,尽可能的压缩占用的内存空间。缓存路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
。动态库共享缓存一个非常明显的好处是节约内存,就是多个App共用系统框架库如UIkit、Foundation等,避免内存中有多份。
ARM处理器指令集架构(依次最新,功能越强大)
- v6
- v7
- v7s
- arm64
指令集原则性上都是向下兼容的
在Mac/iOS中,是使用了/usr/lib/dylb
程序来加载动态库
dyld:有两种可能的名字
- dynamic link editor 动态链接编辑器
- dynamic loader 动态加载器
可以使用dyld源码中的launch-cache/dsc_extractor.app
。将 #if 0
前面的代码删除(包括#if 0),把最后面的#endif
e也删掉
-
编译 dsc_extractor.app
clang++ -o dsc_extractor dec_extractor.cpp
-
使用dsc_extractor
./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的文件
在存放这个命令的文件路径下执行
Mach-O 是Mach object的缩写,是Mac/iOS上用于存储程序、库的标准格式。
可以在xnu源码(mac内核源码)中,查看到Mach-o格式的详细定义。EXTERNAL_HEADERS/mach-o/fat.h EXTERNAL_HEADERS/mach-o/loader.h
file:查看Mach-O的文件类型 file 文件路径
-
MH_OBJECT :
- 目标文件(.o)
- 静态库文件(.a),静态库其实就是N个.o合并在一起
-
MH_EXECUTE:
- 可执行文件
.app/xx
- 可执行文件
-
MH_DYLIB:
- .dylib
- .framework/xx
-
MH_DYLINKER:
- 动态链接编辑器
/usr/lib/dyld
- 动态链接编辑器
-
MH_DYSM:存储着二进制文件符号信息的文件
* .dSYM/Contents/Resources/DWAFR/xx (常用于分析APP的崩溃信息)
在Xcode的target的Build Settings里看查看Mach-O type
Xcode 的tatget的Architectures中$(ARCHS_STANDARD)
:Xcode内置的环境变量,不同Xcode的值不一样,通用的一些架构。编译出来支持的架构是它和Valid Architectures
的交集。一般用默认的,不要修改。
- 通用二进制文件
- 同时适用于多种架构的二进制文件
- 包含了多种不同架构的独立的二进制文件
- 因为需要存储多种架构的代码,通用二进制文件通常比单一平台的二进制文件要大
- 由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多
- 由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存
- 因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)
lipo 命令:常用于多架构Mach-O文件的处理
- 查看架构信息:
lipo -info 文件路径
- 导出某种特定架构:
lipo 文件路径 -thin 架构类型 -output 输出文件路径
- 合并多种架构:
lipo -create 文件路径1 文件路径2 -output 输出文件路径
官方描述,一个Mach-O文件主要包含3个区域:
- Header :文件类型、目标架构类型等
- Load commands :描述文件在虚拟内存中的逻辑结构、布局
- Raw segment data :在Load commands中定义的Segment的原始数据
内存是分段管理的,例如可执行文件的代码段、数据段、堆栈段。
内存是分页管理的,我们进行的内存操作都是在虚拟内存上进行的,需要与物理内存绑定。
窥探Mach-O文件结构的GUI工具:MachOView
dyld用于加载以下类型的Mach-O文件:
- MH_EXECUTE
- MH_DYLIB
- MH_BUNDLE
APP的可执行文件、动态库都是dylb负责加载的
加壳是利用特殊的算法,对可执行文件的编码进行改变(比如压缩、加密),以达到保护程序代码的目的。
脱壳是摘掉壳程序,将未加密的可执行文件还原出来。主要有两种方式:硬脱壳、动态脱壳。硬脱壳是指不运行程序,知道加密算法反向直接解密可执行文件;动态脱壳是指程序在内存中运行时已经被解密,直接导出到磁盘,不需要关心加密算法。
通过otool工具查看Mach-O文件的Load Commands -> LC_ENCRYPTION_INFO -> Crypt ID
的值,0代表未加密。otool -l 可执行文件路径 | grep crypt