| name | js-entry-finder |
| description | 通用定位混淆浏览器 JS 的加密/signature/sign/vmXX/window 全局函数入口。Use when 用户提供 curl、关键参数名、header、body 字段、返回前缀或 DevTools 线索,要求用 MCP/浏览器运行时找到参数来源、扣下相关 JS、反推 webpack/动态 VM 入口、确认第一个可调用加密函数,并整理给补环境或本地单脚本复现和请求验收。 |
JS 入口定位
目标
用“curl + 关键参数/线索”驱动入口定位,而不是针对某个站点写死函数名。最终要回答四件事:
- 关键参数从哪里来:全局变量、模块导出、业务 wrapper、动态 VM、还是服务端下发脚本。
- 哪些 JS 真正相关:保存最小脚本集合,避免把整站无关 chunk 都扣下来。
- 第一个可调用入口是什么:生成器入口、注册入口、业务调用入口分别是谁。
- 怎么复现:给出脚本加载顺序、调用参数、运行时依赖、验签方式、最终单脚本交付模式,以及测试脚本如何消费
_code.js 结果完成请求。
输入规范
用户通常会给:
- 一段 curl:包含 URL、headers、cookie、body。
- 一个或多个关键线索:例如
x-s、sign、h5st、mns、vm29、某个 body 字段、某个返回前缀、某个全局函数名。
- 可选浏览器状态:页面已打开、DevTools 截图、调用栈、当前断点变量。
先从 curl 里提取:
- 请求路径、方法、body 原文、query、cookie。
- 可疑 header:名字像
sign、token、sec、x-*、trace、timestamp、nonce 的字段。
- 会参与签名的稳定材料:
path、query、body、timestamp、cookie/session、平台版本号。
入口分类
定位时始终区分三层:
- 生成器入口:创建可调用函数的 VM/factory/动态编译逻辑。常见形态:
new Function、eval、WASM wrapper、数组解释器、vmXX、带静态属性的匿名函数。
- 注册入口:把函数挂到
window、闭包、模块导出、SDK 实例上的初始化逻辑。
- 业务入口:拿请求参数调用注册函数并组装 header/body 的 wrapper。
不要默认三层是同一个函数。业务入口最适合复现请求,注册入口最适合补环境,生成器入口最适合解释 VM 来源。
MCP 优先流程
如果可用,优先使用 js-reverse MCP 或真实浏览器运行时;静态 grep 只作为辅助。
-
列脚本
- 用 MCP 列当前页面脚本。
- 按 URL、chunk 名、关键词过滤:关键参数名、header 名、返回前缀、
sign、token、encrypt、sec、webpack、runtime、vendor。
- 先记录脚本 URL 和加载顺序,再保存相关脚本源码。
-
搜关键参数
- 在运行时和源码里都查:
- header 名:如
x-s、h5st。
- 参数值前缀:如
XYS_、mns0301_。
- 业务字段:curl body 中独特字段名。
- 可能的全局名:
window.xxx、SDK 对象名。
- 搜不到明文时,改搜拼接片段、字符串表、base64 字母表、MD5/SHA/AES 调用、
JSON.stringify 附近代码。
-
运行时插桩
- 对已知全局名,先装 setter 抓首次赋值:
const name = "TARGET_NAME";
let value;
Object.defineProperty(window, name, {
configurable: true,
enumerable: true,
get() { return value; },
set(v) {
value = v;
console.log("[entry:set]", name, typeof v, v && v.name, new Error().stack);
debugger;
}
});
- 对未知全局名,快照对比:
window.__entryBefore = new Set(Object.());
.().( !..(k));
鲁棒性原则
- 不写死站点、域名、函数名、header 名;全部从用户给的 curl 和关键线索推导。
- 不只搜明文。混淆场景要同时考虑字符串表、拼接、编码字母表、哈希摘要、动态属性名。
- 不只看赋值点。赋值点证明函数从哪来,业务调用点证明参数怎么组。
- 不只验证
success=true。还要看业务数据是否符合预期;空数据时先检查 body、cursor、cookie、timestamp、nonce 是否和签名输入一致。
- 不把一次能跑通当成通用结论。沉淀脚本时,必须让输入来自 curl 文件或配置,而不是写死样例值。
- 不把调试脚本当成交付物。probe、插桩、MCP 保存脚本只用于定位;成功后必须收敛成一个清晰入口的单脚本。
复现交付
入口定位结束后,输出:
- 关键参数来源:参数名、值形态、在哪个函数/模块生成。
- 相关脚本清单:URL、本地文件名、为什么需要它。
- 注册入口:文件/模块/函数、赋值对象、赋值调用栈。
- 业务入口:文件/模块/函数、签名输入材料、header/body 组装位置。
- 生成器入口:VM/factory/动态函数、参数数组、必要运行时环境。
- 本地复现方案:脚本顺序、调用参数、需要补的环境、验签 curl。
- 单脚本成品要求:最终交付必须是一个可直接运行的
run/_code.js;先判断能否走框架原生生成链路,不能时再要求自包含打包。
- 请求验收要求:必须给出测试脚本方案。测试脚本调用
node run/_code.js,解析输出,并使用这些结果完成真实请求/验签。
单脚本交付模式
定位成功后,把调试过程收敛为成品。按目标复杂度选择两种模式:
-
框架生成模式:如果项目已有 main.js 自动拼接/生成 run/_code.js 的机制,并且目标脚本只依赖框架可管理的 config/tools/env/run/sign.js,优先沿用这个机制。验收命令是先跑项目约定生成命令,再跑生成后的 run/_code.js。
-
自包含打包模式:如果目标依赖多段动态脚本、异步安全脚本、特殊加载顺序、MCP 扣下来的 live JS,或框架生成的 _code.js 运行后仍需要读取其他项目文件,则必须把必要环境代码、目标 JS、入口调用、签名/header 逻辑内嵌进 run/_code.js。
-
成品脚本只暴露一个主入口,例如 sign(input)、buildHeaders(curlLikeInput) 或项目约定的执行入口。
-
成品脚本内部可以包含必要的环境初始化、脚本加载、目标函数调用、header 组装,但不要依赖 DevTools 断点、MCP 插桩、临时 wrapper。
-
输入来自 curl 文件、请求对象或明确配置;不要把一次调试的 body、cookie、timestamp、nonce 写死成唯一可用样例。
-
输出要稳定:至少返回关键参数、替换后的 header、必要时返回可直接发起请求的摘要。
-
在当前补环境框架中,最终内容落到 run/_code.js。无论使用哪种模式,最后都必须能用 node run/_code.js 直接得到结果。
-
自包含打包模式下,run/_code.js 不应引用项目内相对模块,不应读取 config/、tools/、env/、run/*.live.js 等项目文件;只允许依赖 Node 内置模块和已安装 npm 包。
-
最终还必须生成测试脚本,例如 run/test_request.js 或 run/verify_code.js。测试脚本不能复制签名逻辑,必须调用 node run/_code.js 并消费其输出。
-
测试脚本要完成真实请求或验签请求,并检查业务响应,而不是只打印 curl 命令或签名字符串。
-
临时脚本可以保留作诊断材料,但 final answer 必须告诉用户成品入口是 run/_code.js,临时脚本不是主交付物。
请求验收设计
定位入口时同时规划 _code.js 的输出契约,方便测试脚本消费:
_code.js 输出 JSON,包含签名字段、headers、timestamp、nonce、body/query 变更等。
- 测试脚本从用户给的 curl 解析原始请求,只替换
_code.js 生成的字段。
- 测试脚本通过
child_process.execFileSync(process.execPath, ["run/_code.js", ...]) 或等价方式调用 _code.js。
- 测试脚本发出真实请求或验签请求,并断言响应成功;如果网络不可用,要保留脚本并说明未完成真实请求验收,不能声明交付完成。
- 空数据、签名成功但业务失败、只返回 success 但业务字段异常,都要回查
_code.js 输出和真实请求输入是否一致。
与补环境衔接
找到入口后再使用 browser-env-patch。移交给补环境时只传必要事实:
- 目标业务入口和调用方式。
- 需要加载的最小 JS 集合与顺序。
- 浏览器里采样到的关键参数、函数属性、调用栈。
- 本地缺失 API 或类型不一致点。
- 用于验收的 curl 和预期返回特征。
- 最终
run/_code.js 应该采用框架生成模式还是自包含打包模式、调用哪个业务入口、接受什么输入、输出什么结果。
- 测试脚本应该如何调用
run/_code.js、替换哪些请求字段、断言哪些响应字段。