CVE-2025-24200 的关键不在弹窗长什么样,而在锁定状态下,谁有权改变 USB 配件策略。iOS 18.3.1 的修复同时涉及辅助功能界面与后台设置服务:前者决定是否呈现交互,后者决定设置是否真正写入。
Apple 于 2025-02-10 发布修复,将问题归类为授权与状态管理错误,并将报告归功于 Bill Marczak。下面以 iOS 18.3 / 18.3.1 的补丁线索为主,单独标明 iOS 16.7.10 的调试观察;公开差异报告、布尔模型和实物验证分别回答不同问题。Apple 安全公告
限制数据连接,不等于关闭整个接口
USB 限制模式约束的是数据连接。Apple 的安全说明描述了锁定或配件数据连接终止后一小时的边界,也区分已识别配件、陌生配件和要求重新输入口令的状态。因此,“一小时后限制新数据连接”是有上下文的规则,并非所有设备状态下唯一的计时器。Apple 数据连接安全
恢复配件数据通道与绕过口令、解密用户数据是三件事。漏洞公告支持的是锁定设备上的 USB 限制模式可能被物理攻击关闭,后续取证或数据读取仍有各自前提。

界面示意图:左侧强调解锁要求,右侧提示 Switch Control 配件可能改变锁屏期间的连接策略。两种界面并列用于说明语义差异,不表示一次连续实验或实物攻击已经完成。
先固定构建,再比较控制流
| 用途 | 设备 | 系统与构建 |
|---|---|---|
| 补丁定位记录 | iPhone14,4 | iOS 18.3(22D63)与 18.3.1(22D72) |
| 主动方法调用记录 | iPhone10,3,iPhone X | iOS 16.7.10(20H350) |
准备样本时,应固定型号、架构切片、组件路径和分析器配置;同时记录 Mach-O UUID 与文件摘要。同名函数的地址不是跨构建常量,函数数量或基本块增量也不是漏洞归因本身。
基本块筛选还有一个容易忽略的问题:用函数名作为字典唯一键,会让同名项互相覆盖。更稳妥的做法是先保留全部候选,再只比较两侧均唯一的名称。下面的函数接收 (name, basic_block_count) 序列;Binary Ninja 的采集端可从完成分析的视图中读取 function.name 与 len(function.basic_blocks)。
from collections import defaultdict
def compare_unique(before, after):
def collect(rows):
out = defaultdict(list)
for name, count in rows:
if not name.startswith("sub_"):
out[name].append(count)
return out
old, new = collect(before), collect(after)
changed, ambiguous = [], []
for name in sorted(old.keys() & new.keys()):
if len(old[name]) != 1 or len(new[name]) != 1:
ambiguous.append(name)
continue
a, b = old[name][0], new[name][0]
if a != b:
changed.append((name, a, b))
return changed, ambiguous该规则仍会遗漏改名、无符号、内联和错误识别的函数。它是候选排序器,不是补丁语义判定器;本地测试使用合成记录,没有重新加载两套固件进行 Binary Ninja 分析。
两处变化分别保护交互和写入
补丁定位记录给出了两个值得检查的入口:
| 组件 | 方法 | 基本块增量 |
|---|---|---|
| AXSpringBoardServerInstance | -[AXSpringBoardServerHelper _handleDisallowUSBRestrictedModeSCInformativeOnly:] |
+4 |
| profiled | -[MCProfileServicer setParametersForSettingsByType:configurationUUID:toSystem:user:passcode:credentialSet:completion:] |
+6 |
这些增量保留为特定分析记录,未重新从完整二进制计算。独立核对 ipsw 项目的构建差异报告,还能看到两条更直接的字符串变化:
第一条出现在 AXSpringBoardServerInstance,第二条出现在 profiled,后者还新增 _MCSettingsErrorDomain 符号。这些事实与“界面检查 + 写入检查”的解释吻合,但字符串存在本身没有还原全部控制流。该报告是工具项目产物,不是 Apple 源码。ipsw 构建差异
界面方法在显示提示前检查解锁状态,标题键为 sc.disallow.usb.restricted.mode.alert.title。单个 OK 按钮和 InformativeOnly 命名说明这里偏向通知,但仅凭命名仍不足以确定所有副作用。追踪最终设置写入才是决定性一步。
后台条件应写成明确的真值表
profiled 的恢复逻辑在原有权限检查后,读取 RestrictedBool 中与 FeatureUSBRestrictedModeAllowed 有关的值,并查询 isDeviceLocked。将对象读取与布尔转换暂时抽象掉,记录中的新增分支可表达为:
def write_allowed(base_permission, setting_value, locked):
return base_permission and (not setting_value or not locked)| setting_value | locked | 模型分支 |
|---|---|---|
| false | false | 调用内部设置接口 |
| false | true | 调用内部设置接口 |
| true | false | 调用内部设置接口 |
| true | true | 返回错误 0x6d66 |
这里的 setting_value 是恢复条件的输入,不是根据 Allowed 英文名称推测出的产品开关含义。缺键、对象类型不符、boolValue 转换和内部设置接口的实际解释仍需逐项追踪。此模型不是可直接替换系统实现的 Objective-C 源码。
flowchart TD
A["收到设置请求"] --> B{"原有权限检查通过?"}
B -->|否| C["保留原错误路径"]
B -->|是| D["解析目标设置与锁定状态"]
D --> E{"值为假,或设备已解锁?"}
E -->|是| F["内部设置写入"]
E -->|否| G["错误 0x6d66 / completion"]
把检查放到后台写入入口,能覆盖不经过同一个弹窗的调用者。另一方面,一次状态查询尚未证明“检查到写入”之间具备原子性;这里只解释观察到的补丁边界,没有据此宣称存在新的竞态漏洞。
通知回调连接到 assistivetouchd
相关守护进程位于 /System/Library/CoreServices/AssistiveTouch.app/assistivetouchd。沿 SCATScannerManager 的交叉引用,可以串起以下关系:
flowchart TD A["配件事件进入 handleUSBMFiDeviceConnected"] --> B["检查已提示、已禁用和当前需求状态"] B --> C["更新提示标志并请求显示通知"] C --> D["OK 回调"] D --> E["_setUSBRMPreferenceDisabled"] E --> F["profiled 设置入口"]
完整方法名是 -[SCATScannerManager handleUSBMFiDeviceConnected] 与 -[SCATScannerManager _setUSBRMPreferenceDisabled]。调用关系解释了通知为何可能关联敏感设置,却未证明任意 USB 配件都能自然产生入口事件。
AssistiveTouch 与 Switch Control 是不同的辅助功能。守护进程名称、浮动菜单和 SCAT 类名可以出现在同一调查中,但不应把“开启 AssistiveTouch”直接写成“已经满足 Switch Control 配件路径的全部条件”。
主动调用只验证到达性
iPhone X 的调试记录使用 -[HNDRocker _shakePressed] 作为可触发的地址锚点,并主动进入目标处理方法。记录显示相应通知出现;这支持界面到达性,不足以单独确认策略持久化或限制状态下的数据通道已经恢复。
同一映像、同一装载偏移下,地址换算成立:
target_runtime = anchor_runtime + (target_static - anchor_static)记录中的两处静态地址是 0x100042858 和 0x1000ad1c8,距离为 0x6a970,即 436592 字节。仅有这两个数值不指定哪一个是目标或锚点;先确认各自符号与指令位置,再决定差值正负。也不要把 iOS 16 的差值移植到 iOS 18。
Objective-C 实例方法的 IMP 通常还接收 self 与 _cmd。复现时应核对实例有效性、选择子、参数与返回类型、线程要求及当前实现地址。Frida 的方法包装器与 Objective-C 运行时信息可辅助核验;一个无参数原生函数包装器加上“弹窗出现”,不足以证明调用约定正确。Frida Objective-C API
离线检查覆盖名称冲突处理、全部三变量布尔组合,以及两种地址方向与四种装载偏移:
PASS: 8 unique-name matching cases; 8 Boolean states; 8 relocation cases
Static address distance: 0x6a970 (436592 bytes)
No device methods called; no USB policy changed这些是本地 Python 模型结果,不是新一轮设备实验。布尔模型只验证分支表达式;地址模型只验证共同装载偏移抵消。
外设假设仍需闭合实际证据链
AbleNet 的 Hook+ 设置文档确认了 Lightning 连接与 Switch Control 的关系,以及接入 1–4 个开关的配置方式。旧版产品说明图中的接口信息可以用结构化表格表达,而不必保留整页产品截图。AbleNet 官方设置说明
| 部件 | 作用 |
|---|---|
| Lightning 连接头 | 连接 iOS 设备 |
| 1–4 号开关插孔 | 接入 3.5 mm 单声道 TS 开关 |
| Micro USB 接口 | 外部充电连接;不等同于任意 USB 主机通道 |
这些连接事实支持调查方向,未确认 Hook+ 就是完整触发设备。MFi 认证、功能启用状态、配件事件传输、用户交互、锁定时长和系统构建都可能影响结果。分析记录未包含相关硬件的端到端测试。
应分别记录自然配件事件是否到达、通知是否显示、后台请求是否成功、设置是否变化,以及新的数据连接是否成立。最后一项也与用户数据解密分开验证。对读者的直接结论是:以 Apple 针对设备提供的修复版本为基线,检查后台的状态变更约束,而不是用一个弹窗或一根线缆替代整个证据链。