概述

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文件的更多相关文章

  1. iOS逆向系列-脱壳

    概述 通过iOS逆向系列-逆向App中使用class-dump工具导出App的Mach-O文件所有头文件.Hopper工具分析App的Mach-O文件代码大概实现.但是这些前体是App的Mach-O没 ...

  2. iOS逆向系列-逆向APP思路

    界面分析 通过Cycript.Reveal. 对于Reveal安装配置可参考配置iOS逆向系列-Reveal 通过Reveal找到内存中的UI对象 静态分析 开发者编写的所有代码最终编译链接到Mach ...

  3. iOS逆向系列-tweak补充

    tweak加载资源 开发自己的deb插件需要加载自己的资源,比如图片资源.iOS中常用的两种加载图片资源的方式: + (nullable UIImage *)imageNamed:(NSString ...

  4. iOS逆向系列-Reveal

    概述 Reveal是一款调试iOS程序UI界面的神器. 官网地址:https://revealall.com 下载:https://revealapp.com/download/ 建议下载Reveal ...

  5. iOS逆向系列-Cycript

    概述 Cycript 是Objective-C++.ES(JavaScript).Java等语法的混合物. 可以用来探索.修改.调试正在运行的Mac\iOS App. 通过Cydia安装Cycript ...

  6. iOS逆向系列-动态调试

    Xcode调试App原理 Mac安装了Xcode Xcode的安装包中包含了debugserver 可执行类型的Mach-O文件,iPhone第一次连接Xcode调试会将Xcode中的debugser ...

  7. iOS逆向系列-theos

    概述 theos是GitHub开源的一个项目,通过nic.pl创建tweak项目.通过编写我们注入代码,然后执行编译.打包.安装等操作将代码注入iPhone安装的制定程序. theos环境配置 安装签 ...

  8. iOS 逆向之ARM汇编

    最近对iOS逆向工程很感兴趣. 目前iOS逆向的书籍有: <Hacking and Securing IOS Applications>, <iOS Hacker's Handboo ...

  9. iOS逆向+越狱

    感觉本文涉及内容有点多的,但是自己不愿意写太多,就简单的谢谢关于ios上手的东西吧 初级入手不免要用到,pp助手,i4 tools等 iOS逆向-ipa包重签名及非越狱手机安装多个应用 1.常识 我们 ...

随机推荐

  1. HTML5布局篇

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title> ...

  2. poi之Excel下载之详细设置

    1.设置标题格式 /** * HEAD样式 * * @param workbook * @param sheet */ public void setHeadCellStyles(HSSFWorkbo ...

  3. NX二次开发-UFUN求两个对象最短距离UF_MODL_ask_minimum_dist

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> UF_initialize() ...

  4. NX二次开发-UFUN将目录与文件名组合在一起uc4575

    NX11+VS2013 #include <uf.h> #include <uf_ui.h> #include <uf_cfi.h> UF_initialize() ...

  5. Jboss集群(五)--F5硬件负载均衡器双击热备 + Jboss集群终极实现

    BIG/IP利用定义在其上面的虚拟IP地址来为用户的一个或多个应用服务器提供服务.因此,它能够为大量的基于TCP/IP的网络应用提供服务器负载均衡服务.BIG/IP连续地对目标服务器进行L4到L7合理 ...

  6. 创建 Angular 8.0 项目

    创建 Angular 8.0 项目,首先确保已经安装了 nodejs,如果没有安装,请看这篇文章安装:node.js 安装 1.新建一个空文件夹 angularproject,作为工作区 2.安装 A ...

  7. Mysql集群和主从

    1.Mysql cluster: share-nothing,分布式节点架构的存储方案,以便于提供容错性和高性能. 需要用到mysql cluster安装包,在集群中的每一个机器上安装. 有三个关键概 ...

  8. 控制音量大小widget

    由于手机音量按键非常悲剧的掉了.无法控制手机音量大小.使用起来非常不方便.所以决定写一个小widget放在桌面能够随时控制音量吧.也算是解决一点便利问题. 1.一个简单的widget 由于我的需求非常 ...

  9. 从虚拟地址,到物理地址(开PAE)

    学了好久好久,但是好久好久都没有用过,今天突然要用,都快忘了怎么玩了, 这里记录一下吧. 如何检测PAE r cr4 第5位如果是1,则开了PAE,否则没开 切入目标进程 查找一个自己关注的字符串s ...

  10. HTML_标签

    <!--HTML:1.概念:最基础的网页开发语言Hyper Text Markup Language 超文本标记语言超文本:超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本. ...