大部分网站都会对关键参数进行加密,JS 逆向时,我们首要任务是定位参数具体的加密逻辑。
常见方式包含:关键字搜索、堆栈调试、XHR 及事件监听、AST 内存漫游、JS Hook 注入等
本篇文章以 JS Hook 注入
为切入点,在做JS逆向往往需要定位到一些关键参数位置去分析,比如Cookie、Sign、Token、s等关键参数,这时候就需要借助到JS Hook快速定位。
1. cookie 通用hook
Cookie Hook 用于定位 Cookie 中关键参数生成位置,以下代码演示了当 Cookie 中匹配到了 v 关键字, 则插入断点
| (function () { |
| var cookieTemp = ''; |
| Object.defineProperty(document, 'cookie', { |
| set: function (val) { |
| if (val.indexOf('v') != -1) { |
| debugger |
| } |
| console.log('Hook捕获到cookie设置->', val); |
| cookieTemp = val; |
| return val; |
| }, |
| get: function () { |
| return cookieTemp; |
| }, |
| }); |
| })(); |
| (function () { |
| |
| var org = window.XMLHttpRequest.prototype.setRequestHeader; |
| window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) { |
| |
| if (key == 'Authorization') { |
| debugger; |
| } |
| return org.apply(this, arguments); |
| } |
| })(); |
3. hook过debugger
| (()=>{ |
| Function.prototype.__constructor = Function; |
| Function=function(){ |
| if ( arguments && typeof arguments[0] === 'string' ){ |
| if ("debugger" === arguments[0]){ |
| return |
| } |
| } |
| return Function.apply(this.arguments[0]); |
| } |
| })() |
| |
| var xxxx = Function.prototype.constructor; |
| |
| |
| Function.prototype.constructor = function(){ |
| |
| if (arguments[0] === 'debugger'){ |
| return; |
| } else { |
| |
| return xxxx.apply(this, arguments); |
| } |
| } |
| |
| |
| Function.prototype.constructor_ = Function.prototype.constructor; |
| Function.prototype.constructor = function (a) { |
| |
| if(a == "debugger") { |
| return function (){}; |
| } |
| |
| return Function.prototype.constructor_(a); |
| }; |
| |
| 2. 如果是定时器的debugger采用以下语句 |
| |
| var setInterval_ = setInterval |
| setInterval = function (func, time){ |
| |
| |
| if(time == 0x7d0) |
| { |
| return function () {}; |
| } |
| |
| return setInterval_(func, time) |
| } |
| |
| |
4. hook URL
URL Hook 用于定位请求 URL 中关键参数生成位置,以下代码演示了当请求的 URL 里包含 login 关键字时,则插入断点:
| (function () { |
| var open = window.XMLHttpRequest.prototype.open; |
| window.XMLHttpRequest.prototype.open = function (method, url, async) { |
| if (url.indexOf("login") != -1) { |
| debugger; |
| } |
| return open.apply(this, arguments); |
| }; |
| })(); |
5. hook JSON.stringify
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串,在某些站点的加密过程中可能会遇到,以下代码演示了遇到 JSON.stringify() 时,则插入断点:
| (function() { |
| var stringify = JSON.stringify; |
| JSON.stringify = function(params) { |
| console.log("Hook JSON.stringify ——> ", params); |
| debugger; |
| return stringify(params); |
| } |
| })(); |
6. hook JSON.parse
JSON.parse() 方法用于将一个 JSON 字符串转换为对象,在某些站点的加密过程中可能会遇到,以下代码演示了遇到 JSON.parse() 时,则插入断点:
| (function() { |
| var parse = JSON.parse; |
| JSON.parse = function(params) { |
| console.log("Hook JSON.parse ——> ", params); |
| debugger; |
| return parse(params); |
| } |
| })(); |
7. hook eval
JavaScript eval() 函数的作用是计算 JavaScript 字符串,并把它作为脚本代码来执行。如果参数是一个表达式,eval() 函数将执行表达式。如果参数是 Javascript 语句,eval() 将执行 Javascript 语句,经常被用来动态执行 JS。以下代码执行后,之后所有的 eval() 操作都会在控制台打印输出将要执行的 JS 源码:
| (function() { |
| |
| window.__cr_eval = window.eval; |
| |
| var myeval = function(src) { |
| console.log(src); |
| console.log("=============== eval end ==============="); |
| debugger; |
| return window.__cr_eval(src); |
| } |
| |
| var _myeval = myeval.bind(null); |
| _myeval.toString = window.__cr_eval.toString; |
| Object.defineProperty(window, 'eval', { |
| value: _myeval |
| }); |
| })(); |
8. hook Function
以下代码执行后,所有的函数操作都会在控制台打印输出将要执行的 JS 源码:
| (function() { |
| |
| window.__cr_fun = window.Function; |
| |
| var myfun = function() { |
| var args = Array.prototype.slice.call(arguments, 0, -1).join(","), |
| src = arguments[arguments.length - 1]; |
| console.log(src); |
| console.log("=============== Function end ==============="); |
| debugger; |
| return window.__cr_fun.apply(this, arguments); |
| } |
| |
| myfun.toString = function() { |
| return window.__cr_fun + "" |
| } |
| Object.defineProperty(window, 'Function', { |
| value: myfun |
| }); |
| })(); |
9. 通用反调试
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| (function() { |
| var _constructor = unsafeWindow.Function.prototype.constructor; |
| |
| unsafeWindow.Function.prototype.constructor = function() { |
| var fnContent = arguments[0]; |
| if (fnContent) { |
| if (fnContent.includes('debugger')) { |
| var caller = Function.prototype.constructor.caller; |
| var callerContent = caller.toString(); |
| if (callerContent.includes(/\bdebugger\b/gi)) { |
| callerContent = callerContent.replace(/\bdebugger\b/gi, ''); |
| eval('caller = ' + callerContent); |
| } |
| return (function () {}); |
| } |
| } |
| |
| return _constructor.apply(this, arguments); |
| }; |
| })(); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)