substitute vs Substrate vs fishhook:iOS/Mac Hook工具终极选型指南
2026/8/22 14:24:12 网站建设 项目流程

substitute vs Substrate vs fishhook:iOS/Mac Hook工具终极选型指南

【免费下载链接】substituteA free runtime modification library.项目地址: https://gitcode.com/gh_mirrors/su/substitute

如果你在 iOS 或 Mac 上开发,需要"劫持"系统函数或第三方库的方法,substitute、Substrate 和 fishhook是最常被拿来对比的三款 Hook 工具。其中substitute是一个免费的运行时修改库(libsubstitute),核心能力是在运行时改写函数机器码并安全地重定向调用;Substrate是越狱生态里元老级的代码注入框架;fishhook则是专注于重新绑定动态库符号的轻量工具。这篇文章用大白话讲清三者的原理差异、能力边界和适用场景,帮你 3 分钟做出靠谱的选型决策。


一、三分钟认识这三款 Hook 工具 🧰

substitute:灵活的运行时函数劫持库

substitute(即 libsubstitute)主打"想 hook 谁就 hook 谁"。它的做法是:先反汇编目标函数的开头几字节,把被覆盖的指令搬到一块**跳板(trampoline)**里,再在原函数入口处写入跳转指令,把调用重定向到你提供的替换函数;同时回传一个"旧函数指针",方便你在钩子里继续调用原实现。

除了函数级钩子,它还提供两种更轻量的拦截方式——GOT/PLT 符号拦截ObjC 消息拦截,全部公共接口都集中在lib/substitute.h中,核心改写逻辑在lib/hook-functions.c,各架构(ARM / ARM64 / x86)的汇编与反汇编实现分别位于lib/arm/lib/arm64/lib/x86/目录。

Substrate:越狱生态的元老级框架

Substrate(Cydia Substrate)是越狱 tweak 的"地基",绝大多数 Cydia 插件都建立在它之上。它提供MSHookFunction钩 C 函数、MSHookMessageEx钩 ObjC 方法,并配套一批便捷宏和实例变量访问工具。值得一提的是,substitute 内置了一个兼容层substrate/substrate.h,让你原本写 Substrate 的代码几乎不改就能跑在 substitute 上,迁移成本极低。

fishhook:轻量级动态符号重绑定工具

fishhook 只做一件事:把某个动态库引用的符号,重新绑定到你的实现(例如把mallocread替换成自定义版本)。它只改 GOT/PLT 表、不碰函数代码,因此体积小巧、上手极快,特别适合做"底层函数透明替换"。


二、原理对比:它们到底"劫持"了什么 🎯

三款工具的差异,根源在于"劫持点"不同。理解了这一点,选型就不再靠感觉:

机制代表工作方式副作用
内联代码补丁substitute、Substrate改写函数入口指令 + 跳板转发需要可写可执行内存
GOT/PLT 重绑定fishhook、substitute 的 interpose修改符号表指向不改代码,但只覆盖动态符号
ObjC 运行时Substrate、substitute替换方法 IMP仅限 ObjC 方法,不碰 C 函数

简单说:内联补丁能力最强但"动刀"最深;符号重绑定最温和、可沙盒化;ObjC 运行时最省心,但只能钩到 Objective-C 方法。


三、关键维度横向对比 📊

维度substituteSubstratefishhook
可劫持范围任意 C/C++ 函数 + ObjC 方法C 函数 + ObjC 方法 + 实例变量动态库引用的 C 符号
是否改写可执行代码是(interpose 除外)
沙盒 / 非越狱 iOSinterpose 技术可用需越狱受只读 GOT 限制
线程安全强(主线程 + 暂停线程)较弱较强
架构支持ARM / ARM64 / x86多架构ARM / x86_64 为主
是否依赖越狱
上手难度中等低(宏丰富)
维护状态已停更(建议用 fork)官方停更稳定但较老

四、按场景选型:我该用哪一个?✅

  • 想 hook 任意 C/C++ 函数,且要线程安全→ 选substitute,它的substitute_hook_functions会暂停其他线程、原子地完成补丁,还能回传旧实现指针,是最"全能"的方案。
  • 维护老项目 / 越狱 tweak,代码已经用MSHookFunction→ 选Substrate,或直接用 substitute 的兼容层substrate/substrate.h平滑替换底层。
  • 只想替换少数几个 C 函数(如日志、内存分配)→ 选fishhook,代码量最小、最不易出错。
  • 钩 Objective-C 方法 / 重写类行为→ 三者皆可,substitute 的substitute_hook_objc_message和 Substrate 的MSHookMessageEx都能胜任,且都比手写 ObjC 运行时代码干净。
  • 要在沙盒(App Store 合规)内做拦截→ 优先看 substitute 的substitute_interpose_imports或 fishhook,二者都不依赖改写可执行内存。

五、新手避坑指南 ⚠️

  1. 注意维护状态:substitute 上游已标注"Unmaintained",生产使用建议寻找活跃维护的 fork 版本;Substrate 官方也已停更。选型时把"谁在维护"也纳入考量。
  2. 主线程限制:substitute 的函数钩子要求在主线程调用(它会暂停其他线程以避免竞态),非主线程调用会直接返回错误码,可用substitute_strerror把错误码转成可读字符串定位问题。
  3. 别 hook 太短的函数:当函数开头的可补丁区域内就出现无条件返回等"危险指令"时,内联补丁会失败——这正是 substitute 提供substitute_interpose_imports这类替代方案的价值所在。
  4. fishhook 的边界:它只重绑定动态符号,改不了内联调用、静态链接代码,以及在较新 iOS 上只读的 dyld shared cache 里的系统符号。
  5. 别混用非原子运行时修改:substitute 的文档明确提示,它与 Substrate 这类"非原子替换方法"的实现并存时可能产生竞态,同一进程内尽量统一一套 Hook 方案。

六、substitute 核心 API 速查 🔧

全部接口定义在lib/substitute.h,最常用的几个:

  • substitute_hook_functions— 内联函数钩子(主线程调用,线程安全,返回旧实现指针)
  • substitute_interpose_imports— GOT/PLT 符号拦截(不改代码、原子操作,技术层面可沙盒)
  • substitute_hook_objc_message— ObjC 方法钩子(基于原子的class_replaceMethod
  • substitute_open_image/substitute_find_private_syms— 查找已加载镜像中的(私有)符号地址
  • substitute_strerror— 把SUBSTITUTE_ERR_*错误码转成可读字符串

结语

一句话总结:要全能和线程安全选 substitute,要越狱生态与低迁移成本选 Substrate,要轻量替换少数 C 符号选 fishhook。三者并非互斥——理解"内联补丁 / 符号重绑定 / ObjC 运行时"这三种劫持机制,你就能根据目标函数的类型、运行环境(是否越狱、是否沙盒)和线程要求,做出最合适的选择。

【免费下载链接】substituteA free runtime modification library.项目地址: https://gitcode.com/gh_mirrors/su/substitute

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询