APP从开发到安装到手机的过程1 MJRefreshExample.app中的MJRefreshExample文件是iOS中的可执行文件,文件格式是Mach-O APP从开发到安装到手机的过程2 逆向APP /dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的文件夹 Mach-O Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式 属于Mach-O /mach-o/fat.h EXTERNAL_HEADERS/mach-o/loader.h 常见的Mach-O文件类型 MH_OBJECT 目标文件(.o) 静态库文件(.a),静态库其实就是 Mach-O的文件类型 file 文件路径 otool:查看Mach-O特定部分和段的内容 lipo:常用于多架构Mach-O文件的处理 查看架构信息:lipo dyld用于加载以下类型的Mach-O文件 MH_EXECUTE MH_DYLIB MH_BUNDLE APP的可执行文件、动态库都是由dyld负责加载的
主要内容: 理解可执行文件 理解Mach-O文件 Mach-O文件结构 Mach Header Load Commands Data 理解大小端模式 理解通用二进制文件 一、理解可执行文件 1.可执行文件 (Mach Object)文件 二、理解Mach-O文件 作为iOS,iPadOS、macOS平台的可执行文件格式,Mach-O文件涉及App启动运行、bitcode分析、 crash符号化等诸多多个功能 Mach-O文件 Mach-O文件是iOS,iPadOS、macOS平台的可执行文件格式。 1.查看Mach-O的两种方法 使用MachOView软件,可直接查看MachO文件的结构; 使用终端命令objdump; 2.查看Mach-O文件结构 使用MachOView查看Mach-O,效果如下 - cputype 和 cpusubtype:说明Mach-O适用的平台 - offset(偏移)、size(大小)、align(页对齐)描述了Mach-O二进制位于通用二进制文件的位置 */
目录 一、什么是Mach-O 二、属于Mach-O格式的文件类型 三、常见的Mach-O文件类型 四、Universal Binary通用二进制文件 五、Mach-O基本结构 5.1 窥探Mach-O的结构 5.2 Mach-O文件包含3个主要区域 5.2.1 Header 5.2.2 Load commands 5.2.3 Section 5.2.4 _debug相关section 六、Mach-O加载过程 一、什么是Mach-O Mach-O是Mach Object的缩写,是Mac/iOS上用于存储程序、库的标准格式 二、属于Mach-O格式的文件类型 xnu内核源码-loader.h文件 #define 基本结构 5.1 窥探Mach-O的结构 5.2 Mach-O文件包含3个主要区域 Header(头部) : 指明了cpu架构、大小端序、文件类型、Load commands个数等一些基本信息 Load 加载 Mach-O 到进程空间。 加载动态连接器 dyld 并将控制权交给 dyld 处理。
之前负责项目的包体积优化学习了 Mach-O 文件的格式,那么 Mach-O 究竟是怎么样的文件,知道它的组成之后我们又能做点什么? 本文会从 Mach-O 文件的介绍讲起,再看看认识它后的一些实际应用。 Mach-O 文件格式 先让我们看看 Mach-O 的大致构成 [1240] 再使用 MachOView 一窥究竟 [1240] 结合可知 Mach-O 文件包含了三部分内容: Header(头部),指明了 在 Mach-O 文件中可以有多个 Segment,每个 Segment 可能包含一个或多个 Section。 Data(数据区),Segment 的具体数据,包含了代码和数据等。 Headers Mach-O 文件的头部定义如下: [1240] magic 标志符 0xfeedface 是 32 位, 0xfeedfacf 是 64 位。
Mach-O 定义 ---- Mach-O(Mach Object)是 macOS、iOS、iPadOS 存储程序和库的文件格式。 Mach-O 格式用来代替 BSD 系统的 a.out 格式。Mach-O 文件格式保存了在编译过程和链接过程中产生的机器代码和数据,从而为静态链接和动态链接的代码提供了单一文件格式。 (符号表) 由此我们知道,可执行文件只是Mach-O的一种,因此我们将Mach-O文件分为以下几种: 名称 注释 Mach-O Object 目标文件 Mach-O ececutable 可执行文件 Mach-O dynamically 动态库文件 Mach-O dynamic linker 动态链接器文件 Mach-O DSYM companion 符号表文件 通用二进制文件(Universal Mach-O 文件结构 ---- Mach-O文件主要由 3 部分组成 注释 ?
但可执行文件和Mach-O文件有什么关系呢?其实可执行文件属于Mach-O文件类型,换句话说,可执行文件是一种Mach-O文件。所以,了解Mach-O文件的同时,我们也就了解了可执行文件。 Mach-O简介Mach-O是Mach object的缩写(来源于官方文档)。Mach-O是iOS/macOS系统上应用程序、库的标准文件格式,它并不像Windows平台中的PE文件那样复杂。 符合Mach-O标准格式的文件都是Mach-O文件。 Mach-O文件格式Mach-O文件由一下3部分数据区域组成:Header(Mach-O头部)Load Commands(加载命令)Raw segment data(下图中的Data,数据块)[Mach-O 用于校验Mach-O文件的合法性即确定文件的运行环境。我们可以使用 otool 的-h参数分析header的数据。下图是mach-o/loader.h中对Mach-O的header的定义。
x^2 + y^2 = r^2# mach-o文件分析多余的类和方法.md 背景 最近做包大小优化,在做项目代码优化时,其中有一个过程是分析Mach-O文件,看网上很多文章都说通过otool分析Mach-O 原理 首先来看Mach-O是什么,Mach-O是Mach Object文件格式的缩写,是一种记录可执行文件、对象代码、共享库、动态加载代码和内存转储的文件格式。 Mach-O文件主要由3部分组成: Mach Header: 描述 Mach-O 的CPU架构、文件类型、加载命令等信息 Load Command: 描述文件中数据等具体组织结构,不同数据类型使用不同等加载命令表示 参考 otool 工具分析可能没有使用的Objective-C类 LinkMap iOS调优 | 深入理解Link Map File iOS堆栈信息解析(Mach-O) 包体积大小:瘦身 Mach-O学习 Mach-O 文件格式探索 二进制文件分析之常用命令 iOS代码瘦身实践:删除无用的类
Mach 内核的操作系统比如 macOS,iPadOS 和 iOS 都是用的 Mach-O。Mach-O 包含程序的核心逻辑,以及入口点主要功能。 构建 构建 Mach-O 文件,主要需要用到编译器和静态链接器,编译器可以将编写的高级语言代码转成中间目标文件,然后用静态链接器把中间目标文件组合成 Mach-O。 构建完 Mach-O。那你一定好奇 Mach-O 里面都有什么呢? 选择要加载的 Mach-O 后,系统内核会先确定该文件是否是 Mach-O 文件。 文件的第一个字节是魔数,通过魔数可以推断是不是 Mach-O,mach-o/loader.h 里定义了四个魔数标识。
归根到底还是由于Mach-O文件存储了类和函数的信息。在Mach-O中,所有的类都存储到__objc_classlist这个section中。 在Mach-O需要先判断0x1000011820位于哪个segment中,在Load Commands里会记录每个segment的起始虚拟地址及size。 按Mach-O的存储习惯,大概率是先约定单个函数的存储长度,再告诉我们函数个数; void addVTable() { ... 按照Mach-O的习惯,一般Kind、Flag这样的字节都会有一定的标示性,能够通过一个或几个字节告诉我们后续内容的类别情况。 本文并不是推广动态调用,仅仅是从动态调用这个场景将大家吸引到Mach-O的解析过程中。Swift作为一门很先进的语言,有太多的特性值得我们去探索。
void *(*)(size_t)) MSFindSymbol(image, "_malloc"); void *data = (*palloc)(1024); free(data); III 、Mach-O 在这里插入图片描述 Mach-O 是针对不同运行时可执行文件的文件类型。 Image: executable,dylib 或 bundle Framework: 包含 Dylib 以及资源文件和头文件的文件夹 3.2 Mach-O 镜像文件 iOS 可执行文件是 Mach-O
前言 ---- 上一节学习了 iOS强化 : 熟悉 Mach-O 文件, 对 Mach-O 有个大致的了解,今天来学习 Mach-O 可执行文件的生成过程 :编译与链接。 Mach-O 文件生成过程 ---- 链接的本质 :就是把多个⽬标⽂件组合成⼀个⽂件(Mach-O可执行文件) 目标文件 :通常.o文件被我们称之为目标文件 ▐ 2.1 目标文件的生成过程 ? 多个目标文件合并 符号表(包括重定位符号表)合并成一张表 生成一个Mach-O可执行文件 3. 静态链接 ---- 代码经过编译链接最后分配虚拟内存地址生成可执行文件或动态库 ? 4. 生成一个或多个.o目标文件 链接本质:多个目标文件合并,符号表(包括重定位符号表)合并成一张表,生成一个Mach-O可执行文件
architecture arm64): Mach-O 64-bit dynamically linked shared library arm64 lipo lipo 是Apple提供的针对“ /tmp-armv7.a: current ar archive random library .a 文件通常由多个 Mach-O 文件通过特殊算法压缩的,所以,我们可以通过 tar 命令进行解压缩。 该命令会产出多个 Mach-O object 文件,每个文件对应一个源码文件(.c 或 .m ) tar -xf tmp-armv7.a 在进行后续的校验前,我们先验证产出文件的类型是否为 Mach-O object 类型 file MockLibrary.o MockLibrary.o: Mach-O object arm_v7 每个 Mach-O 包含很多份不同用途的 data。 file tmp-armv7.a 我们可以从输出信息看到,动态库已经是 Mach-O 格式的文件。
如下: otool -l mach-O文件 | grep crypt 例如: 图片 image.png 如上:TEST是笔者App的已经脱壳的可执行文件。 使用MachOView检测 不想使用otool命令行还可以使用MachOView,MachOView是一款开源的Mach-O可视化工具。通过MachOView可以清晰的查看Mach-O问价的内部结构。 Mach-O通常是胖二进制格式,也就是一个Mach-O文件包含多种架构,比如:arm64、armv7、armv7s等。胖二进制的目的是为了支持更多架构的iPhone。 mach-O文件 -thin 架构类型 -output 分离的mach-O文件 # lipo WeChat -thin arm64 -output WeChat_arm64 # 合并多种架构 命令格式:lipo mach-O文件1 mach-O文件2 -output 合成的mach-O文件 # lipo WeChat_arm64 WeChat_armv7 -output WeChat
Clutch- Fast iOS executable dumper dumpdecrypted - Dumps decrypted mach-o files from encrypted iPhone .app/2048 pp2048/Payload/2048.app/2048: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O 所以,一般还是直接在Mach-O中注入少量指令,并使其在运行时加载我们的动态库, 这样就可以在动态库中实现复杂的操作了。 关于Mach-O的详细文件格式可以参考PARSING MACH-O FILES。 以insert_dylib为例,注入dylib只需一条命令: $ . : [arm_v7:Mach-O dynamically linked shared library arm_v7] [arm64:Mach-O 64-bit dynamically linked shared
作为a.out格式的替代,Mach-O提供了更强的扩展性,并提升了符号表中信息的访问速度。 Mach-O曾经为大部分基于Mach核心的操作系统所使用。 深度了解可以看下这篇文章:探秘 Mach-O 文件 Mach-O术语 文件类型: Executable:应用的主要二进制文件(比如.o文件) Dylib:动态库(又称 DSO 或 DLL) Bundle Framework:动态库和对应头文件和资源的集合 Mach-O文件 ---- 介绍了 Mach-O内部结构,每个分区和如何支持不同架构等。 1、 Mach-O被分为下图的几个segment: ? __objc_classrefs :引用的类 3、Mach-O的通用文件 ? 在不同的架构内存的分配是不同的,那么怎么做一个兼容架构的Mach-O文件? ? 1、加载动态库步骤 解析依赖所有的动态库 找到请求的mach-o 文件 打开读取文件 验证mach-o 文件 签名 调用每个segmentmmap()函数 等到所有直接依赖的动态库加载完成,加载动态库依赖的其他动态库
[图:Asset Catalog] 1.2、Mach-O 文件 Mach-O 文件是 iOS 上的可执行文件,它是由代码源文件经过编译和静态链接获得。 经过 App Slicing 之后的 Mach-O 文件往往仅包含单个架构。使用 MachOView 等工具,我们可以直观了解 Mach-O 中包含的内容。 [image] 同时,Link Map 文件能更进一步帮助我们分析 Mach-O 文件的构成。 三、Mach-O 文件优化 在资源优化的同时,我们也关注到,Mach-O 文件始终占据了今日头条安装包 80% 左右的体积。Mach-O 文件的优化必不可少。 但是,对于一个 Mach-O 文件来说,并非所有的符号都是需要暴露给其他动态库或可执行文件的。
rename_section,__TEXT, __custom_section,__CUSTOM_TEXT,__text,-segprot, __CUSTOM_TEXT,rx,rx 二、验证 1、如何找到Mach-O 文件 在xcode项目编译后,在项目目录下找到Product文件夹,下面有个xxxx.app的文件,右键show in finder,下面有个和项目同名的可执行文件这个就是Mach-O文件 2、查看Mach-O mach-o before.png 移动后 ? mach-o after.png 三、成果 将最新的IPA上传App Store后查看下载大小及安装大小。
,ASLR为:0x100d54000 - 0x100000000 = 0xd54000 2、在NSLog前通过断点停住,通过汇编可以看到,当前断点处的地址为:0x100d5a2a8 NSLog符号在Mach-O 中的偏移为:0x100d5a2a8 - 0x100d54000 = 0x62A8 3、查看并执行0x100d5a2a8地址中的内容 通过地址直接打印内容 Mach-O查看内容 使用dis - 中0x63D4偏移量的内容 【7】从Mach-O中可以看到,使用b指令跳转至偏移量为0x63BC处。 【8】查看Mach-O中0x8008偏移量的内容。 这里是指向dyld_stub_binder函数,该函数是用于符号绑定的。 从Mach-O中,可以看到dyld_stub_binder函数的偏移地址为0x8008,但其值全是0,说明在Mach-O中没有值,而dyld_stub_binder函数的真实地址其实是dyld加载主程序时
共享缓存会在进程启动时被dyld映射到内存中,之后,当任何Mach-O映像加载时,dyld首先会检查该Mach-O映像与所需的动态库是否在共享缓存中,如果存在,则直接将它在共享内存中的内存地址映射到进程的内存地址空间 2.1 Mach-O文件加载 这里先说下Mach-O文件。 Mach-O文件格式是OS X与iOS系统上的可执行文件格式,像我们编译过程产生的.O文件,以及程序的可执行文件,动态库等都是Mach-O文件。 我们可以通过Mach-O文件查看器MachOView查看一个测试项目(这里放上地址)编译后的可执行文件内容: Mach-O文件内容 这里可以看到,程序需要的dyld 在动态加载一个Mach-o文件的时候,最终都调用了load这个API。
--《唐高骈·山亭夏日》 mach-o文件和进程的映像(image) iOS系统生成的可执行程序或者动态库文件的存储布局格式被称之为mach-o格式。 mach-o文件中的段和节信息 进程映像(Image)操作API 对映像进行操作的API都在<mach-o/dyld.h>中声明。你可以import这个头文件来使用里面定义的函数。 不明白为什么这个函数会放在<mach-o/dyld.h>中声明,完全不搭界! 参数mhp则表明mach-o文件的头部结构指针。 //Author by 欧阳大哥 #import <mach-o/dyld.h> #import <mach-o/getsect.h> BOOL checkMethodBeHooked(Class class