iOS逆向学习之四(初识Mach-O)

什么是Mach-O文件?

Mach-O是Mach object的缩写,是Mac\iOS上用来存储程序、库的标准格式

Mach-O文件类型

  • 可以点击下载xnu源码,在源码中的<font color=red>EXTERNAL_HEADERS/mach-o/loader.h
    </font>文件中,我们可以看到Mach-O格式的所有文件类型
image

xun是苹果MacOS\iOS等操作系统的内核

  • 常见的Mach-O文件类型
Mach-O类型 示例文件
MH_OBJECT 目标文件(.o)
静态库文件(.a)注:
MH_EXECUTE 可执行文件,存放App的所有源码信息,在.app/xx
MH_DYLIB 动态库文件.dylib 或者 .framework/xx
MH_DYLINKER 动态链接编辑器,也就是之前所说的/usr/lib/dyld工具
MH_DSYM 此文件中存储这二进制文件符号信息,在开发中,我们经常使用此文件来分析App的崩溃信息

Mach-O的基本结构

可以点击官网查看Mach-O的介绍。

Mach-O组成

Mach-O由3个部分组成

  • Header,包含文件类型、目标架构类型等等
  • Load commands,是描述文件在虚拟内存中的逻辑结构和布局,相当于一份目录索引
  • Raw segment data,在Load commands中所定义的Segment,在这里都能找到原始数据。

Raw segment data存放了所有的原始数据,而Load commands相当于Raw segment data的索引目录

image

窥探Mach-O的结构

常用工具

  • 命令行工具,通过file命令查看Mach-O文件的基本信息
file 文件路径
  • otool,查看Mach-O特定部分和段的内容
#查看Mach-O文件的header信息
otool -h 文件路径

#查看Mach-O文件的load commands信息
otool -l 文件路径

更多使用方法,终端输入otool -help查看

  • lipo,用来处理多架构Mach-O文件,常用命令如下
#查看架构信息
lipo -info 文件路径

#导出某种类型的架构
lipo 文件路径 -thin 架构类型 -output 输出文件路径

#合并多种架构类型
lipo 文件路径1 文件路径2 -output 输出文件路径

Universal Binary(通用二进制文件)

通用二进制文件就是同时适用于多种架构的二进制文件,它包含了多种不同架构的独立的二进制文件,它有以下特点

  • 因为需要存储多种架构的代码,所以通用二进制文件要比单架构二进制文件要大
  • 因为两种种架构之间可以共用一些资源,所以两种架构的通用二进制文件大小不会达到单一架构版本的两倍。
  • 运行过程中只会调用其中的部分代码,所以运行起来不会占用额外的内存
  • 通用二进制文件通常也被称为“胖二进制文件(Fat binary)”

dyld和Mach-O

dyld是iOS中用来加载可执行文件、动态库的工具,其实它本身也是一个Mach-O文件。

什么是dyld?
  • dyld 动态加载器(又叫做动态链接编辑器)
  • dyld的源码可以点击此处下载
dyld的作用。

dyld可以用来加载以下三种类型的Mach-O文件

  • MH_EXECUTE
  • MH_DYLIB
  • MH_BUNDLE

通过查看dyld的源码可以看到加载文件时的类型校验

image

从编码到App安装到手机

想要了解Mach-O文件,首先要了解从编写代码,开发App到App打包并安装到手机上的整个过程。

  • 首先我们编写完成代码之后,会通过LLVM编译器预处理我们的代码,比如将宏放在指定的位置
  • 预处理结束之后,LLVM会对代码进行词法分析和语法分析,生成AST。AST是抽象语法树,主要用来进行快速遍历,实现静态代码检查的功能。
  • AST会生成IR,IR是一种更加接近机器码的语言,通过IR可以生成不同平台的机器码。对于iOS平台,IR生成的可执行文件就是Mach-O.
  • 然后通过链接器将符号和地址绑定在一起,并且将项目中的多个Mach-O文件合并成一个Mach-O文件。
  • 最后通过签名等操作生成.app文件,然后对.app文件进行压缩就生成了我们可以安装的ipa包。
  • 当然,ipa包的安装途径有两种:
    • 通过开发者账号上传到App Store,然后在App Store上下载安装。
    • 通过PP助手、iFunBox、Xcode等工具来安装

逆向App,我们需要做哪些工作?

初步了解了什么是Mach-O文件,以及App从开发到安装的过程,我们就可以来学习如何逆向一款App

  • 界面分析
    通过之前的学习,我们已经可以使用Cycript和Reveal对App的界面进行分析
  • 代码分析
    iOS开发中,所有的代码最后都会经过编译生成Mach-o文件,所以我们需要对Mach-O文件进行静态分析

静态分析的工具有MachOView、class-dump、Hopper Disassembler、ida等等,后面会一一学习

  • 动态调试
    除了静态分析,我们还需要运行目标App,对App进行动态调试

动态调试的工具有debugserver、LLDB等等

  • 代码编写、注入
    进行完界面分析、代码分析和动态调试之后,我们可以在特定位置注入我们自己写的代码,必要时可以重新签名并且打包ipa

调试工具

calss-dump

class-dump的作用就是把Mach-O文件的class信息给导出来,生成对应的.h头文件

  • 可以点击官网下载class-dump工具包
  • 下载完成之后将其中的class-dump可执行文件复制到Mac上的<font color=red>/usr/local/bin</font>目录中,这样在终端就能识别class-dump命令了

在Mac中,终端执行的所有指令都会去<font color=red>/usr/bin</font>目录和<font color=red>/usr/local/bin</font>目录下寻找

  • class-dump的常用命令如下
# -H表示需要生成头文件  -o用于指定头文件的存放目录
class-dump -H Mach-O文件路径 -o 头文件存放目录

Hopper Disassmbler

Hopper Disassmbler可以将Mach-O文件的机器语言反编译成汇编代码、OC伪代码或者是Swift伪代码。最常使用的快捷键有

#找出哪里引用了这个方法
Shift + Option + X

下载地址:https://pan.baidu.com/s/1yP_VcBlQ2G-rWsRue3uSBg


静态库和动态库

在iOS开发中,有很多功能都是现成可用的,不关你的App在用,其它的App也在用,比如UIKit框架、GUI框架、I/O、网络等等。这些库都是通过链接器链接到Mach-O文件中的。

静态库

静态库是编译时链接的库,需要连接进入Mach-O文件中,如果需要更新就必须重新编译一次,无法做到动态加载和更新

动态库

动态库是运行时链接的库。

Mach-O是文件编译之后的产物,所以动态库并没有参与Mach-O文件的编译和链接。所以Mach-O文件中没有包含动态库的符号定义,也就是说这些符号会直接显示未定义,但是他们的名字和对应库的路径会被记录下来。在运行时通过dlopen和dlsym导入动态库时,会根据记录的路径找到对应的库,再通过记录的名字符号找到绑定的地址。

动态库共享缓存(dyld shared cache)

从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache),缓存路径是<font color=red>/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX</font>

dyld_shared_cache_armX里面的X代表ARM处理器指令集的架构

ARM指令集

ARM指令集(CPU指令的集合)有以下几种

ARM指令集 支持的设备
armv6 iPhone、iPhone3G
iPod Touch、iPod Touch2
armv7 iPhone3GS、iPhone4、iPhone4S
iPad、iPad2、iPad3(The New iPad)、iPad mini
iPod、Touch3G、iPod Touch4、iPod Touch5
armv7s iPhone5、iPhone5C、iPad4
arm64 iPhone5S、iPhone6、iPhone6 Plus、iPhone6S、iPhone6S Plus
iPhoneSE、iPhone7、iPhone7Plus、iPhone8、iPhone8 Plus、iPhoneX
iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2
iPad mini with Retina display、iPad mini3、iPad mini4
iPod Touch6

以上所有的指令集都是向下兼容的
为什么要使用动态库共享缓存呢?最大的好处就是节省内存。

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

由于动态库共享缓存太大,如果想获取其中某个动态库,例如UIKit,就需要从动态库共享缓存中抽取对应的动态库

  • 使用dyld源码中提供的方式来进行抽取,工具在源码中的<font color=red>launch-cache/dsc_extractor.cpp</font>文件中

    • 首先需要去掉源码中的<font color=red>#if 0</font>判断
    • 然后使用如下命令编译<font color=red>dsc_extractor.cpp</font>文件
    clang++ -o dsc_extractor dsc_extractor.cpp
    

    此处是将dsc_extractor.cpp编译生成可执行文件dsc_extractor

    • 进入执行文件dsc_extractor所在目录。通过以下的命令来抽取动态库
    ./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的目录
    
image
>建议抽取armv7s架构的动态库,arm64抽取时会报以上错误,原因是dsc_extractor.bundle不能在Xcode10之后使用

- 抽取完成之后,使用Hopper Disassmbler打开想要逆向的动态库,就可以看到动态库中的源码信息。


![image](https://upload-images.jianshu.io/upload_images/20878107-73f56e5bab50be16?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 一、APP从开发到安装到手机的过程 1.1、生成ipa包的过程选择手机下的可执行文件 1.2、真正安装的过程安装方...
    IIronMan阅读 1,788评论 0 4
  • 一、ipa了解是个压缩包,解压后 二、逆向app思路; 界面分析Cycript:通过命令行查看界面的组成情况,子控...
    Lovell_阅读 1,353评论 0 1
  • 逆向App的基本步骤 界面分析Cycript、Reveal 代码分析对Mach-O文件的静态分析MachOView...
    迷心迷阅读 737评论 0 0
  • Cycript简介 Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混...
    斑驳的流年无法释怀阅读 793评论 0 0
  • 原文链接 dyld简介 共享缓存机制1. dyld_cache_extract提取2. jtool提取3. dsc...
    三三At你阅读 1,325评论 0 4