MachO文件简介

一、什么是MachO文件?
  • Mach-O其实是Mach Object文件格式的缩写,它是Mac以及iOS上一种用于可执行文件、目标代码、动态库的文件格式,类似于Windows上面的PE格式(Portable Executable),linux上的elf格式(Executable and Link Format)。
  • 它是一种用于可执行文件、目标代码、动态库的文件格式,作为.out格式的替代,MachO提供了更强的扩展性。
二、Mach-O文件格式
  • 目标文件.o
  • 库文件:.a .dylib .Framework
  • 可执行文件
  • dyld(动态链接器)
  • .dsym(符号表:Relese环境运行生成)
三、查看文件类型
  • $ file xxx.xx

系统架构

一、iPhone不同的型号对应的架构
手机型号 架构
32位模拟器 i386
64位模拟器 x86_64
iPhone4、iPhone4S armv7
iPhone5、iPhone5C armv7s
iPhone5s——iPhoneX arm64
iPhone XS、iPhone XS Max、iPhoneXR、iPhone11… arm64e
二、Xcode中指令集相关选项(Build Setting)
  • Architectures
    指定工程被编译成可支持哪些指令集类型,支持的指令集越多,就会编译出包含多个指令集代码的数据包,对应生成二进制 .ipa 包会变大。
  • Valid Architectures
    限制可能被支持的指令集的范围,即:Xcode编译出来的二进制包类型最终从这些类型产生,而编译出哪种指令集的包,将由Architectures与Valid Architectures的交集来确定
  • Build Active Architecture Only
    指定是否只对当前连接设备所支持的指令集编译。当其值设置为YES,是为了debug的时候编译速度更快,它只编译当前的Architecture版本,而设置为no时,会编译所有的版本。 所以,一般debug的时候可以选择设置为YES,release的时候要改为NO。
三、生成多种架构
  • 新建一个工程,真机运行,查看可执行文件仅是一个arm64架构的,将项目最低适配系统调为iOS9.0,真机运行 Relese环境:
~/Library/Developer/Xcode/DerivedData/TestDemo-aszxljwcoetyppfyxjarbzmhorsh
/Build/Products/Release-iphoneos/TestDemo.app  file TestDemo
TestDemo: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7 ] [arm64:Mach-O executable arm64]
TestDemo (for architecture armv7):     Mach-O executable arm_v7
TestDemo (for architecture armv54):     Mach-O 64-bit executable arm64
  • 为什么要改为iOS9.0呢 ?是因为iPhone5c等armv7、armv7s架构不支持iOS11.0;
  • 为什么要Relese环境运行呢 ?因为Xcode默认Debug只生成单一架构;

  • 怎么生成所有架构 ?Xcode10中只包含了v7和64,需要在 Architectures 中添加:

通用二进制文件(Universal binary)

一、简介

  • 通用二进制文件也被叫做胖二进制(Fat binary)
  • 苹果公司提出的一种程序代码,能同时适用多种架构的二进制文件
  • 同一个程序包中同时为多种架构提供最理想的性能;
  • 由于需要储存多种代码,通用二进制应用程序通常比单一平台二进制的程序要大;
  • 由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多;
  • 由于执行中只调用一部分代码,运行起来也不需要额外的内存;

二、拆分/合并架构

① 终端命令
  • 架构查看
lipo -info + macho
  • 架构合并
lipo -create macho_A macho_B -output(-o) macho_AB
  • 架构分离
lipo macho -thin -arm64 -o macho_arm64
② 结论
  • 胖二进制拆分后再重组会得到原始胖二进制
  • 通用二进制的大小可能大于子架构大小之和,也可能小于,也可能等于,取决于公共资源文件的多少;

MachO文件结构

一、苹果官方结构

主要组成可以大概分为三大块:

  • Header部分(包含该二进制文件的一般信息):字节顺序、架构类型、加载指令的数量等。使得可以快速确认一些信息,比如当前文件用于32位还是64位,对应处理器是什么,文件类型是什么。
  • Load commands 部分(一张包含很多内容的表);内容区包括区域的位置、符号表、动态符号表等。
  • Data段:包含Segement的具体数据。
二、整体结构
  • 使用 MachOView 打开会看到通用二进制文件由 Fat Header 和可执行文件组成(可执行文件是由 Header 、 Load commands 和 Data 组成):

  • 可执行文件是由 Header 、 Load commands 和 Data 组成:

  • 可以使用otool命令来查看Mach-O文件,也可以使用MachOView这个工具查看刚刚生成的MachO文件,先cd到当前文件夹,然后:
$otool -f MachOFat headers
fat_magic 0xcafebabe
nfat_arch 3
architecture 0cputype 12cpusubtype 9capabilities 0x0offset 16384size 73568align 2^14 (16384)
architecture 1cputype 12cpusubtype 11capabilities 0x0offset 98304size 73568align 2^14 (16384)
architecture 2cputype 16777228cpusubtype 0capabilities 0x0offset 180224size 73888align 2^14 (16384)
  • header 包含了该二进制文件的字节顺序、架构类型、加载指令的数量等,使得可以快速确认一些信息,比如当前文件用于 32 位 还是 64 位 ,对应的处理器是什么、文件类型是什么;Xcode中 shift+command+O -> load.h -> 如下信息(mach_header_64(64位)对比mach_header(32位)只多了一个保留字段)
struct mach_header_64 {uint32_t  magic;    /* 魔数,快速定位64位/32位 */cpu_type_t  cputype;  /* cpu 类型 比如 ARM */cpu_subtype_t  cpusubtype;  /* cpu 具体类型 比如arm64 , armv7 */uint32_t  filetype;  /* 文件类型 例如可执行文件 .. */uint32_t  ncmds;    /* load commands 加载命令条数 */uint32_t  sizeofcmds;  /* load commands 加载命令大小*/uint32_t  flags;    /* 标志位标识二进制文件支持的功能 , 主要是和系统加载、链接有关*/uint32_t  reserved;  /* reserved , 保留字段 */
};
  • load commands 是一张包括区域的位置、符号表、动态符号表等内容的表。它详细保存着加载指令的内容,告诉链接器如何去加载这个 Mach-O 文件。通过查看内存地址发现,在内存中 load commands 是紧跟在 header 之后的;

  • load commands的详情:
/* Constants for the cmd field of all load commands, the type */#define    LC_SEGMENT    0x1    /* segment of this file to be mapped */
#define    LC_SYMTAB    0x2    /* link-edit stab symbol table info */
#define    LC_SYMSEG    0x3    /* link-edit gdb symbol table info (obsolete) */
#define    LC_THREAD    0x4    /* thread */
#define    LC_UNIXTHREAD    0x5    /* unix thread (includes a stack) */
#define    LC_LOADFVMLIB    0x6    /* load a specified fixed VM shared library */
#define    LC_IDFVMLIB    0x7    /* fixed VM shared library identification */
#define    LC_IDENT    0x8    /* object identification info (obsolete) */
#define LC_FVMFILE    0x9    /* fixed VM file inclusion (internal use) */
#define LC_PREPAGE      0xa     /* prepage command (internal use) */
#define    LC_DYSYMTAB    0xb    /* dynamic link-edit symbol table info */
#define    LC_LOAD_DYLIB    0xc    /* load a dynamically linked shared library */
#define    LC_ID_DYLIB    0xd    /* dynamically linked shared lib ident */
#define LC_LOAD_DYLINKER 0xe    /* load a dynamic linker */
#define LC_ID_DYLINKER    0xf    /* dynamic linker identification */
#define    LC_PREBOUND_DYLIB 0x10    /* modules prebound for a dynamically */
/*  linked shared library */
#define    LC_ROUTINES    0x11    /* image routines */
#define    LC_SUB_FRAMEWORK 0x12    /* sub framework */
#define    LC_SUB_UMBRELLA 0x13    /* sub umbrella */
#define    LC_SUB_CLIENT    0x14    /* sub client */
#define    LC_SUB_LIBRARY  0x15    /* sub library */
#define    LC_TWOLEVEL_HINTS 0x16    /* two-level namespace lookup hints */
#define    LC_PREBIND_CKSUM  0x17    /* prebind checksum *//** load a dynamically linked shared library that is allowed to be missing* (all symbols are weak imported).*/
#define    LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)#define    LC_SEGMENT_64    0x19    /* 64-bit segment of this file to be
mapped */
#define    LC_ROUTINES_64    0x1a    /* 64-bit image routines */
#define LC_UUID        0x1b    /* the uuid */
#define LC_RPATH       (0x1c | LC_REQ_DYLD)    /* runpath additions */
#define LC_CODE_SIGNATURE 0x1d    /* local of code signature */
#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */
#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */
#define    LC_LAZY_LOAD_DYLIB 0x20    /* delay load of dylib until first use */
#define    LC_ENCRYPTION_INFO 0x21    /* encrypted segment information */
#define    LC_DYLD_INFO     0x22    /* compressed dyld information */
#define    LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)    /* compressed dyld information only */
#define    LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */
#define LC_VERSION_MIN_MACOSX 0x24   /* build for MacOSX min OS version */
#define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */
#define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */
#define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat
like environment variable */
#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
#define LC_SOURCE_VERSION 0x2A /* source version used to build binary */
#define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */
#define    LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */
#define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */
#define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */
#define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */
#define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */
#define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */
#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */
  • 部分字段说明:
  • data 是MachO文件中最大的部分,其中 _TEXT段 、 _DATA段 能给到很多信息。load commands 和 data 之间还留有不少空间,给我们留下了注入代码的冲破口:
_TEXT段名称 作用
_text 主程序代码
_stubs、_stub_helper 动态链接
_objc_methodname 方法名称
_objc_classname 类名称
_objc_methtype 方法类型
_cstring 静态字符串常量
_DATA段名称 作用
_got=Non-Lazy Symbol Pointers 非懒加载符号表
_la_symbol_ptr => Lazy Symbol Pointers 懒加载符号表
_objc_classlist 方法名称

dyld

  • dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统的一个重要组成部分,在系统内容做好程序准备工作之后,交由dyld负责余下的工作。
  • 系统库的方法由于是公用的,存放在共享缓存中,那么我们的MachO在调用系统方法时,dyld会将MachO里调用存放在共享缓存中的方法进行符号绑定。这个符号在 release环境 是会被自动去掉的,这也是经常使用收集 bug 工具时需要恢复符号表的原因。

iOS逆向之深入解析MachO文件相关推荐

  1. iOS逆向与安全 - 5. Mach-O文件格式

    前言 Mach-O文件格式源码 Mach-O苹果官方手册 想要程序跑起来,那么这个可执行文件的格式就需要被当前的操作系统所理解,比如: Linux 操作系统下可执行文件格式是 ELF Windows ...

  2. iOS逆向之深入解析如何Hook所有+load方法及Category的处理

    一.类方法 +load iOS 有四种方法可方便的在 premain 阶段执行代码: Objective C 类的 +load 方法: C++ static initializer: C/C++ at ...

  3. iOS逆向之深入解析如何计算+load方法的耗时

    一.类方法 +load 在 pre-main 时期,objc 会向 dyld 注册一个 init 回调: void _objc_init(void) {static bool initialized ...

  4. iOS逆向之深入解析App签名的双向验证机制和原理

    一.非对称加密 通常说的签名就是数字签名,它是基于非对称加密算法实现的. 对称加密是通过同一份密钥加密和解密数据,而非对称加密则有两份密钥,分别是公钥和私钥,用公钥加密的数据,要用私钥才能解密,用私钥 ...

  5. iOS逆向之深入解析如何使用Theos开发插件

    一.Logos 语法 Logos 作为 Theos 开发组件的一部分,通过一组特殊的预处理指令,可以让编写函数钩子(hook)代码变得非常简单和清晰,Logos 是随着 Theos 发布的. %hoo ...

  6. 【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编框架 | PyCharm 中导入 Capstone 反汇编框架 )

    文章目录 一.Capstone 反汇编框架 二.PyCharm 中导入 Capstone 反汇编框架 一.Capstone 反汇编框架 Android 的 APK 安装文件中 , 可能存在若干 so ...

  7. 【Android 逆向】使用 Python 代码解析 ELF 文件 ( PyCharm 中进行断点调试 | ELFFile 实例对象分析 )

    文章目录 一.PyCharm 中进行断点调试 二.ELFFile 实例对象分析 一.PyCharm 中进行断点调试 在上一篇博客 [Android 逆向]使用 Python 代码解析 ELF 文件 ( ...

  8. android r 编译找不到头文件_「投稿」iOS逆向——砸壳与反编译

    作者:疯狂的蛋神 近来对iOS逆向十分感兴趣,就在业余时间里自己在上网找了各种资料学习,发现许多资料对于一些细节描述的不够详细,所以也踩了很多坑,我也将自己踩的一些坑总结出来,希望对大家有所帮助. 注 ...

  9. ios逆向- 01逆向原理Class-dump安装及获取头文件

    逆向原理 动态调试 通过界面调试Cycript\Xcode LLDB! 静态分析 利用之前学习的汇编代码,分析三方APP的源码! 代码注入 注入的其实是动态库!HOOK代码 改变原来程序的执行流程! ...

最新文章

  1. Battle for Wesnoth 1.8.4,开源战斗游戏
  2. 清华成果发布 | 广度学习基础计算系统集成平台
  3. [Leedcode][JAVA][第76题][最小覆盖子串]滑动窗口]
  4. educoder实训平台java入门_educoder上的实训题目(学习-Java包装类之Byte类)
  5. libuv 和 libev的对比
  6. 计算机软件3dmax在展览中的研究,【建模技巧】实用展览设计3ds Max建模方法(第一期)...
  7. 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
  8. bootstrapTable 取消 “正在加载中...”
  9. 迭代器模式在 Java 容器中的实现
  10. windows 系统新建 vue 项目的坑
  11. SpringBoot+kaptcha生成验证码
  12. C++中使用GSoap
  13. 3DMax人物动画制作
  14. 散点数据的包络线获取(MATLAB)
  15. Youtube内容正在失控
  16. proteus8 Professional和keil4联调流水灯程序
  17. mysql 时间戳转换为时间_将MYSQL数据库里的时间戳转换成时间
  18. 1018 锤子剪刀布python3无超时
  19. 周志华机器学习——聚类算法。
  20. 借助FreeHttp为任意移动端web网页添加vConsole调试

热门文章

  1. 运维记录 - 业务日志清理功能
  2. request和response对象如何解决中文乱码问题?
  3. 20175213 2018-2019-2 《Java程序设计》第6周学习总结
  4. 记一次MyBatis的错误
  5. seajs打包部署工具spm的使用总结
  6. 加班其实不是真正的理由(Coders Life)
  7. 使用squid代理时出现“The requested URL could not be retrieved”
  8. ubuntu64位 oracle 11g,64位Ubuntu安装Oracle11G
  9. 示波器测ab相_独有功能,剑走偏锋,示波器鲜为人知的10大特异功能|测试能力篇...
  10. sqoop 增量导入mysql_sqoop增量导入数据库