sharoon7171/vidfast-pro-stream-resolver

GitHub: sharoon7171/vidfast-pro-stream-resolver

一个逆向工具包,用于解密 VidFast 加密载荷并根据内容 ID 解析出直链 HLS 播放地址。

Stars: 0 | Forks: 1

# vidfast-pro 解密 VidFast 加密的 payload,通过 TMDB 内容 ID 解析 m3u8 URL,并通过 HTTP 将结果与用于播放的 Web 客户端一起暴露出来。 ## 1. 概述 VidFast 会针对两种数据类型返回加密的 base64 blob: | 加密输入 | 明文输出 | 用途 | | --- | --- | --- | | `capture/probe.b64` | 服务器列表(`name`、`data`、…) | 流媒体服务器目录 | | Stream POST 响应体 | `{ url: "….m3u8", … }` | 直连 HLS manifest URL | 两者都使用相同的加密算法以及来自 `capture/keys.json` 的相同密钥。代码库在 `src/dec/` 中对它们进行解密,通过 `src/capture/init.js` 加载密钥和 probe,通过 `src/net/vidfast.js` 获取 stream blob,并在 `src/resolve/run.js` 中编排整个链路。 ## 2. 解密 ### 2.1 输入与输出 ``` capture/keys.json ──► parseKeys() ──► { k1, k2, k3 } │ capture/probe.b64 ──► decProbe() ──────────┤──► [ { name, data, description, image }, … ] │ Stream POST body ──► decStream() ─────────┘──► "https://…/index.m3u8" ``` | 密文来源 | 磁盘上的文件 | 解密函数 | 模块 | 输出 | | --- | --- | --- | --- | --- | | 服务器列表 | `capture/probe.b64` | `decProbe(b64, keys)` | `src/dec/probe.js` | 服务器行数组 | | Stream URL | VidFast POST 响应 | `decStream(b64, keys)` | `src/dec/stream.js` | m3u8 URL 字符串 | | 任意(原始 JSON) | 任何 base64 blob | `decJson(b64, keys)` | `src/dec/aes.js` | 解析后的 JSON 对象 | 密钥永远不会嵌入到密文中。它们在启动时从磁盘加载一次: ``` capture/keys.json ──► parseKeys() ──► src/dec/keys.js ──► { k1, k2, k3 } as Buffer ``` ### 2.2 加密算法 所有解密路径都会调用 `src/dec/aes.js` 中的 `decJson()`。 **实现:** Node.js `node:crypto` — `createHash('sha256')`、`createDecipheriv('aes-256-gcm')`。 **Blob 布局(base64 解码后):** | 偏移量 | 大小 | 字段 | | --- | --- | --- | | 0 | 16 | Header | | 16 | 12 | IV | | 28 | n | Ciphertext | | 28 + n | 16 | Auth tag | **密钥派生:** ``` h1 = SHA256(k1 ‖ k2 ‖ k3) key = SHA256(h1 ‖ header) ``` **解密:** ``` plain = AES-256-GCM-Decrypt(key, iv, ciphertext, tag) json = JSON.parse(plain.subarray(8)) ``` 在解析 JSON 之前,明文的前 0–7 字节会被丢弃。 ### 2.3 模块链 ``` src/dec/keys.js parseKeys(raw) keys.json object → { k1, k2, k3 } │ ▼ src/dec/aes.js decJson(b64, keys) base64 blob → JSON │ ├──► src/dec/probe.js decProbe(b64, keys) JSON → server rows │ └──► src/dec/stream.js decStream(b64, keys) JSON → json.url ``` `src/dec/` 不具有文件系统或网络访问权限。调用者需提供 `b64` 和 `keys`。 ### 2.4 加载器 `src/capture/init.js` 读取磁盘构件并连接解密调用: | 函数 | 读取 | 调用 | 返回 | | --- | --- | --- | --- | | `warm()` | `keys.json`、`probe.b64` | `parseKeys`,缓存在内存中 | — | | `listProbe()` | 缓存的 probe + keys | `decProbe` | 服务器行 | | `urlFromBlob(b64)` | 缓存的 keys | `decStream` | m3u8 URL | 每个进程加载一次。修改 `capture/` 后需要重启。 ## 3. 解析 解析过程将内容 ID 转换为 probe 列表中每个服务器的已解密 m3u8 URL。 ### 3.1 Pipeline ``` listProbe() decrypt probe.b64 → server rows │ ▼ for each row (8 workers): postStream(row.data, pagePath) POST to VidFast → base64 body urlFromBlob(b64) decrypt body → m3u8 URL │ ▼ yield NDJSON events meta → server → done ``` ### 3.2 内容路径 | 查询 `type` | 构建的路径 | | --- | --- | | `movie` | `/movie/{id}` | | `tv` | `/tv/{id}/{season}/{episode}` | 在 `src/resolve/run.js` 中根据 `URLSearchParams` 构建。在 stream POST 中用作 `Referer` 后缀。 ### 3.3 Stream POST `src/net/vidfast.js` → `postStream(data, page)` **读取:** `capture/routes.json` **请求:** ``` POST {origin}/{probePrefix}/{streamPrefixB}/{data} Referer: {origin}{page} Origin: {origin} + csrfHeaders, User-Agent Timeout: 2500 ms ``` **返回:** 修剪过的 base64 密文,失败或返回 JSON 错误体时为 `null`。 该 base64 字符串是 `urlFromBlob()` → `decStream()` → `decJson()` 的输入。 ### 3.4 并发 `src/resolve/pool.js` 最多并行运行 8 个 `postStream` + 解密任务。结果按完成顺序 yield。重复的 m3u8 URL 会被跳过。POST 或解密失败仅针对该服务器返回 `null`。 ### 3.5 服务器结果对象 由 `src/resolve/run.js` 生成: | 字段 | 来源 | | --- | --- | | `name`、`description`、`image`、`data` | Probe 行 | | `streamUrl` | `decStream` 输出 | | `playbackUrl` | `{origin}/api/hls?url={encodeURIComponent(streamUrl)}` | ## 4. HTTP 服务器 **入口:** `npm start` → `src/srv/http.js` **端口:** `8787`(环境变量 `PORT`) | 路由 | 使用的模块 | 动作 | | --- | --- | --- | | `GET /api/resolve` | `src/resolve/run.js` | 流式传输 NDJSON 解析事件 | | `GET /api/hls?url=` | `src/net/hls.js` | 代理 HLS manifest 或分片 | | `GET /` | — | 提供 `public/index.html` | 启动时会调用 `warm()` 将 `capture/` 预加载到内存中。 ### 4.1 `/api/resolve` **查询参数:** `id`(必填)、`type`(`movie`|`tv`)、`season`、`episode` **响应:** `application/x-ndjson` | 事件 | Payload | | --- | --- | | `meta` | `{ type, contentPath, total }` | | `server` | `{ server: { name, streamUrl, playbackUrl, … } }` | | `done` | `{ servers: [...] }` | | `error` | `{ error }`(仅在流传输过程中) | ### 4.2 `/api/hls` 不进行解密。使用 VidFast referrer 标头获取上游 HLS。 | 响应类型 | 行为 | | --- | --- | | `.m3u8` manifest | 将分片 URL 重写为通过 `/api/hls` 循环 | | 分片字节 | 如果存在 PNG 包装则剥离;返回 MPEG-TS | ## 5. Web 客户端 **文件:** `public/index.html` | 依赖项 | 来源 | | --- | --- | | hls.js 1.5.15 | jsDelivr CDN | | 动作 | 使用的 API | | --- | --- | | 获取流 | `GET /api/resolve` — 读取 NDJSON 流 | | 播放视频 | 通过 `server.playbackUrl` 调用 `GET /api/hls` | | 切换服务器 | 更改 `
标签:AES解密, GNU通用公共许可证, HLS, MITM代理, Node.js, 云资产清单, 后端开发, 流媒体解析, 逆向工程