动态库注入

栏目: 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

之后补个图


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

查看所有标签

猜你喜欢:

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

复杂:信息时代的连接、机会与布局

复杂:信息时代的连接、机会与布局

罗家德 / 中信出版集团股份有限公司 / 2017-8-1 / 49.00 元

信息科技一方面创造了人们互联的需要,另一方面让人们在互联中抱团以寻找归属感,因此创造了大大小小各类群体的认同和圈子力量的兴起,即互联的同时又产生了聚群,甚至聚群间的相斥。要如何分析这张网?如何预测它的未来变化?如何在网中寻找机会,实现突围?本书提出了4个关键概念──关系、圈子、自组织与复杂系统: • 关系 关系是人与人的连接,又可以被分为强关系和弱关系。强关系就是和你拥有亲密关系的人,......一起来看看 《复杂:信息时代的连接、机会与布局》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具