JS逆向实战:从抓包到本地复现,破解翻译接口加密参数 1. 逆向工程入门为什么需要破解翻译接口当你使用在线翻译工具时浏览器会向服务器发送包含待翻译文本的请求。但仔细观察就会发现这些请求往往携带了像sign、token这样看似随机的加密参数。这些参数就像是网站发放的临时通行证服务器通过验证这些参数来判断请求是否合法。作为爬虫开发者如果我们想通过程序自动调用翻译接口就必须破解这些参数的生成逻辑。我第一次接触JS逆向是在做一个多语言内容聚合项目时。当时发现直接复制浏览器请求中的参数很快就会失效后来才明白这些参数往往具有时效性并且与请求内容相关联。比如某翻译网站的sign参数实际上是通过待翻译文本、时间戳和隐藏密钥计算得出的哈希值。这种设计既能防止接口被滥用又增加了逆向分析的难度。2. 实战准备抓包与参数定位2.1 浏览器开发者工具使用技巧打开Chrome开发者工具Windows按F12Mac按CommandOptionI切换到Network面板。这里有个实用技巧先点击清除按钮清空记录再在翻译框输入文本这样能快速定位到目标请求。我习惯勾选Preserve log选项防止页面跳转时请求记录丢失。找到翻译请求后重点关注以下几个部分Headers查看Request URL和Request MethodPayload如果是POST请求查看Form Data或Request PayloadResponse检查返回数据的结构和加密情况某次分析中我发现虽然请求参数中有10多个字段但实际每次变化的主要是q待翻译文本、sign和token三个参数。这大大缩小了逆向分析的范围。2.2 加密参数特征识别加密参数通常具有以下特征长度固定或在一定范围内变化如32位MD5、40位SHA1包含特殊字符如包含.分隔符随请求内容变化但无明显规律举个例子某翻译接口的sign值为232427.485594这种包含小数点的数值就很可能是通过特定算法生成的。而token类似3dde9ef10b6f6ae310af38e6f1bd564f的字符串则可能是MD5或类似哈希算法的产物。3. 逆向分析核心追踪加密逻辑3.1 XHR断点技巧实战在Sources面板中找到XHR/fetch Breakpoints区域点击添加断点。这里有个经验不要直接输入完整路径而是输入接口路径的关键部分比如/v2transapi。这样可以避免因URL参数变化导致断点失效。当断点触发后Call Stack面板会显示调用栈。这里有个实用技巧忽略jquery.js等第三方库的调用重点关注网站自身的JS文件。我通常会从栈顶向下逐个查看直到发现参数被赋值的代码段。某次分析中我在调用栈中发现了一个名为ajax的函数其参数对象中正好包含我们要找的sign和token。通过点击跳转到源码位置最终定位到加密函数的具体实现。3.2 搜索大法快速定位关键代码当断点难以触发时可以使用全局搜索CtrlShiftF。我常用的搜索策略包括直接搜索参数名如sign:搜索常见加密函数名如CryptoJS、MD5、encrypt搜索参数赋值语句如 sign、sign 在某次实战中通过搜索window.common.token我快速找到了token的生成位置。原来这个值是在页面加载时就已经生成并存储在全局变量中不需要复杂计算。4. 代码抠取与本地复现4.1 处理浏览器环境依赖浏览器中的JS代码往往依赖window、document等全局对象。在Node.js环境中运行时我们需要模拟这些环境。常见解决方案创建模拟对象const window { common: { token: 3dde9ef10b6f6ae310af38e6f1bd564f } };使用jsdom库完整模拟浏览器环境const { JSDOM } require(jsdom); const dom new JSDOM(, { runScripts: dangerously }); window dom.window;我曾遇到一个棘手的案例加密函数使用了window.gtk这个动态值。通过分析发现这个值其实在页面源码中是固定的最终通过搜索window.gtk找到了它的定义位置。4.2 函数改写与调试技巧从浏览器抠出的代码往往需要适当改造才能运行。常见修改包括删除浏览器特有的API调用替换全局变量引用提取依赖的辅助函数这里有个实用技巧使用try-catch包裹可疑代码段逐步排查问题。比如try { const sign e(测试文本); console.log(sign); } catch (err) { console.error(Error in function e:, err); }某次我遇到一个报错ReferenceError: i is not defined。通过分析发现原代码依赖一个闭包变量在抠取时丢失了上下文。解决方法是在函数开头添加var i null;初始化语句。5. 完整案例翻译接口逆向实现5.1 加密函数分析与提取以某翻译接口的sign生成函数为例核心逻辑如下function e(r) { // 字符串预处理 var o r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g); if (null o) { var t r.length; t 30 (r r.substr(0, 10) r.substr(Math.floor(t / 2) - 5, 10) r.substr(-10, 10)) } // 密钥处理 var l gtk; var i null; var u i || 320305.131321201 || ; // 核心加密逻辑 for (var p m, b 0; b S.length; b) { p S[b], p n(p, F); } return p n(p, D), p ^ s, (p % 1e6).toString() . (p ^ m) }这个函数的关键点在于对长文本会进行截取处理使用固定密钥320305.131321201通过位运算实现混淆5.2 Node.js完整实现方案最终可复用的Node模块代码如下var token 3dde9ef10b6f6ae310af38e6f1bd564f; function a(r) { if (Array.isArray(r)) { for (var o 0, t Array(r.length); o r.length; o) t[o] r[o]; return t } return Array.from(r) } function n(r, o) { for (var t 0; t o.length - 2; t 3) { var a o.charAt(t 2); a a a ? a.charCodeAt(0) - 87 : Number(a), a o.charAt(t 1) ? r a : r a, r o.charAt(t) ? r a 4294967295 : r ^ a } return r } function e(r) { var o r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g); if (null o) { var t r.length; t 30 (r r.substr(0, 10) r.substr(Math.floor(t / 2) - 5, 10) r.substr(-10, 10)) } var u, l gtk; var i null; u i || 320305.131321201 || ; for (var d u.split(.), m Number(d[0]) || 0, s Number(d[1]) || 0, S [], c 0, v 0; v r.length; v) { var A r.charCodeAt(v); 128 A ? S[c] A : (2048 A ? S[c] A 6 | 192 : (55296 (64512 A) v 1 r.length 56320 (64512 r.charCodeAt(v 1)) ? (A 65536 ((1023 A) 10) (1023 r.charCodeAt(v)), S[c] A 18 | 240, S[c] A 12 63 | 128) : S[c] A 12 | 224, S[c] A 6 63 | 128), S[c] 63 A | 128) } for (var p m, F -a^6, D -3^b-f, b 0; b S.length; b) { p S[b], p n(p, F); } return p n(p, D), p ^ s, 0 p (p (2147483647 p) 2147483648), p % 1e6, p.toString() . (p ^ m) } module.exports { getSign: e, getToken: () token };使用时只需要const translator require(./translator); console.log(translator.getSign(你好)); // 输出287622.219665 console.log(translator.getToken()); // 输出3dde9ef10b6f6ae310af38e6f1bd564f6. 常见问题与解决方案6.1 参数突然失效怎么办加密逻辑可能会定期更新常见应对策略检查密钥是否变化如window.gtk值确认加密函数是否有版本更新查看是否有新的验证参数加入我曾遇到一个案例某翻译网站每周一更新密钥。解决方案是定期访问首页通过正则表达式提取最新的密钥值。6.2 如何处理复杂的混淆代码对于重度混淆的代码可以尝试使用AST解析工具反混淆通过Hook技术动态获取参数寻找代码中的固定模式如加密函数通常包含位运算有个实用技巧在加密函数入口处添加console.log输出中间计算结果这能帮助理解算法逻辑。7. 安全与伦理考量在进行JS逆向时务必注意遵守网站的robots.txt规定控制请求频率避免给服务器造成负担仅用于学习研究和合法用途不要绕过明显的付费验证机制我个人的做法是在header中添加明显的User-Agent标识如MyResearchBot/1.0让网站管理员能识别出是自动化请求。同时严格控制爬取频率通常设置为每秒不超过1次请求。