~/posts/mobile/cve-2025-24200-usb-lock-state-authorization.md

CVE-2025-24200:USB 策略与锁定状态

分开核对辅助功能提示与后台设置写入,结合构建差异、布尔分支和地址模型,明确补丁证据、调试观察与外设触发假设的边界。

date[31:24]
read[23:16]
7 分钟
cat[15:8]
移动端
tags[7:0]
目录
  1. 0x00限制数据连接,不等于关闭整个接口
  2. 0x01先固定构建,再比较控制流
  3. 0x02两处变化分别保护交互和写入
  4. 0x03后台条件应写成明确的真值表
  5. 0x04通知回调连接到 assistivetouchd
  6. 0x05主动调用只验证到达性
  7. 0x06外设假设仍需闭合实际证据链
  8. 0x07官方参考

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 配件通知的并列界面示意图

界面示意图:左侧强调解锁要求,右侧提示 Switch Control 配件可能改变锁屏期间的连接策略。两种界面并列用于说明语义差异,不表示一次连续实验或实物攻击已经完成。

先固定构建,再比较控制流

两组证据对应不同设备与系统2 行
用途 设备 系统与构建
补丁定位记录 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)。

唯一名称匹配python
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 分析。

两处变化分别保护交互和写入

补丁定位记录给出了两个值得检查的入口:

函数级差异线索2 行
组件 方法 基本块增量
AXSpringBoardServerInstance -[AXSpringBoardServerHelper _handleDisallowUSBRestrictedModeSCInformativeOnly:] +4
profiled -[MCProfileServicer setParametersForSettingsByType:configurationUUID:toSystem:user:passcode:credentialSet:completion:] +6

这些增量保留为特定分析记录,未重新从完整二进制计算。独立核对 ipsw 项目的构建差异报告,还能看到两条更直接的字符串变化:

构建差异中的新增字符串+2 −0
Not showing USB restricted mode alert because device is locked
SETTINGS_DEVICE_IS_LOCKED_P_SETTING

第一条出现在 AXSpringBoardServerInstance,第二条出现在 profiled,后者还新增 _MCSettingsErrorDomain 符号。这些事实与“界面检查 + 写入检查”的解释吻合,但字符串存在本身没有还原全部控制流。该报告是工具项目产物,不是 Apple 源码。ipsw 构建差异

界面方法在显示提示前检查解锁状态,标题键为 sc.disallow.usb.restricted.mode.alert.title。单个 OK 按钮和 InformativeOnly 命名说明这里偏向通知,但仅凭命名仍不足以确定所有副作用。追踪最终设置写入才是决定性一步。

后台条件应写成明确的真值表

profiled 的恢复逻辑在原有权限检查后,读取 RestrictedBool 中与 FeatureUSBRestrictedModeAllowed 有关的值,并查询 isDeviceLocked。将对象读取与布尔转换暂时抽象掉,记录中的新增分支可表达为:

设置入口的布尔模型python
def write_allowed(base_permission, setting_value, locked):
    return base_permission and (not setting_value or not locked)
原有权限检查已通过时4 行
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] 作为可触发的地址锚点,并主动进入目标处理方法。记录显示相应通知出现;这支持界面到达性,不足以单独确认策略持久化或限制状态下的数据通道已经恢复。

同一映像、同一装载偏移下,地址换算成立:

同一映像内的地址关系text
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

离线检查覆盖名称冲突处理、全部三变量布尔组合,以及两种地址方向与四种装载偏移:

离线检查结果log
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 官方设置说明

产品说明中的物理接口3 行
部件 作用
Lightning 连接头 连接 iOS 设备
1–4 号开关插孔 接入 3.5 mm 单声道 TS 开关
Micro USB 接口 外部充电连接;不等同于任意 USB 主机通道

这些连接事实支持调查方向,未确认 Hook+ 就是完整触发设备。MFi 认证、功能启用状态、配件事件传输、用户交互、锁定时长和系统构建都可能影响结果。分析记录未包含相关硬件的端到端测试。

应分别记录自然配件事件是否到达、通知是否显示、后台请求是否成功、设置是否变化,以及新的数据连接是否成立。最后一项也与用户数据解密分开验证。对读者的直接结论是:以 Apple 针对设备提供的修复版本为基线,检查后台的状态变更约束,而不是用一个弹窗或一根线缆替代整个证据链。

官方参考

NORMAL~/posts/mobile/cve-2025-24200-usb-lock-state-authorization.md§--
0%zh-CN