内容简介:免越狱调试的方案中,常用的有环境信息optool: commit(2898b51)
免越狱调试的方案中,常用的有 IPAPatch 与 MonkeyDev ,都会将自定义的代码打成 framework,注入到 App 中,以实现调试的功能。
环境信息
optool: commit(2898b51)
dyld: commit(3f928f3)
关于动态库注入,IPAPatch 采用的是开源的 optool ,MonkeyDev 采用的是 monkeyparser。相比之下 monkeyparser 比 optool 多一些功能,但在动态库注入上,原理应该类似。除了免越狱调试这种玩法外,还可以用于 App 自动化测试、性能分析等。
在不使用 Xcode 调试的情况下,如果想要获取 premain 的耗时,可以看 Joy 的 如何精确度量 iOS App 的启动时间 。其中要记录所有动态库加载时间,所以打点的库需要第一个被加载。对于内部应用,可以用 Cocoapods,对于 ipa 产物来说,可以直接将动态库注入到第一个 LoadCommand(第一个 LC_LOAD_DYLIB
)。
流程总览
注入做的事情,其实就是给 MachO 的每个架构中,添加类型为 LC_LOAD_DYLIB
的 LoadCommand。
之后补个图
optool 源码浅析
optool 实现了动态库注入与移除、移除签名,移除 ASLR 等功能,主要看动态库的部分。
基础配置
拉取源码:
# 拉取代码 git clone --depth 1 -b master git@github.com:alexzielenski/optool.git # 拉取 optool 用来做参数解析的 FSArgumentParser cd optool git submodule init git submodule update --remote
打开工程,Xcode -> Product -> Scheme -> Edit Scheme… -> Run -> Arguments 添加入参。相当于控制台直接调用,方便断点调试。
# install: 动态库注入 Action # -t: 指定目标二进制 # -p: 指定动态库 install -t /Users/saitjr/Desktop/TTTest.app/TTTest -p /Users/saitjr/Desktop/MTHawkeye.framework/MTHawkeye
关于 -p
参数,也就是动态库路径的指定,后文再谈,这里只是为了调试 optool。目前写本地绝对路径,注入后的 App 会启动闪退。
在 optool 的 main
函数中,如果断点能正确拿到入参,就说明配置没问题了。
int main(int argc, const char * argv[]) { @autoreleasepool { BOOL showHelp = NO; NSLog(@"%s", argv[1]); // 输出 install ... ... }
读取 MachO Header
参数校验的部分直接跳过,从读取二进制,解析 header 开始:
// 读取可执行文件 NSData *originalData = [NSData dataWithContentsOfFile:executablePath]; // mutableCopy 一下,方便编辑 NSMutableData *binary = originalData.mutableCopy; // 初始化 thin header 数组,数组长度为 4,也就是最多能包含四个架构 struct thin_header headers[4]; // 初始化 thin header 个数,即可执行文件中的架构数 uint32_t numHeaders = 0; // 读取 header headersFromBinary(headers, binary, &numHeaders);
thin_header
结构体是自定义的,里面直接用的系统的 mach_header
,虽然还有一个是 mach_header_64
,但是 64 里面多的 reserved
只是保留字段,没有具体含义,所以不影响解析。
除此之外,还将 fat header 中,每个架构的 offset
逐个赋值给了 thin header,只是为了方便读取。
在 headersFromBinary
中,对 header 进行读取。
之后补个图
查找 LoadCommand
header 读取完后,注入需要用到的信息有:
- 架构数
- 每个架构的偏移量
- 每个架构的 Load Command 数量
- 每个架构的 Load Command 大小
然后遍历全部架构,执行 install
,也就是 insertLoadEntryIntoBinary
方法。在真正执行插入之前,会先检查当前 LoadCommand 是否已经存在,所以有个查找的操作,方法是 binaryHasLoadCommandForDylib
。
之后补个图
以上所述就是小编给大家介绍的《动态库注入》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 一个静态注入动态库的工具 luject
- 动态调试|Maccms SQL 注入分析(附注入盲注脚本)
- 用expect脚本实现Xcode对越狱设备的动态库注入
- luject v1.0.3首发,一个静态注入动态库的工具
- hookso 1.1 发布,Linux 动态链接库的注入修改查找工具
- Angular 4 依赖注入教程之二 组件中注入服务
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Science of Programming
David Gries / Springer / 1989-4-21 / USD 99.00
Describes basic programming principles and their step-by- step applications.Numerous examples are included.一起来看看 《The Science of Programming》 这本书的介绍吧!