动态库注入

栏目: IOS · 发布时间: 5年前

内容简介:免越狱调试的方案中,常用的有环境信息optool: commit(2898b51)

免越狱调试的方案中,常用的有 IPAPatchMonkeyDev ,都会将自定义的代码打成 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

之后补个图


以上所述就是小编给大家介绍的《动态库注入》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

计算机图形学原理及实践:C语言描述(原书第2版) (平装)

计算机图形学原理及实践:C语言描述(原书第2版) (平装)

福利 / 唐泽圣 / 机械工业出版社 / 2004-3 / 95.0

《计算机图形学原理及实践:C语言描述(原书第2版)》:这是计算机图形学领域的一部经典之作,作者Fley、va Dam等是国际图形学界的著名学者、学术带头人,而且《计算机图形学原理及实践:C语言描述(原书第2版)》英文版自出版以来,一直是各国大学计算机图形学课程的主要教科书。来自清华大学、北京大学、中国科学院计算技术研究所、中国科学院软件研究所的多位图形学领域的专家和精英花费了大量的时间和精力进行翻......一起来看看 《计算机图形学原理及实践:C语言描述(原书第2版) (平装)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

SHA 加密
SHA 加密

SHA 加密工具