iOS 开发中的 Mach O 文件 - 文章教程

iOS 开发中的 Mach O 文件

发布于 2021-02-28 字数 7118 浏览 1363 评论 0

一、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 动态加载器

dyld源码 apple源码

2.从动态库共享缓存抽取动态库

可以使用dyld源码中的launch-cache/dsc_extractor.app。将 #if 0前面的代码删除(包括#if 0),把最后面的#endife也删掉

  • 编译 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

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

2583 文章
29 评论
84935 人气
更多

推荐作者

Jay

文章 0 评论 0

guowei007

文章 0 评论 0

2668157715

文章 0 评论 0

HY阳

文章 0 评论 0

想挽留

文章 30 评论 3