Files
reverse-skills-max/vendor-new/xbsReverseSkill/web-js-env-patcher/references/dynamic-resource-freshness.md

4.9 KiB
Raw Blame History

动态 HTML / JS 资源保鲜与运行时刷新

当目标站点的 HTML、JS bundle、动态 chunk、challenge JS、403/风控页面或内联脚本可能随时间、会话、Cookie、seed、nonce、地域、TLS 指纹或点击动作变化时读取本文件。目标是防止把已经过期的本地快照当作最终补环境输入。

核心规则

  • 下载到本地的动态 HTML / JS 默认只是 分析快照,不能直接作为最终产物的固定依赖。
  • 最终入口运行时必须先刷新当前有效资源,再加载当前资源生成加密参数并发送请求。
  • 如果资源会过期,最终项目必须包含资源刷新模块,例如 src/resources/fetch-runtime-resources.js 或等价封装。
  • cURL / HAR / fixture 中的旧 HTML、旧 JS、旧 seed、旧 token、旧 Cookie 只能作为证据和 expected,不得硬编码到最终 signer。
  • 请求失败或参数不一致时,先检查资源是否过期、JS hash 是否变化、challenge seed 是否变化,再继续补 WebAPI。

动态性判定

任一条件命中时,将资源标记为动态或高风险:

证据 说明
Cache-Control: no-store/no-cache/private/max-age=0 不应长期复用
Expires 已过期或 TTL 很短 需要运行时刷新
URL 含 t/ts/timestamp/nonce/rand/random/_ 等 query 可能每次变化
同 URL 多次请求 body hash 不一致 不能固定本地文件
HTML 内联 seed/nonce/config/challenge/token 每次变化 必须刷新入口页
403 / challenge 页面返回 JS 通常与当前会话绑定
响应包含 Set-Cookie 可能刷新设备 Cookie / 风控 Cookie
JS URL 从当前 HTML 动态拼接 需要最终入口重新解析 HTML
JS 内容依赖当前 Cookie / Storage / 地域 / TLS 需要和请求客户端链路绑定

资源清单

每个已保存资源都记录到 case/notes/resource-manifest.json:

{
  "resources": [
    {
      "url": "https://example.com/challenge.js?ts=...",
      "type": "js",
      "file": "case/js/snapshots/challenge-001.js",
      "capturedAt": "2026-06-23T00:00:00.000Z",
      "status": 200,
      "headers": {
        "cache-control": "no-store",
        "set-cookie": "脱敏记录"
      },
      "sha256": "body hash",
      "dynamic": true,
      "use": "analysis-snapshot",
      "requiredForFinal": true,
      "runtimeRefresh": true,
      "refreshEntry": "result/src/resources/fetch-runtime-resources.js",
      "dependsOn": ["Cookie", "HTML seed", "TLS client"]
    }
  ]
}

字段要求:

  • dynamic: true:明确动态资源。
  • use: "analysis-snapshot":只用于分析,不进入最终主路径。
  • use: "runtime-refresh" 或 runtimeRefresh: true:最终运行前刷新。
  • requiredForFinal: true:最终生成参数需要它;此时必须提供运行时刷新方案。
  • refreshEntry:最终项目中负责重新获取该资源的模块。

目录约定

case/
├── js/
│   ├── snapshots/        # 动态资源快照,只用于分析
│   ├── static/           # 已确认可长期复用的静态 bundle
│   └── extracted/
├── notes/
│   └── resource-manifest.json
└── result/
    ├── final.js
    └── src/
        ├── resources/    # 运行时刷新 HTML / JS / challenge
        ├── env/
        ├── signer/
        └── request/

动态资源可以保存在 case/js/snapshots/,但不得原样复制到 result/ 作为 signer 主输入。

最终入口流程

涉及动态 HTML / JS 时,最终入口应按以下顺序执行:

  1. 使用用户已确认的 TLS 指纹兼容客户端请求入口页或 challenge 页。
  2. 解析最新 HTML,提取当前 seed、nonce、config、动态 JS URL、Set-Cookie。
  3. 按当前页面状态请求最新 JS / chunk / challenge 资源。
  4. 验证资源 hash、状态码和关键字段,并更新运行时资源上下文。
  5. 将当前 JS / seed / Cookie / Storage 注入补环境运行链路。
  6. 生成目标加密参数。
  7. 用同一会话 / Cookie / TLS 客户端发送最终请求。

不得在最终入口中只执行“加载旧本地 JS 快照 → 生成参数 → 请求”。

验证

进入最终交付前运行:

node scripts/check_dynamic_resources.js --case-dir case --markdown
node scripts/check_dynamic_resources.js --case-dir case --require-runtime-refresh --markdown

检查失败时先修复资源刷新链路,再继续补环境或最终请求。

输出模板

## 动态资源保鲜检查

- 是否存在动态 HTML / JS:
- 动态资源清单:
- 是否只作为分析快照:
- 是否影响最终参数生成:
- 最终入口是否运行时刷新:
- 刷新模块:
- 当前资源 hash 是否与 fixture 一致:
- 失败时是否先排查资源过期: