iOS 开发中的 Mach O 文件
一、APP 从开发到安装到手机的过程
APP 开发的代码及相关资源被编译、链接、签名后是 .app
格式文件,被 zip
压缩后是 .ipa
(zip 压缩后改格式为 ipa)格式文件,其中的代码成为了可执行文件,文件格式是 Mach-O
。
通过 AppStore、PP 助手、iFunBox、Xcode 等工具安装到手机上
二、逆向APP
- 界面分析:Cycript(命令行打出视图层级)、Reveal(图形化界面)
- 代码分析:对Mach-O文件的静态分析
- MachOView、class-dump、Hopper Disassembler、ida等
- 动态调试
- 对运行中的APP进行代码调试
- debugserver、LLDB
- 代码编写
- 注入代码到APP中
- 必须时还可能需要重新签名、打包ipa
1.Mach-O 分析工具 class-dump
它的作用就是把 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. 如果命令不在这两个指令下,需要进入到指令所在的文件夹,./指令名
,./
表明从当前文件开夹
2.代码的编译过程
源代码 -> 汇编代码 -> 机器语言(Mach-O),通过编译,实现转化。
在同一种架构平台下,每一条汇编指令都有与之对应的唯一的机器指令。机器指令可以反编译成汇编指令
3.反编译汇编代码 - Hopper Disassmbler
Hopper Disassmbler 能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码
- 常用快捷键 Shift + Option + X :找出哪里引用了这个方法找到相应的方法,右键菜单选择“References to selector loadview”,和快捷键作用相同
4.Cycript
Cycript 是Objective-C++、ES6(JavaScript)、Java 等语法的混合物。可以用来探索、修改、调试正在运行的Mac/iOS APP。
通过 Cydia 安装 Cycript,即可在 iPhone 上调试运行的 APP。
三、动态库共享缓存(dyld shared cache)
从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache),公用部分头信息,尽可能的压缩占用的内存空间。缓存路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
。动态库共享缓存一个非常明显的好处是节约内存,就是多个App共用系统框架库如UIkit、Foundation等,避免内存中有多份。
ARM处理器指令集架构(依次最新,功能越强大)
- v6
- v7
- v7s
- arm64
指令集原则性上都是向下兼容的
1.动态库的加载
在Mac/iOS中,是使用了/usr/lib/dylb
程序来加载动态库
dyld:有两种可能的名字
- dynamic link editor 动态链接编辑器
- dynamic loader 动态加载器
2.从动态库共享缓存抽取动态库
可以使用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-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 文件路径
1.常见的Mach-o文件类型
- 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的崩溃信息)
2.在 Xcode 中
在Xcode的target的Build Settings里看查看Mach-O type
Xcode 的tatget的Architectures中$(ARCHS_STANDARD)
:Xcode内置的环境变量,不同Xcode的值不一样,通用的一些架构。编译出来支持的架构是它和Valid Architectures
的交集。一般用默认的,不要修改。
3.Universal Binary (通用二进制文件)
- 通用二进制文件
- 同时适用于多种架构的二进制文件
- 包含了多种不同架构的独立的二进制文件
- 因为需要存储多种架构的代码,通用二进制文件通常比单一平台的二进制文件要大
- 由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多
- 由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存
- 因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)
lipo 命令:常用于多架构Mach-O文件的处理
- 查看架构信息:
lipo -info 文件路径
- 导出某种特定架构:
lipo 文件路径 -thin 架构类型 -output 输出文件路径
- 合并多种架构:
lipo -create 文件路径1 文件路径2 -output 输出文件路径
4.Mach-O 的基本结构
官方描述,一个Mach-O文件主要包含3个区域:
- Header :文件类型、目标架构类型等
- Load commands :描述文件在虚拟内存中的逻辑结构、布局
- Raw segment data :在Load commands中定义的Segment的原始数据
内存是分段管理的,例如可执行文件的代码段、数据段、堆栈段。
内存是分页管理的,我们进行的内存操作都是在虚拟内存上进行的,需要与物理内存绑定。
窥探Mach-O文件结构的GUI工具:MachOView
dyld 和 Mach-O
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论