动态库注入

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

内容简介:免越狱调试的方案中,常用的有环境信息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

之后补个图


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

查看所有标签

猜你喜欢:

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

The Science of Programming

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》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具