JS逆向快速定位关键点之9大通用hook脚本

2023-11-10 11:10:58 浏览数 (1)

大部分网站都会对关键参数进行加密,JS 逆向时,我们首要任务是定位参数具体的加密逻辑。

常见方式包含:关键字搜索、堆栈调试、XHR 及事件监听、AST 内存漫游、JS Hook 注入等

本篇文章以 JS Hook 注入 为切入点,在做JS逆向往往需要定位到一些关键参数位置去分析,比如Cookie、Sign、Token、s等关键参数,这时候就需要借助到JS Hook快速定位。

1. cookie 通用hook

Cookie Hook 用于定位 Cookie 中关键参数生成位置,以下代码演示了当 Cookie 中匹配到了 v 关键字, 则插入断点

代码语言:javascript复制
(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;
        },
    });
})();

2. header 参数通用hook

代码语言:javascript复制
(function () {
    // 头部参数 请求对象当中的 设为请求头部参数
   var org = window.XMLHttpRequest.prototype.setRequestHeader;
   window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
       // 关键字 在请求当中发现有键是Authorization 断点
       if (key == 'Authorization') {
            debugger;
        }
       return org.apply(this, arguments);
   }
})();

3. hook过debugger

代码语言:javascript复制
// 先保留原 constructor
// 1. 比如判断是否有该debugger词语,替换为同等长度的空格(避免判断长度)
Function.prototype.constructor_ = Function.prototype.constructor;
Function.prototype.constructor = function (a) {
    // 如果参数为 debugger,就返回空方法
    if(a == "debugger") {
        return function (){};
    }
    // 如果参数不为 debugger,还是返回原方法
    return Function.prototype.constructor_(a);
};

2. 如果是定时器的debugger采用以下语句
// 先保留原定时器
var setInterval_ = setInterval
setInterval = function (func, time){
    // 如果时间参数为 0x7d0,就返回空方法
    // 当然也可以不判断,直接返回空,有很多种写法
    if(time == 0x7d0)
    {
        return function () {};
    }
    // 如果时间参数不为 0x7d0,还是返回原方法
    return setInterval_(func, time)
}

// eval("debugger;");

4. hook URL

URL Hook 用于定位请求 URL 中关键参数生成位置,以下代码演示了当请求的 URL 里包含 login 关键字时,则插入断点:

代码语言:javascript复制
(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() 时,则插入断点:

代码语言:javascript复制
(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() 时,则插入断点:

代码语言:javascript复制
(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 源码:

代码语言:javascript复制
(function() {
    // 保存原始方法
    window.__cr_eval = window.eval;
    // 重写 eval
    var myeval = function(src) {
        console.log(src);
        console.log("=============== eval end ===============");
        debugger;
        return window.__cr_eval(src);
    }
    // 屏蔽 JS 中对原生函数 native 属性的检测
    var _myeval = myeval.bind(null);
    _myeval.toString = window.__cr_eval.toString;
    Object.defineProperty(window, 'eval', {
        value: _myeval
    });
})();

8. hook Function

以下代码执行后,所有的函数操作都会在控制台打印输出将要执行的 JS 源码:

代码语言:javascript复制
(function() {
    // 保存原始方法
    window.__cr_fun = window.Function;
    // 重写 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);
    }
    // 屏蔽js中对原生函数native属性的检测
    myfun.toString = function() {
        return window.__cr_fun   ""
    }
    Object.defineProperty(window, 'Function', {
        value: myfun
    });
})();

9. 通用反调试

代码语言:javascript复制
// ==UserScript==
// @name         debugger
// @namespace    http://tampermonkey.net/
// @version      1
// @description  Stops most anti debugging implementations by JavaScript obfuscaters
// @author       ss
// @match        *
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function() {
    var _constructor = unsafeWindow.Function.prototype.constructor;
    // Hook Function.prototype.constructor
    unsafeWindow.Function.prototype.constructor = function() {
        var fnContent = arguments[0];
        if (fnContent) {
            if (fnContent.includes('debugger')) { // An anti-debugger is attempting to stop debugging
                var caller = Function.prototype.constructor.caller; // Non-standard hack to get the function caller
                var callerContent = caller.toString();
                if (callerContent.includes(/bdebuggerb/gi)) { // Eliminate all debugger statements from the caller, if any
                    callerContent = callerContent.replace(/bdebuggerb/gi, ''); // Remove all debugger expressions
                    eval('caller = '   callerContent); // Replace the function
                }
                return (function () {});
            }
        }
        // Execute the normal function constructor if nothing unusual is going on
        return _constructor.apply(this, arguments);
    };
})();

写到最后

感谢您的一路陪伴,用代码构建世界,一起探索充满未知且奇妙的魔幻旅程。如果您对Python编程技巧、好玩实用的开源项目、行业新知趣事和各类技术干货等充满兴趣,那么不要错过未来我为大家奉上的精彩内容!点击关注,让您的探索学习之旅更加丰富多彩,我们一同成长,一同前行!

0 人点赞