iOS逆向系列-Mach-O文件
概述
Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式。
常见的Mach-O文件
属于Mach-O格式的文件类型有。

可以在xnu源码中,查看到Mach-O格式的详细定义(https://opensource.apple.com/tarballs/xnu/)
- MH_OBJECT
代码编译中间的产物目标文件(.o)属于MH_OBJECT类型Mach-O格式文件。我们平时制作的静态库本质就是N个.O文件的集合,所以静态库也是属于MH_OBJECT类型Mach-O格式文件。 - MH_EXECUTE
顾名思义是可执行文件,通过项目编译的二进制文件就是属于MH_EXECUTE类型的Mach-O格式文件。 - MH_EXECUTE
苹果的动态库比如.Framework、.dylib文件是属于MH_EXECUTE类型的Mach-O格式文件。 - MH_DYLINKER
动态库链接编译器 比如iPhone目录/usr/lib/dyld属于MH_DYLINKER类型的Mach-O格式文件。 - MH_DSYM
存储着二进制文件符号信息的文件。项目编译生成的不仅有程序还有一个与之对应的.dsYM文件。
Mach-O的基本结构

[官方描述(https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html)
一个Mach-O文件包含3个主要区域
- Header
文件类型、目标架构类型等 - Load commands
描述文件在虚拟内存中的逻辑结构、布局 - Raw segment data
在Load commands中定义的Segment的原始数据
窥探Mach-O的基本结构
命令行file指令查看
- file 文件路径
otool查看Mach-O特定部分和段的内容
通过otool -l 可执行文件路径快速查看Mach-O基础结构信息,比如通过cryptid的值可以判断是否加壳。命令行lipo指令
- 查看架构信息:lipo -info 文件路径
- 导出某种特定架构:lipo 文件路径 -thin 架构类型 -output 输出文件路径
- 合并多种架构:lipo 文件路径1 文件路径2 -output 输出文件路径
Universal Binary
翻译为通用的二进制文件,同时支持多种架构的二进制文件。因为需要储存多种架构的代码,通用二进制文件通常比单一平台二进制的程序要大。
由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多,由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存。因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)。
通过xcode编译的静态库需要支持多架构的配置:

不同的CPU架构不同 指令集不同 二进制指令跟汇编指令一一对应,处理器比较高级,指令集就多,支持的功能就不比较多。
v6架构支持的机型
iPhone、iPhone3G、iPod Touch、iPod Touch2
v7架构支持的机型
iPhone3GS、iPhone4、iPhone4S、
iPad、iPad2、iPad3
iPad mini
iPod Touch3G、iPod Touch4、iPod Touch5
v7s
iPhone5、iPhone5C
iPad2
arm64
iPhone5s、iPhone6、iPhone6 Plus、iPhone6s、iPhone6s Plus
iPhoneSE、iPhone7、iPhone7 Plus、iPhone8 Plus、iPhone8 Plus、iPhoneX
iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2
iPad mini with Retina display、iPad mini3、iPad mini4
iPod Touch6
动态库共享缓存(dyld shared cache)
在我们手机的/usr/lib目录下有个Mac-O文件dyld。

dyld是可以加载苹果的动态库。从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache)。

缓存文件路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX

dyld源码 https://opensource.apple.com/tarballs/dyld/。在最新的源码版本当中我们可以使用源码中的launch-cache/dsc_extractor.cpp抽取缓存文件中的动态库。
从缓存动态共享库中抽取动态库
- 将dyld的源码中的
dsc_extractor.cpp的#if 0一上代码删除,包含#if 0与#endif,代码如下
#include <stdio.h>
#include <stddef.h>
#include <dlfcn.h>
typedef int (*extractor_proc)(const char* shared_cache_file_path, const char* extraction_root_path,
void (^progress)(unsigned current, unsigned total));
int main(int argc, const char* argv[])
{
if ( argc != 3 ) {
fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
return 1;
}
//void* handle = dlopen("/Volumes/my/src/dyld/build/Debug/dsc_extractor.bundle", RTLD_LAZY);
void* handle = dlopen("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle", RTLD_LAZY);
if ( handle == NULL ) {
fprintf(stderr, "dsc_extractor.bundle could not be loaded\n");
return 1;
}
extractor_proc proc = (extractor_proc)dlsym(handle, "dyld_shared_cache_extract_dylibs_progress");
if ( proc == NULL ) {
fprintf(stderr, "dsc_extractor.bundle did not have dyld_shared_cache_extract_dylibs_progress symbol\n");
return 1;
}
int result = (*proc)(argv[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
return 0;
}
- 命令行clang编译连接可执行文件
- clang++ -o 执行文件名称 cpp源文件
- 通过生成的可执行文件抽取

抽离的苹果的动态库就在我们执行的framework目录下

我们就可以获取苹果所有动态库代码的Mach-O文件,就可以通过上面的Hopper等工具做源码分析了。
dyld与Mach-O
dyld文件是属于在unix内核规范中的Mach-O格式的文件。dyld可以用来加载一下类型的Mach-O文件
- MH_EXECUTE
- MH_DYLIB
- MH_BUNDLE
总结:App的可执行文件、动态库都是由dyld负责加载的。
iOS逆向系列-Mach-O文件的更多相关文章
- iOS逆向系列-脱壳
概述 通过iOS逆向系列-逆向App中使用class-dump工具导出App的Mach-O文件所有头文件.Hopper工具分析App的Mach-O文件代码大概实现.但是这些前体是App的Mach-O没 ...
- iOS逆向系列-逆向APP思路
界面分析 通过Cycript.Reveal. 对于Reveal安装配置可参考配置iOS逆向系列-Reveal 通过Reveal找到内存中的UI对象 静态分析 开发者编写的所有代码最终编译链接到Mach ...
- iOS逆向系列-tweak补充
tweak加载资源 开发自己的deb插件需要加载自己的资源,比如图片资源.iOS中常用的两种加载图片资源的方式: + (nullable UIImage *)imageNamed:(NSString ...
- iOS逆向系列-Reveal
概述 Reveal是一款调试iOS程序UI界面的神器. 官网地址:https://revealall.com 下载:https://revealapp.com/download/ 建议下载Reveal ...
- iOS逆向系列-Cycript
概述 Cycript 是Objective-C++.ES(JavaScript).Java等语法的混合物. 可以用来探索.修改.调试正在运行的Mac\iOS App. 通过Cydia安装Cycript ...
- iOS逆向系列-动态调试
Xcode调试App原理 Mac安装了Xcode Xcode的安装包中包含了debugserver 可执行类型的Mach-O文件,iPhone第一次连接Xcode调试会将Xcode中的debugser ...
- iOS逆向系列-theos
概述 theos是GitHub开源的一个项目,通过nic.pl创建tweak项目.通过编写我们注入代码,然后执行编译.打包.安装等操作将代码注入iPhone安装的制定程序. theos环境配置 安装签 ...
- iOS 逆向之ARM汇编
最近对iOS逆向工程很感兴趣. 目前iOS逆向的书籍有: <Hacking and Securing IOS Applications>, <iOS Hacker's Handboo ...
- iOS逆向+越狱
感觉本文涉及内容有点多的,但是自己不愿意写太多,就简单的谢谢关于ios上手的东西吧 初级入手不免要用到,pp助手,i4 tools等 iOS逆向-ipa包重签名及非越狱手机安装多个应用 1.常识 我们 ...
随机推荐
- FastText总结,fastText 源码分析
文本分类单层网络就够了.非线性的问题用多层的. fasttext有一个有监督的模式,但是模型等同于cbow,只是target变成了label而不是word. fastText有两个可说的地方:1 在w ...
- centos6 & centos7搭建ntp服务器
原理 NTP(Network TimeProtocol,网络时间协议)是用来使计算机时间同步的一种协议.它可以使计算机对其服务器或时钟源做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1 ...
- C盘清理垃圾
经常清理C盘垃圾,会让系统运行更快,避免死机,今天教大家一种简单实用的方法,用文本文档清理垃圾: 1:在电脑桌面空白处右键-建立文本文档: 2:把以下代码复制到文本里 @echo offecho 正在 ...
- 【LGP5127】子异和
题目 子异和这个名字,真是思博 显然一个集合的子集异或和为,\(2^{|S|-1}\times A\),\(A\)为集合的或和 于是现在的问题变成了树链异或一个数,求树链或和 显然强行拆位是可以做的, ...
- docker使用gitlab持续集成(1)
修改ssh连接端口vi /etc/ssh/sshd_config 写docker-compose.yml文件配置gitlab version: '3' services: gitlab: image: ...
- DIV+CSS网页布局常用的一些基础知识
CSS命名规范 一.文件命名规范 全局样式:global.css:框架布局:layout.css:字体样式:font.css:链接样式:link.css:打印样式:print.css: 二.常用类/I ...
- 02->交互式图形学--用glut库实现Sierpinski镂垫
Sierpinski图形是一类有趣的图形,本文结合交互式图形学教材,讲解Sierpinski镂垫图形生成,作为入门图形学编程的第一课.为了简便,本文就2D来进行讨论.实验环境见01 算法 主要是根据随 ...
- python_django_models模块中的查询
查询集:表示从数据库获取的对象集合,查询集可以有多个过滤器,过滤器就是一个函数(方法),基于所给参数限制查询集结果 从sql角度来说,查询集和select等价,过滤器和where等价 查询集特点: 惰 ...
- C++ 系列:iostream 的用途与局限
转载自http://www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html 本文主要考虑 x86 Linux 平台,不考虑跨平台的可移植性,也 ...
- (上线时清缓存)laravel 5.1 的程序性能优化(配置文件) - 简书
代码上到正式环境后执行这六步 php artisan config:clear php artisan config:cache php artisan route:clear php artisan ...