find-crypto-entry
定位加密参数 $ARGUMENTS 的生成入口,并明确给出可继续分析的落点。
目标:找到生成该参数的函数位置(脚本 URL + 行列号 + 函数名 + 调用路径),让后续补环境或算法分析可以直接接上。
使用方式
优先走成本最低的路径:
- 先搜参数名、请求头名、调用点和赋值位置。
- 再读上下文,确认是业务代码、拦截器还是外部 SDK。
- 静态路径不够时,再用浏览器调试验证调用链。
- 结束时只交付入口位置与调用链,不在本 skill 内继续做算法还原。
如果用户同时给了页面、抓包或报错,优先先确认一个真实请求:
- 请求是在首页首跳、挑战页还是页面内 XHR / fetch 发出的。
- 响应是正常业务数据,还是
412/202/204/ 跳转链 / 挑战文档。 - 如果只是“HTTP 200 但空 body / 空数据”,优先怀疑环境或注册路径没对上,而不是立刻认定入口没找到。
开始前先快速判断目标更像哪类:
- 行为型签名:页面能正常加载,参数出现在 XHR / fetch 请求里,常见于
sign、token、a_bogus、X-Bogus。 - 首屏 challenge / 动态 cookie:首页或前置请求先落到
412、202、204、跳转链或 challenge 文档。这类目标不要直接按“普通请求加签”思路深追入口,优先确认 challenge 脚本、cookie 写入点和初始化链路。 - 环境读取型 JSVMP / 环境即签名:请求字段不是单一显式函数直接返回,而是依赖环境读取、副作用、解释器执行或初始化过程共同生成。这类目标不要强行寻找一个孤立的
sign()函数。
如果已经确认是第二类或第三类,本 skill 只做局部定位,不承诺能单靠源码搜索直接找到最终 cookie 生成链或最终输出函数。
触发边界
下面这些需求通常应该触发本 skill:
- “这个参数在哪生成”。
- “请求头里的 Authorization / x-sign 是哪来的”。
- “帮我找签名入口和调用链”。
- “我要脚本 URL、函数名、行列号或调用路径”。
下面这些需求通常不该由本 skill 单独处理:
- “给我一个浏览器里能直接 hook 的脚本”。
- “把浏览器代码补环境后放到 Node 里跑”。
- “直接还原整个混淆文件”。
- “我已经知道目标函数了,直接帮我补环境执行”。
转交提示
如果用户明确要的是“浏览器里能直接执行的 hook / 断点脚本”,转给 browser-hook-snippets。
如果用户在定位入口之后,下一步目标是“脱离浏览器在 Node.js 里独立运行”,转给 env-patch。
如果入口已经找到,但 SDK 或目标文件本身高度混淆、需要源码级结构化还原,转给 ast-deobfuscate。
策略选择
根据信号选择策略,不要按固定顺序执行:
优先静态搜索:优先用 OpenCode 的搜索能力在源码里搜参数名。大多数情况下直接找到赋值位置,然后读上下文追溯来源。
静态搜不到时再走浏览器侧定位:在 DevTools 或可用的浏览器调试工具里围绕请求 URL、请求发起点和调用栈定位。断点命中后优先检查业务代码帧中的变量值。
两种策略可以组合:先静态搜索定位赋值位置,再在赋值处设断点动态验证。
经验规则
逆向定位里最常见的误判如下:
更完整的入口架构、动态验证步骤和完成模板见 references/entry-patterns.md。当任务涉及拦截器、外部 SDK 或 challenge 分支时,先读该参考再开始追链。
加密参数的 5 种常见架构
- 业务代码直接赋值 — 在请求函数中
headers["x-sign"] = encrypt(data)。静态搜索直接找到。 - 请求拦截器统一加签 — axios interceptor 或 fetch wrapper 中统一添加。搜参数名可能只在拦截器中出现一次。
- 外部安全 SDK — 独立 JS 文件(通常混淆)挂载全局对象(如
window.h5sign),业务代码调用其方法。静态搜索能找到调用处,但 SDK 内部代码全被混淆。 - challenge / 动态 cookie 分支 — 参数或 cookie 来自首屏脚本副作用、跳转链或前置验证,不一定存在独立加密函数。
- 环境读取型 JSVMP — 输出依赖解释器执行时读取的环境、对象属性或宿主 API,不一定能抽象成单一业务函数。
行为型 SDK 的 2 个高价值线索
- 初始化配置决定拦截器是否生效 — 某些 SDK 不是“找到 sign 函数就结束”,而是初始化时要注册目标路径或开关。除了参数名本身,也要搜初始化入参、路径表、配置对象。
cacheOpts/paths/ 请求白名单 — 字节系或同类 SDK 常把目标 API 路径挂在初始化配置里。静态搜索参数名搜不到时,改搜cacheOpts、paths、目标 URL 片段、拦截器注册函数名,常能更快落到入口。
环境读取型目标的 3 个高价值线索
- 请求发出前没有显式 sign 赋值 — 但会出现 cookie 变化、header 被统一注入、首屏脚本先运行一段解释器逻辑。
- 请求是否放行取决于初始化配置 — 例如路径白名单、SDK 注册、解释器装载、cookie 预热、挑战脚本执行完成。
- 环境读取比算法本身更关键 — 真正高价值的入口可能是
document.cookie写入点、createElement/canvas/navigator访问点、或 VMP 调度入口,而不是最终摘要函数。
OB 混淆的影响
当加密逻辑在 OB 混淆的文件中(特征:_0x 前缀、大型字符串数组、RC4 解密函数),所有字符串都被加密,静态搜索在该文件内无法匹配任何明文。但调用该文件的业务代码通常未混淆,从业务代码侧搜索更高效。
XHR 断点命中时的堆栈特点
XHR 断点命中在 send() 调用处,调用栈底部通常是框架代码(axios/fetch wrapper)。加密逻辑在栈的中上层。直接跳过底部框架帧,关注业务代码帧。
反模式
- 不要反复 step_into — 容易掉进框架响应式系统(Vue reactivity、React fiber)。优先直接检查当前调用帧里的变量,比盲目单步跟踪高效得多。
- 不要在 OB 混淆文件中搜字符串 — 所有明文都被加密了,搜不到。从非混淆的调用方搜。
- 不要频繁刷新页面 — 每次刷新所有 scriptId 失效。设好断点再刷新,一次到位。
- 断点命中时优先检查指定调用帧 — 如果调试工具支持按帧求值,优先查看目标业务帧,不要只看顶层上下文。
完成标准
找到以下信息即为完成:
入口位置:
- 参数:$ARGUMENTS
- 脚本:https://example.com/static/js/main.abc123.js
- 位置:第 X 行,第 Y 列
- 函数:functionName (或 anonymous)
- 调用路径:request → addSign → encrypt
- 加密类型:[标准算法名 | 外部SDK | 环境读取型 | 未知/需解混淆]
- 入口类别:[业务直赋值 | 拦截器统一加签 | 外部 SDK | challenge/动态 cookie 分支 | 环境读取型 JSVMP]
如果目标不是普通函数加签,允许交付“初始化入口 / challenge 入口 / 环境访问链入口”,不强行伪造一个单点 sign() 结论。
只找入口,不做算法还原。
参考文件
references/entry-patterns.md:业务直赋值、请求拦截器、外部 SDK、challenge/dynamic cookie 分支的定位模式。evals/evals.json:入口定位、拦截器、challenge 转交和 hook 负例的回归测试集。