在 Codex 里接入 js-reverse`之后,如何配合 chrome_devtools逆向网站

张开发
2026/4/20 14:19:07 15 分钟阅读

分享文章

在 Codex 里接入 js-reverse`之后,如何配合 chrome_devtools逆向网站
写在前面如果只靠肉眼在浏览器里点点点逆一个现代站点的签名参数效率通常不高。真正提速的方式不是“多开几个标签页”而是把能力拆开Codex负责调度、提问、整理上下文、生成代码js-reverse负责快速定位 bundle 中的关键字符串、模块和调用链chrome_devtools负责在真实浏览器环境里验证推断是否成立这次我拿 FotMob 的x-mas参数做了一次完整实战正好很适合说明这套组合拳的价值。为什么这套组合有效单看这三个工具很多人会觉得它们都能“看代码”但实际分工完全不同。Codex 擅长什么Codex 的优势不是直接替代你手工调试而是快速组织分析路径把多个工具结果合并成统一结论自动生成验证脚本最后把逆向结论沉淀成 Python / JS 代码和文档js-reverse擅长什么它最适合做两件事在大 bundle 中迅速搜索关键字把分散的字符串、函数、模块编号串成可读链路对于x-mas这种目标来说js-reverse的作用非常明显先搜x-mas再搜matchDetails再追生成函数和依赖模块chrome_devtools擅长什么它最大的价值是你不是在“猜前端怎么跑”而是在真实浏览器上下文里看它怎么跑。比如页面到底加载了哪些脚本请求发起时真正带了哪些 header某个 webpack 模块是否真的能调用成功这一步非常关键因为很多签名逻辑在浏览器内成立但离开浏览器就不一定成立。实战目标这次分析的目标接口是aHR0cHM6Ly93d3cuZm90bW9iLmNvbS9hcGkvZGF0YS9tYXRjaERldGFpbHM/bWF0Y2hJZD01MDY3Mjk5目标页面是aHR0cHM6Ly93d3cuZm90bW9iLmNvbS9tYXRjaGVzL2l0YWx5LXZzLWJvc25pYS1oZXJ6ZWdvdmluYS8ycnQ4MHgjNTA2NzI5OQ页面加载时这个接口会自动携带一个自定义请求头x-mas我们要做的不是拍脑袋猜而是把它完整拆出来。第一步用chrome_devtools打开页面确认页面上下文先用浏览器工具打开目标页面确认页面内容正常Bosnia and Herzegovina vs Italy - live score, predicted lineups and H2H stats接着做两个动作枚举已加载的脚本抓取页面里的网络与控制台信息这一阶段最重要的收获不是“看到请求”而是拿到 bundle 列表。很快可以发现一个关键 bundlehttps://www.fotmob.com/_next/static/chunks/pages/_app-b4715019995d80d7.js第二步用js-reverse搜关键字缩小范围如果没有js-reverse这里通常就要靠手工全文搜索和读压缩代码。但有了它以后步骤就非常直接搜索 1x-mas目的是确认哪个 bundle 里直接出现 header 名称。搜索 2matchDetails目的是把参数生成逻辑和接口调用逻辑连接起来。搜索 3/api/data/目的是确认它属于统一请求包装层而不是页面局部代码。最后会收敛到_appbundle。第三步锁定关键函数在_appbundle 里可以定位到下面这段关键代码g(e,t)l(${JSON.stringify(e)}${t}),m(e,tnewDate){letr{url:e,code:t.getTime(),foo:production:74ac2edaa7d42530fa49330efe1eedcfb21b555d},ng(r,h);returnbtoa(JSON.stringify({body:r,signature:n}))},y(e,t)(p(e)(t.headerst.headers??{},t.headers[x-mas]m(e)),t)这一步非常有代表性因为js-reverse能快速帮你把压缩变量链串起来m()生成x-masg()生成signatureh参与签名的常量y()把x-mas挂到请求头里第四步继续追l()确认签名算法接下来不能停在“看起来像哈希”这种模糊结论上。继续顺着模块依赖追可以看到letleo()(e).toUpperCase()再追到对应模块后会看到典型 MD5 常量1732584193-271733879-1732584194271733878这就足够确认l() MD5(...)而且输出被转成了大写。第五步确认body.url不是完整 URL这是这次逆向里最容易被忽略的细节。虽然接口本身是https://www.fotmob.com/api/data/matchDetails?matchId5067299但页面内部调用时真正传给请求包装层的是fasynce{lett(0,a.DQ)(/api/data/matchDetails,e);returnawait(0,a.LK)(t)}也就是说签名用的是/api/data/matchDetails?matchId5067299不是完整 URL。这个结论只有把“调用入口”和“签名函数”放到同一个分析上下文里才能稳定得出而这正是 Codex js-reverse配合时最省时间的地方。第六步确认h是什么继续往上追常量可以发现h是一整段歌词字符串来自《Three Lions》。所以最终公式就是signature MD5(JSON.stringify(body) lyrics_secret).upper()其中body { url: /api/data/matchDetails?matchId5067299, code: 当前毫秒时间戳, foo: production:74ac2edaa7d42530fa49330efe1eedcfb21b555d }最后再做一次base64(JSON.stringify({ body, signature }))第七步用chrome_devtools在真实页面里验证这一阶段最关键因为它决定你是在“猜”还是“证实”。我直接在页面里调用 webpack 模块70614let__wr;self.webpackChunk_N_E.push([[Math.random()],{},req{__wrreq;}]);constapi__wr(70614);constdataawaitapi.LK(/api/data/matchDetails?matchId5067299);console.log(data.general.matchId);浏览器内返回成功5067299同时抓到请求里实际存在x-mas: base64 payload这说明我们前面基于 bundle 的推断是成立的。第八步Codex 输出 Python 代码当结论已经闭合后Codex 最适合做的就是把它沉淀成脚本。核心 Python 版本如下defbuild_x_mas(api_url_or_path:str,foo:str,lyrics:str,ts_msNone)-str:api_pathnormalize_api_path(api_url_or_path)ts_msts_msorint(time.time()*1000)body{url:api_path,code:ts_ms,foo:foo,}signaturehashlib.md5((json.dumps(body,separators(,,:))lyrics).encode(utf-8)).hexdigest().upper()payload{body:body,signature:signature}returnbase64.b64encode(json.dumps(payload,separators(,,:)).encode(utf-8)).decode()真正值得写进结论的一点x-mas补对了仍然可能被拦这次分析还有一个非常重要的工程结论。我把x-mas完整还原出来后用 Python 和curl_cffi去直连接口服务端返回的是{error:Verification required,code:TURNSTILE_REQUIRED}这意味着x-mas的逆向是正确的但服务端并不只校验x-mas还叠加了 Turnstile / 风控机制也就是说这次实战最值钱的地方不是“拿到了接口”而是看清了完整边界内层问题参数怎么构造签名怎么计算bundle 哪个模块负责生成 header外层问题是否需要浏览器环境是否要求额外验证是否存在 Cloudflare / Turnstile / 行为校验这套方法的真正价值如果没有 Codex、js-reverse和chrome_devtools的组合这种题很容易陷入两种低效状态手工搜索 bundle来回跳转结论零碎补出签名后误以为问题已经结束而这次的工作流比较清楚chrome_devtools打开真实页面js-reverse快速搜索和追模块Codex汇总上下文、输出代码、验证逻辑最后在浏览器里做一次闭环验证这不是某个单点工具的胜利而是三个能力在各自最擅长的位置工作。总结这次 FotMobx-mas逆向可以浓缩成一句话用 Codex 编排分析用js-reverse快速定位代码用chrome_devtools在真实浏览器里完成验证。最终结论是x-mas生成逻辑已还原body.url使用相对路径signature MD5(JSON.stringify(body) lyrics_secret).upper()x-mas base64(JSON.stringify({body, signature}))但直连请求仍可能命中TURNSTILE_REQUIRED所以真正成熟的逆向不只是“把参数补出来”而是知道什么时候你在解决签名什么时候你在面对风控。这才是工具链协同之后最值得留下来的方法论。

更多文章