injection III 注入任意 Swift 代码的原理

简介

Injection III 是一个 Swift 和 Objective-C 的代码注入工具,可以实现在运行时注入修改代码的功能。这个工具可以帮助开发者快速测试和迭代应用,提高开发效率。但是我们都知道 Swift 是一个静态语言, 在之前我们的认知是只有加了@objc 修饰的代码才能通过 Objective-c 的动态特性实现注入。那么injection III是如何实现注入任意 Swift 代码的呢?

dyld_dynamic_interpose

dyld_dynamic_interpose 是 macOS 和 iOS 上的动态链接器技术,可以在运行时替换函数,实现动态代码注入的功能。这个技术是通过修改动态链接库的符号表来实现的。dyld 会在程序启动时加载动态链接库,并建立动态链接库的符号表,这个符号表包含了动态链接库中的函数和变量等符号。dyld_dynamic_interpose 通过修改这个符号表来实现函数替换的功能。

具体来说,dyld_dynamic_interpose 允许开发者使用 interpose 功能来定义要替换的函数。interpose 定义了两个函数,一个是要替换的函数,另一个是替换后的函数。dyld 在加载动态链接库时,会根据 interpose 定义的要替换的函数来查找这个函数,并将其替换成替换后的函数。这个过程是在程序启动时完成的,因此可以实现在运行时注入修改代码的功能。

原理

  1. 在 dyld 中使用 dyld_dynamic_interpose 特性需要使用一个特殊的 __interpose 修饰符。该修饰符需要应用在一个数组的元素上,其中数组的元素为两个函数指针,第一个指针是需要替换的原始函数,第二个指针是需要替换成的新函数。比如,下面的代码定义了一个包含两个元素的数组,其中第一个元素是要替换的函数指针,第二个元素是要替换成的新函数指针:
__attribute__((used)) static const struct {
    void *old_func;
    void *new_func;
} interposers[] = {
    { (void*)old_func, (void*)new_func },
};
  1. dyld_dynamic_interpose 只能用于动态链接库中的函数替换,而不能用于替换可执行文件中的函数。这是因为在可执行文件中使用 __interpose 修饰符会导致链接错误。

  2. 在 dyld 加载一个动态链接库时,它会扫描这个库中的 __DATA,__interpose 节,找到所有使用 __interpose 修饰符定义的函数替换关系,并将其添加到一个替换表中。当程序调用一个被替换的函数时,dyld 会在替换表中查找对应的替换函数,并执行替换操作。

  3. 如果需要在运行时动态添加一个函数替换关系,可以使用 dyld_dynamic_interpose 函数。该函数的原型如下:

int dyld_dynamic_interpose(const char *dylib_path, const struct dyld_interpose_tuple interposers[], size_t count);

其中,dylib_path 参数是需要添加替换关系的动态链接库路径,interposers 参数是一个包含替换关系的结构体数组,count 参数是结构体数组的长度。使用 dyld_dynamic_interpose 函数添加替换关系后,新的替换关系将被添加到替换表中,之后程序调用对应的被替换函数时,会被动态地替换成新的函数实现。

限制

从这个原理中,显而易见,我们不能修改类的属性的类型,也不能增添属性,因为这都是修改了 class 的 meta 布局。并且,对于非 final 的class,也不要添加方法或者修改方法的顺序。

参考

Swift Code Injection (johnholdsworth.com)
iOS进阶 - App启动 & dyld详解(二) - 掘金 (juejin.cn)

如果这篇文章帮到你,请点个

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