JS逆向实战:从Hook到扣代码——油猴脚本自动化与内存溢出精准定位
1. Hook技术基础与实战价值Hook技术本质上是一种偷梁换柱的代码拦截手段。想象你正在观察一栋大楼的快递收发室浏览器执行环境Hook就是给快递员函数戴上一个智能手环Hook逻辑不仅能记录他送了什么包裹参数还能随时让他改道送货修改行为。在JS逆向中Hook的价值主要体现在三个维度关键函数定位比如拦截eval执行快速发现动态加载的加密逻辑参数监控实时捕获cookie设置时的完整参数链反调试对抗绕过无限debugger等防御机制我曾在分析某电商平台加密逻辑时通过Hook XMLHttpRequest.open方法仅用15分钟就定位到了核心的签名生成位置而传统断点调试至少需要2小时。2. 油猴脚本Hook实战配置2.1 基础模板搭建油猴脚本的配置直接影响Hook效果。这是我优化过的通用模板// UserScript // name Crypto_Hook // namespace http://your.site // version 0.1 // description Hook crypto functions // match https://target.site/* // grant none // run-at document-start // /UserScript (function() { use strict; // 保存原始函数引用 const nativeEval window.eval; // 重写eval函数 window.eval function(code) { // 关键代码检测 if (/encrypt|signature/.test(code)) { console.log([EVAL HOOK], code.slice(0, 200) ...); debugger; } return nativeEval.apply(this, arguments); }; // 指纹伪装 eval.toString function() { return function eval() { [native code] }; }; })();关键参数说明run-at document-start确保在页面JS执行前注入grant none避免沙箱限制toString重写 防止函数指纹检测2.2 内存溢出防护方案当处理混淆代码时内存溢出是常见问题。我的解决方案是循环保护在Hook逻辑中添加计数器let counter 0; window.eval function(code) { if (counter 1000) { console.warn(Loop protection triggered); return ; } // ...原有逻辑 };大代码块过滤if (code.length 50000) { console.log(Large code block skipped); return nativeEval(code); }3. 关键函数Hook实战3.1 Cookie操作拦截这是经过实战验证的cookie Hook方案Object.defineProperty(document, cookie, { configurable: true, set: function(val) { if (val.includes(token)) { console.trace(Cookie modified:, val); debugger; } // 实际开发中建议保留原始功能 this._cookie val; }, get: function() { return this._cookie || ; } });常见问题处理失效场景某些网站会先delete再set需要额外处理delete操作多级代理遇到检测代码时可采用Proxy层层代理3.2 XHR请求拦截进阶版这个增强版脚本可以捕获完整请求生命周期const nativeOpen XMLHttpRequest.prototype.open; const nativeSend XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open function() { this._url arguments[1]; return nativeOpen.apply(this, arguments); }; XMLHttpRequest.prototype.send function(body) { if (this._url.includes(api/)) { console.log(XHR to ${this._url}, body); this.addEventListener(readystatechange, function() { if (this.readyState 4) { debugger; } }); } return nativeSend.apply(this, arguments); };4. 反调试对抗策略4.1 无限debugger破解最新实战验证的解决方案// 保存原始Function const NativeFunction window.Function; // 创建代理构造函数 window.Function function() { const fn new NativeFunction(...arguments); // 过滤debugger语句 const newFn function() { try { return fn.apply(this, arguments); } catch(e) { if (e.message.includes(debugger)) { console.log(Debugger blocked); return; } throw e; } }; // 保持原型链 newFn.prototype fn.prototype; return newFn; }; // 伪装指纹 Function.prototype.constructor NativeFunction;4.2 检测绕过技巧时间差检测Hook Date.now和performance.nowconst baseTime Date.now(); Date.now () baseTime 1000;控制台检测重写console.log等方法的toString检测console.log.toString () native code;5. 扣代码实战指南5.1 代码定位三板斧调用栈分析通过Hook捕获的调用栈向上追踪特征搜索搜索encrypt/sign等关键词事件监听跟踪click/keydown等事件绑定5.2 环境补全技巧常见需要补全的对象// Node环境补浏览器对象 if (typeof window undefined) { global.window { navigator: { userAgent: Mozilla/5.0 }, document: {} }; }内存泄漏处理方案// 循环引用处理 function cleanCircular(obj, seen new WeakSet()) { if (typeof obj object obj ! null) { if (seen.has(obj)) return [Circular]; seen.add(obj); for (let key in obj) { obj[key] cleanCircular(obj[key], seen); } } return obj; }6. 自动化Hook系统设计6.1 规则引擎配置建议的规则配置格式{ hooks: [ { target: eval, condition: code.length 1000, action: debugger }, { target: cookie, property: set, pattern: token, action: trace } ] }6.2 性能优化方案懒加载Hook按需注入Hook逻辑缓存机制缓存已分析过的函数Worker线程复杂运算放入Web Worker7. 实战案例电商签名破解某电商平台商品列表API签名分析过程请求分析发现sign参数随时间变化XHR Hook捕获到签名生成请求堆栈追踪定位到crypto_utils.js代码提取扣出核心签名函数环境补全补全window.crypto对象性能优化缓存中间计算结果最终实现的Node版本签名生成器速度比原版快3倍。8. 常见问题排查手册8.1 Hook失效排查检查油猴脚本是否启用确认run-at设置为document-start查看是否有其他脚本冲突检测网站是否使用了iframe隔离8.2 内存泄漏处理使用Chrome Memory面板记录内存快照重点关注闭包引用未清理的定时器缓存对象膨胀9. 安全防护建议指纹多样化定期更换Hook脚本的toString实现环境检测在Hook代码中加入反调试逻辑日志清理自动清除调试痕迹超时机制设置执行时间上限10. 工具链推荐调试工具Fiddler Chrome DevTools代码分析AST Explorerhttps://astexplorer.net性能分析Chrome Performance面板自动化测试Puppeteer在最近的一次金融网站逆向中通过组合使用Hook技术和AST分析成功还原了被混淆的加密算法整个过程就像在解一个精心设计的密码谜题每个Hook点都是揭开谜底的关键线索。