iOS 真机 JS 注入 · 第 2 课

三条死胡同:撞墙不可怕,可怕的是不知道墙分两种

带着第 1 课那张五层地图,我去敲三扇最常见的门:iwdpwebinspector cdpinspector_session。三扇全是死的。但它们死的原因分成两类——分清这两类, 就等于把"接下来该找什么样的工具"这道题从大海捞针缩小成了一句话。

为什么先讲失败?

因为呈现一个调试结论时,"我一上来就找到了正确方案"是不可信的;"我试了 A、B、C,各自死在哪、于是排除了什么"才是可信的。 失败不是流水账,是逐步缩小搜索范围的过程。下面每一扇门,我都用第 1 课的层号标出它死在哪一层。

死胡同一:iwdp —— 建在一扇已经被拆掉的门上

iwdp ios-webkit-debug-proxy 是很多人第一反应会用的经典工具: 它把 iPhone 的网页调试能力"翻译"成 Chrome 开发者工具能连的形式。教程满天飞,理应最稳。

现象 & 定位

直接连不上,死在第 2 层。原因正是第 1 课那个总根源:iwdp 依赖的是 老的 lockdownd 那扇门。iOS 17 起苹果把门换成了 RemoteXPC,iwdp 没跟上—— 它敲的那扇门物理上已经不存在了

👉 这类失败的本质:「架构变了,老工具没跟上」。不是你用错了,是工具本身在新系统上作废了。

死胡同二:webinspector cdp —— 敲对了门,却被自己绊倒

pymobiledevice3 webinspector cdp 是我们主力工具自带的命令,思路对:它面向 iOS 17 的新世界, 想把网页调试暴露成标准的 CDP Chrome DevTools Protocol 接口给你连。

现象 & 定位

命令起不来,卡在工具自身的 asyncio(Python 异步框架)报错上。 这次不是架构的问题——门是对的,是工具这段代码本身有 bug,还没打磨好。

👉 这类失败的本质:「新工具还不成熟」。方向没错,实现有坑。这和第一类是完全不同的墙—— 第一类要换工具,第二类可能只要换命令、换版本、绕开那段坏代码。

死胡同三:inspector_session —— 需要先修隧道,人却卡在半路

inspector_session(走开发者隧道 tunneld 的那套会话)在原理上是最"正统"的: 它按第 1 课说的规矩,先建 IPv6 隧道、过 RSD,再开调试会话。

现象 & 定位

会话挂住、拉不起来,卡在第 2~3 层的隧道/会话建立环节。 正统路要求那条隧道全程稳、RSD 全程配合;真机环境里它没能稳定拉起来(隧道/守护进程争用等),于是整条会话就吊在那。

👉 仍属第二类偏环境:「路子对,但链路太重、太脆」。步骤越多、依赖越重,真机上越容易某一环掉链子。

把三次失败收敛成一句话

这才是这一课真正的产出——一张"死因分类表":

A
架构变了,老工具没跟上 iwdp。iOS 17 换了门,工具作废。→ 对策:换工具,别在老门上耗。
B
新工具还不成熟 / 链路太重 cdp(自身 bug)、inspector_session(隧道会话太脆)。方向对、实现或链路掉链子。→ 对策:找同方向里更轻、更稳的那条命令

于是"接下来找什么"就从模糊变清晰了:我要的,是一个既面向 iOS 17 新世界(排除 A)、 又足够轻量稳定、不依赖那条脆隧道会话(避开 B)的执行 JS 的口子。——这句话,直接把第 3 课的主角 js-shell --userspace 给"框"出来了。

接下来

第 3 课:登场的 js-shell --userspace 为什么正好满足这两个条件—— --userspace(用户态隧道)如何绕开"要 root、要重隧道"的负担,以及它靠 WebKit Inspector Protocol 把 JS 送进第 5 层。

📖 参考来源pymobiledevice3 Discussion #450 — How to work with webinspector?, 社区里对这些命令各自适用场景的真实讨论,写文档时是很好的旁证。


第 2 课 / 共 6 课 · 课程:iOS 真机 JS 注入