edit | blame | history | raw

Bilibili 已登录会话完整视频扩展入口安全设计 V002

1. 修订范围与组合基线

  • 事项:DEV-PROJECT-INFO-BILI-AUTHENTICATED-SESSION-DOWNLOAD-20260805-001
  • 上游需求:REQ-BILI-DYNAMIC-COLLECTOR-20260804-001
  • 唯一目标:青枫浦上Q / BV1HA3o6oEJJ
  • 前序设计:CODE-DESIGN-PROJECT-INFO-BILI-AUTHENTICATED-SESSION-EXTENSION-INGRESS-V001.md=22418/665DDDFE4247DEFEE69B6DD1E0CBBD128EDD75B8A32BA609C90C718AC7C97C71
  • 前序审核:DEV-AUDIT-PROJECT-INFO-BILI-AUTHENTICATED-SESSION-EXTENSION-INGRESS-V001-DESIGN-20260805-001 / HOLD/4
  • 本修订只闭环前序 F1—F4。V001 已通过的 exact BVID、二次用户点击、无通用下载、无外部消息/loopback/token 文件、内存 Cookie、页面/DRM/multi-P/live/preview 门禁、冻结 accept-browser-file 和 offline-only 边界全部保留。
  • V001 与 V002 组成唯一设计合同;冲突处以 V002 为准。V002 独立复审 PASS 前,禁止创建产品实现、测试、扩展、Native Host、构建/安装脚本,禁止任何真实认证、Chrome、下载、注册表、媒体或正式路径动作。

2. F1:固定扩展身份与 exact wire schema

2.1 固定 public identity

项目扩展身份不再由安装器接收任意合法格式 ID。V002 固定以下值:

  • Native Host 名:com.project_info.bili_auth_ingress
  • 协议版本:2
  • extension build identity:project-info-bili-auth-ingress/1.0.0+20260805.v002
  • host build identity:project-info-bili-auth-native-host/1.0.0+20260805.v002
  • manifest public key DER SHA-256:E83C2B2AF3CF011543FBA13FBC524D1122EEA68548F9F27B9F7A82B5D594666C
  • expected extension ID:oidmclckpdmpabbfedplkbdplmfcenbb
  • exact origin:chrome-extension://oidmclckpdmpabbfedplkbdplmfcenbb/

manifest 固定 key

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt2dT1HGYaI0DXM7zZwOTNBWXTKlMBJMpyDVjRUc+v6bUotmLyoraC+ay2scy9UQluSZVYq0tS8qvQNNvuZOlc5w2bOExm4TH2IIKvaVO8nVthHBnNz2kXdiM8ItN0vPZEmS+8gpTCI1+6wPTuUglMoXpqYBYhii8fJ5RkENRF3PRJBBigGt8soqdBFRY1QZUmpQv9dYw4dRq4L2C4QtBgClUg4bQpuCppiVZ9LHbePi9IAjc9r9R93KLzpaBuXdJpfVRE5w/6YHnxP8ovXxBdl7XktmrdH3xj7mWT7Q7ZBxkDNwn2RkruD45XgDD3yuNxOYSkLFMkseN+Ua69gSS4wIDAQAB

该 public key 由一次内存 RSA 生成,仅保留 public SPKI;private material 未写文件、未记录且已释放。Chrome ID 按 public DER SHA-256 前 128 bit 的 nibble a..p 映射复算,必须得到上述 expected ID。

安装器只允许操作者提供 Chrome UI 观察到的 ObservedExtensionId,并执行比较,不用它生成身份:

  1. 读取项目 manifest 的 key,复算 DER hash 与 extension ID;两者必须等于冻结值。
  2. ObservedExtensionId 必须逐字等于 pinned ID;不接受其他 32 位 ID、通配符或第二 origin。
  3. Native Host manifest 的 allowed_origins 必须是只含 exact origin 的单元素数组。
  4. 安装器核对 extension/host build identity 和实现审核冻结 artifact manifest hashes 后才写 HKCU;任何差异在注册表动作前失败。

Native Host 启动时把 Chrome 传入的首个 origin argv 与 exact origin 常量逐字比较;只允许额外的 Chrome --parent-window=<decimal> 参数,其他参数失败。origin 失败时在读取 native stdin、创建 worker、读取秘密或触发文件/网络前退出。扩展和 host 先交换 build identity;任一方不一致不得发送 Cookie。

2.2 Native frame 与 JSON 共用规则

  • Chrome 到 host 的帧上限=131072 bytes;host 到 Chrome 的帧上限=16384 bytes
  • UTF-8 必须严格解码;JSON 必须是 object;使用 duplicate-key rejecting decoder;禁止 NaN/Infinity。
  • 所有 object 使用逐层 exact key set,未知、缺失或重复字段均失败。
  • 字符串禁止 NUL、TAB、CR、LF 和 Unicode 控制字符;所有计数和时间使用 JSON integer,禁止 bool 冒充 integer。
  • schema 必须为 integer 2target 必须为 BV1HA3o6oEJJcanonical_url 必须为 https://www.bilibili.com/video/BV1HA3o6oEJJ
  • startcookies[].value 外,任何协议响应、状态或错误均不得含秘密或第三方文本。

2.3 handshake/status/cancel schema

扩展连接后必须先发送:

{
  "schema": 2,
  "type": "hello",
  "extension_build": "project-info-bili-auth-ingress/1.0.0+20260805.v002",
  "target": "BV1HA3o6oEJJ"
}

host 只返回固定 host_buildphasetarget。随后只允许:

{"schema":2,"type":"status","target":"BV1HA3o6oEJJ"}
{"schema":2,"type":"cancel","target":"BV1HA3o6oEJJ","task_nonce":"<32 lowercase hex>"}

task_nonce 由 background 在页面校验前用 CSPRNG 生成 16 bytes,仅用于绑定本次用户点击和取消,不是认证秘密;长度和字符集固定。过期、非当前 nonce 或任务已终态的 cancel 不产生外部动作。

2.4 page proof schema

page_proof exact keys、类型与范围:

字段 类型与范围 规则
target string exact BVID
canonical_url string exact canonical URL
task_nonce string 32 lowercase hex,与 start/cancel 一致
observed_at_unix_ms integer 0 < value < 2^53;host 接收时不早于 60 s、不晚于 host 时钟 5 s
observed_duration_ms integer 3133950 差值不超过 3134 ms
video_width integer 1..7680
video_height integer 1..4320
ready_state integer 1..4
eme_present boolean 必须 false

background 只投影上述原始标量,不传 DOM、文本、HTML、媒体对象、URL 列表或页面异常。页面 hostname/path 校验、可见 52:14/充电中 提示及 V001 门禁不变。

2.5 start schema

start exact keys:

{
  "schema": 2,
  "type": "start",
  "extension_build": "project-info-bili-auth-ingress/1.0.0+20260805.v002",
  "target": "BV1HA3o6oEJJ",
  "canonical_url": "https://www.bilibili.com/video/BV1HA3o6oEJJ",
  "cookie_store_id": "0",
  "page_proof": {},
  "cookies": []
}
  • cookie_store_id 为 ASCII [0-9]{1,8}。background 调用 chrome.cookies.getAllCookieStores(),要求 active tab ID 恰好属于一个 store;使用该 store ID 读取/投影 Cookie,所有 record 必须同值。
  • cookies 数量=1..128;整个 start frame 不超过 131072 bytes
  • 原始 Chrome Cookie object 不得直接 stringify;background 逐字段创建下节 record。
  • host 在 worker 发出 READY_PLUGIN_DISABLED 前不把 start 的 secret 部分写入 worker。

2.6 cookie record schema 与 Netscape 转换

每个 record exact keys:

{
  "name": "synthetic-name",
  "value": "synthetic-value",
  "domain": ".bilibili.com",
  "host_only": false,
  "path": "/",
  "secure": true,
  "http_only": true,
  "same_site": "unspecified",
  "session": true,
  "expiration_unix": null,
  "store_id": "0",
  "partition_key": null
}

字段规则:

  • name=1..256 UTF-8 bytesvalue=1..4096 UTF-8 bytes;均禁止 NUL/TAB/CR/LF/control。禁止空值 record。
  • domain 只允许:host_only=true 时 exact www.bilibili.comhost_only=false 时 exact .bilibili.com。大小写、尾点、IDN、其他子域和其他站点均拒绝。
  • path=1..1024 UTF-8 bytes,必须以 / 开始、无控制字符,且必须是 canonical target path /video/BV1HA3o6oEJJ 的 RFC cookie-path prefix;不做文件路径解析。
  • secure/http_only/session 必须是 boolean。
  • same_site 仅允许 no_restriction|lax|strict|unspecified
  • store_id 必须逐字等于 top-level cookie_store_id
  • partition_key 必须显式为 null。Chrome 返回任何 partitioned cookie 时 fail-closed;不把分区 Cookie 降级为非分区 Cookie。
  • session=trueexpiration_unix 必须为 null;转换为 Netscape expiry 0
  • session=falseexpiration_unix 必须是 1..2^53-1 integer,且大于 page proof 秒级时间;转换为相同整数。过期、float、bool、二者不一致均拒绝。

Netscape text 只在 worker 内的 io.StringIO 形成:header 固定;domain column 使用 canonical domain,http_only=true 时只在内存中加 #HttpOnly_ 前缀;include-subdomains=FALSE iff host_only,否则 TRUE;path/secure/expiry/name/value 按上述已验证值写 TAB 分隔行。转换后禁止任何文件名、Cookie 临时文件或 browser profile 入口。

3. F2:真实禁用插件与隔离第三方输出

3.1 broker/worker 进程隔离

V001 的单进程 host 改为最小 broker/worker 两进程:

  • broker 只使用 Python stdlib/Win32 ctypes,负责 Native Messaging、origin/build/schema、任务状态、Job Object 和固定 bridge 调度;绝不 import yt-dlp。
  • worker 是同一冻结 host executable 的 --worker 模式。argv 只含非秘密 mode 与继承 handle 数字;start JSON/Cookie 经专用匿名 stdin pipe 传入,不进入 argv/env。
  • broker 在启动早期复制 Chrome protocol stdout 的二进制 OS handle并设为 non-inheritable;随后把 broker 的 fd 1/fd 2 和 worker 的 stdout/stderr 全部指向 Windows NUL。只有 broker 的 protocol writer 能写复制 handle。
  • worker 的安全状态通过另一条只承载固定 schema/数值的匿名 control pipe返回;该 pipe 不发送第三方字符串、路径、URL、headers 或 Cookie。

因此 yt-dlp CookieJar 的 direct write_string、Python warning、真实包 stdout/stderr、FFmpeg stdout/stderr 和 traceback 都只能进入不持久化 NUL sink,不能污染 Chrome 协议 stdout,也不形成日志文件。

3.2 import 前禁用插件

worker 的启动顺序固定:

  1. 只 import stdlib;把 fd 1/fd 2 指向 NUL
  2. 在进程环境设置 YTDLP_NO_PLUGINS=1,该环境不含任何 Cookie/token/URL。
  3. 才允许 import yt_dlp
  4. 立即设置 yt_dlp.globals.plugin_dirs.value=[];调用冻结插件初始化后断言:plugin_dirs.value==[]plugins.directories()==[]plugin_ies.value=={}plugin_pps.value=={}plugin_ies_overrides.value 为空。
  5. 任一断言失败则从 control pipe 发送 E_PLUGIN_BOUNDARY 并退出;broker 不发送 start secret。
  6. 只有全部通过后发送 READY_PLUGIN_DISABLED,broker 才把 start payload 写入 worker stdin。

这同时阻断默认 plugin_dirs=['default']、旧兼容插件目录和用户插件在秘密进入进程后执行。实现固定 yt-dlp 2026.07.04 包 hash 清单;版本或相关模块 hash 漂移须重新实现审核。

3.3 真实包无网络 sentinel 门禁

实现审核前用冻结真实包而非仅 fake logger 执行:

  • 在临时默认插件目录放一个若加载即写 sentinel/marker 的 synthetic plugin;worker 设置禁用机制并真实创建 YoutubeDL,断言 marker 不出现且 plugin maps/directories 为空。
  • 用真实 YoutubeDLCookieJario.StringIO 分别加载合法和畸形 synthetic Cookie,触发正常、解析 warning、close/save 路径;sentinel 不得进入 broker protocol、父 stdout/stderr、临时树、配置、异常或证据。
  • 网络 request director 被测试桩设为“调用即失败”,证明这些测试网络=0;真实 yt-dlp 初始化、CookieJar 和输出路径仍被执行。
  • 启动真实 sleeping ffmpeg helper,把 sentinel 写 stdout/stderr/异常后退出;broker protocol 只可收到固定错误码,磁盘日志为 0。
  • 逐字节扫描 protocol frames、所有父子 stdout/stderr 捕获、argv/env、临时树和 evidence;Cookie/token/signed URL/header/exception sentinel 出现次数必须为 0。

4. F3:一次解析、同一下载对象和 downloader/FFmpeg 门禁

4.1 唯一解析状态机

同一个冻结 YoutubeDL 实例只执行一次:

processed_info = ydl.extract_info(CANONICAL_URL, download=False, process=True)

随后:

  1. processed_info 执行 exact id、single video、duration、live、multi-P、DRM、AV、availability 和 format 基线门禁。
  2. 使用冻结 2026.07.04 实例的 _get_formatsbuild_format_selector("bestvideo+bestaudio/best")_select_formats 取得唯一 selected format;数量不为 1 即失败。
  3. 按冻结库自身路径生成一次 download_info = ydl._copy_infodict(processed_info); download_info.update(selected_format)
  4. 对这个 exact download_info 及其 requested_formats 逐叶验证下节合同。
  5. 验证后把 ydl.extract_info 替换为“调用即 E_SECOND_EXTRACT” guard,再把同一个 download_info object 直接交给 ydl.process_info(download_info)

禁止调用 ydl.download(url)、第二次 extract_info、按 URL 的 process_ie_result 或重新取得 metadata/formats。测试记录 extractor invocation count 必须恒等于 1,并证明被验证 object identity 与交给 process_info 的 object identity 相同。

4.2 requested format 与实际 downloader allowlist

逐个实际叶 format 校验:

  • requested_formats 存在,必须恰好 2 个:一个 vcodec!=none/acodec=none,一个 vcodec=none/acodec!=none;顶层必须同时有 AV 合并语义。
  • 若不存在,单叶必须同时 vcodec!=noneacodec!=none,进入 4.4 单文件 remux。
  • 每个叶 has_drm 必须 false/absent;URL scheme 必须 https;protocol 只允许 httpshttp_dash_segments
  • 用冻结真实 get_suitable_downloader(leaf, ydl.params) 计算实际 class;只允许 exact HttpFDDashSegmentsFD
  • FFmpegFDHlsFD、任何 ExternalFD、m3u8/m3u8_native/rtmp/rtsp/mms/ism、未知协议、多个 manifest、缺失 URL 或额外 subtitle/data format 全部在首个媒体字节前失败。
  • fragment_retries、HTTP headers 和签名 fragment URL只由 worker 内置 downloader 消费;不导出、不转成任何子进程 argv。

4.3 子进程 argv 审计门

worker 在 yt-dlp import 后、任何子进程前注册 Python audit hook,拦截所有 subprocess.Popen

  • executable 必须逐字等于安装配置中 pinned FFmpeg 或固定 host/bridge executable;其他 child 失败。
  • argv 中禁止含 ://-headers-cookiesauthorizationcookie:referer:user-agent:,禁止含本任务任一 Cookie value/name、signed URL/header synthetic/real value。
  • FFmpeg 的所有 -i 值和输出必须是固定 run directory 下通过重解析点检查的本地普通文件;禁止 pipe/network/protocol input。
  • child environment 使用固定 allowlist,禁止 Cookie/token/URL/header;stdout/stderr=NUL;child 必须属于第 5 节 Job Object。

audit hook 在 CreateProcess 前抛出安全异常,因此禁止值不得短暂出现在 Windows process command line。真实 dispatcher 测试要求 https -> HttpFDhttp_dash_segments -> DashSegmentsFD PASS,m3u8 -> FFmpegFD 被产品门禁拒绝且实际 FFmpeg spawn=0。

4.4 最终唯一 MKV

  • 双叶 DASH 路径:merge_output_format="mkv",yt-dlp 只在两份本地文件完成后调用 FFmpeg stream-copy merger;argv 必须通过 4.3。
  • 单文件 best fallback:下载器只产生本地完整 AV 文件;host 不把原容器视为最终结果,使用 pinned FFmpeg 固定本地命令 -nostdin -i <local> -map 0:v:0 -map 0:a:0 -c copy -map_metadata -1 -f matroska <exclusive-stage>.mkv。remux、AV 或 MKV 验证失败即清理并 fail-closed。
  • 两种路径最终都必须只剩一个 .mkv;原单文件或双流中间件在 MKV 验证成功后删除。任何其他媒体候选、未知 sidecar 或 partial 残留失败。

离线合成门禁使用真实 FFmpeg 生成短 AV fixture,分别覆盖双叶合并和单叶 remux;验证 MKV、音视频、无转码语义、唯一候选、argv 全为本地路径。无需网络或业务媒体。

5. F4:有界并发、超时与 Windows Job Object

5.1 broker reader/coordinator/worker

  • broker 的 reader thread 持续读取 Chrome stdin;它不等待下载,可立即消费 status/cancel。EOF、坏帧、origin/session disconnect 设置同一个 cancel event。
  • coordinator 是唯一状态机 owner,负责 worker、control pipe、时钟、Job Object、协议响应和清理;同一时刻最多一个 worker。
  • worker 通过继承的 Windows event handle检查 cancel;在 metadata 前后、每个 progress/fragment hook、FFmpeg 前后及 bridge 前后检查。阻塞 socket 由固定 socket timeout打断。
  • reader 只入队已验证的非 secret control;start secret 只从 broker 写入 worker input pipe一次,随后 broker 清空 start/Cookie引用。

5.2 固定重试和时间上限

yt-dlp/host 值固定为:

项目 上限
socket/read timeout 20 s
extractor retries 1
HTTP retries 2
fragment retries 2
file access retries 1
retry sleep 每次 1 s,最大 3 s
metadata phase 120 s
download+merge 总墙钟 7200 s
frozen bridge 子进程 900 s
graceful cancel 3 s
TerminateJobObject 后 wait 5 s
reader/control join 5 s

达到任一阶段或总墙钟,coordinator 设置 cancel;3 秒后 worker 仍存活则调用 TerminateJobObject,5 秒后仍不能确认 PID 全灭则返回 E_PROCESS_OWNERSHIP 并退出,绝不继续后半程或发布。没有无限重试、无限 join 或断点续传。

5.3 OS 级后代所有权

每个 task 在接收 secret 前创建独立 Windows Job Object,设置 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE。broker 使用 Win32 CreateProcessWCREATE_SUSPENDED|CREATE_NO_WINDOW 启动同一 host executable 的 worker 模式,继承句柄 allowlist 只含 worker input、sanitized control 和 cancel event:

  1. worker 尚未执行用户代码时,broker 用 AssignProcessToJobObject 加入 task job。
  2. 成功后才 ResumeThread;失败则 terminate suspended worker、关闭 handles,并在 secret 写入前停止。
  3. worker 后续 yt-dlp/FFmpeg/bridge children 自动继承同一 job;禁止 breakaway。
  4. broker 持有 job 的唯一有效 handle。cancel/EOF/disconnect/BaseException/timeout 走 grace→TerminateJobObject→wait;broker 被 Chrome 强杀或崩溃时 handle 由 OS 关闭,kill-on-close 自动终止 worker 及全部后代。

若当前 Windows/Chrome job 策略不允许该所有权链,任务在 Cookie 读取/worker secret/网络前以 E_JOB_OBJECT fail-closed,不回退到普通 Popen 或仅 PID 递归清理。

5.4 Cookie 和 stage 的终态

  • graceful success/cancel/EOF/BaseException/timeout 路径要求 worker 在退出前 seek(0)/truncate(0)/close() Cookie stream,control pipe 只返回 cookie_stream_closed=true;broker 不记录内容。
  • 强制 kill/host crash 不依赖 Python finally;Job Object 确保持有 Cookie 的进程及后代全部终止,秘密内存由 OS 回收。此路径不虚报 Python close marker。
  • stage 始终只含媒体字节,不含 Cookie/URL/headers/log。强杀可能留下内部 stage;下次 broker 启动在读取任何 secret 前按 V001 固定根/重解析点边界清理,正式目录不受影响。

5.5 真实 sleeping-child 无网络门禁

实现审核使用真实 Win32 process,不只 fake child:

  • 测试 broker 通过同一 suspended→assign job→resume 路径启动 worker;worker 再启动一个 300 秒 sleeping child 和一个 grandchild,记录非秘密 PID。
  • 分别触发:用户 cancel、native stdin EOF、模拟 Chrome disconnect、worker KeyboardInterruptSystemExit、下载墙钟超时、broker TerminateProcess 模拟 host kill。
  • 每个 case 用 OpenProcess/WaitForSingleObject 验证 worker/child/grandchild handle 全部 signaled、无 PID 存活;grace 与 kill/join 时间均不超冻结值。
  • graceful case 断言 Cookie stream truncate+close marker;host kill case 断言 job kill 后秘密进程为 0、重启清理 stage成功且无协议/sentinel/日志。
  • child stdout/stderr 写 synthetic secret sentinel;逐字节扫描 Native protocol、父捕获、临时树、argv/env/evidence,出现次数必须为 0。

6. V002 离线复审矩阵

6.1 F1

  • 复算 public DER hash 和 expected ID;manifest key/ID/build 任一字符漂移失败。
  • installer 对正确 observed ID PASS;任意其他合法 32 位 ID、第二 origin、wildcard、hash/build 漂移均在 HKCU 前失败。
  • host argv exact origin PASS;错 origin、缺 origin、额外非 parent-window arg 在读 stdin/secret 前失败。
  • page/start/cookie 每个字段分别覆盖 missing/unknown/wrong type/bool-as-int/null/range/control/duplicate-key/oversize。
  • active tab store 不唯一、record store不一致、partitioned cookie、domain/path/hostOnly/session/expiry 所有反例外部动作 0。

6.2 F2

  • 冻结真实 yt-dlp 首次 import/实例化,默认插件目录存在 sentinel plugin 仍不加载;plugin dirs/maps exact empty。
  • 真实 CookieJar 合法/畸形/close 路径和 sleeping FFmpeg stdout/stderr sentinel 均进入 NUL;protocol frame保持可解析且无 sentinel。
  • worker 未发 READY 时 broker 不写 start secret;plugin gate失败时 secret write count=0。

6.3 F3

  • extractor invocation=1;validated/downloaded download_info object identity相同;第二解析 guard非真空。
  • real downloader class:HttpFD/DashSegmentsFD PASS;FFmpegFD/HlsFD/ExternalFD/unknown/m3u8 全拒绝且 media spawn=0。
  • audit hook 对 URL/header/Cookie/env/非 pinned executable/非本地 -i 在 CreateProcess 前拒绝。
  • 真实短合成双流与单文件均产一个 MKV,FFprobe AV PASS;single fallback 不得直接发布原容器。

6.4 F4

  • reader 在 worker 阻塞时仍能于冻结时限消费 cancel/EOF/status;第二 start E_BUSY。
  • retry/metadata/socket/fragment/total/bridge 每一门禁有计时反例,无无限等待。
  • 七类真实 sleeping child case 的 worker/child/grandchild PID 全灭;graceful Cookie close、host-kill OS memory终止、restart stage cleanup和无 sentinel全部非真空。

7. 文件与动作边界

V002 复审前仅新增本设计并追加既有开发账本/私有 worklog。以下保持冻结:

  • dev/project-dev/bili_video_download_bridge.py=28500/749FC486B0F42315BD463F11771FE2A7C71CAB53DD9AC2E411CE82E1175DFF13
  • dev/project-dev/test/test_bili_video_download_bridge.py=22553/80D8C94DF6922820AA4643984E91209C16046364C20A6A04F6ADA22C8DC36C8B
  • dev-doc/project-doc/B站完整视频下载桥接工具.md=6931/8103EA6F2077BF6BB30B31BCDFB3786B057306A747C18286E2622D19F8393687
  • 当前安装 TXT 扩展、public snapshot、localhost/token/SQLite/Cookie 文件链、600 秒隔离 preview、F:\video 和正式 ana-data

真实 Cookie/token/signed URL、Chrome、扩展安装、Native Host 注册、network、download、real media、F:\video、formal ana-data、implementation/test/config actions 全部保持 0

8. 复审请求与后续授权

dev.reviewer.project 只复审 F1—F4 是否闭环以及 V001 已通过边界是否回退,返回一次完整 PASS/0 或精确 HOLD。V002 PASS 只授权在冻结文件边界内创建最小离线实现、合成媒体测试和真实 sleeping-child 测试;不授权读取真实 Cookie、安装 Chrome/扩展/host、注册 HKCU、联网下载、读取隔离预览、写 F:\video/正式 ana-data 或启动转写。