JS逆向之快速定位关键参数通用hook脚本

在 JS逆向时,首先需要做的就是定位加密参数的生成位置,然而在大量的 JS 中找到它不是很容易。在定位过程中,经常用到的一个技术就是 hook 技术,今天分享几个可以快速定位 JS 逆向加密参数的通用 hook 脚本。

油猴脚本框架

以下所有的脚本都要放到油猴脚本中使用,为了简化代码,这里先给出油猴脚本的框架,后续在进行 hook 的时候,只需要在框架中添加相应的 hook 代码即可。

// ==UserScript==
// @name        demo
// @namespace   Violentmonkey Scripts
// @match       https://xxxx.xxxx-xxxx.com/*
// @grant       none
// @version     1.0
// @author      -
// @description 2025/2/25 21:20:14
// @run-at      document-start
// ==/UserScript==
(function () {

//这里添加所需的 hook 代码

})();

别忘了修改上面的 @match 注释中的网址,此网址是 hook 脚本运行的网站,例如想要 hook 百度,填写 // @match       https://www.baidu.com/* 即可。可以按需修改其他注释,但是 @run-at 一定要是 document-start,这样才可以在网页加载前执行 hook 代码,hook 才能正常生效。

定位 json 序列化反序列化

json 数据是在逆向中经常遇到的,分享一个 hook json 序列化和反序列化过程的脚本,可以在遇到请求和响应都是 json 数据的情况下快速定位 json 的序列化和反序列化的位置。

// Hook JSON.stringify
    const originalStringify = JSON.stringify;
    JSON.stringify = function(params) {
        console.log("[Hook] JSON.stringify 参数:", params);
        // 检测关键加密参数(如token、sign等)
        if (typeof params === 'object' && params !== null) {
            if ('encryptedData'in params || 'token'in params) {
                debugger; // 触发断点
            }
        }
        return originalStringify.apply(this, arguments);
    };

    // Hook JSON.parse
    const originalParse = JSON.parse;
    JSON.parse = function(text) {
        console.log("[Hook] JSON.parse 输入数据:", text);
        // 检测解密后的响应数据
        if (typeof text === 'string' && text.includes('{')) {
            try {
                const parsed = originalParse(text);
                if ('data'in parsed && parsed.data.length > 100) {
                    debugger; // 触发断点
                }
            } catch (e) {}
        }
        return originalParse.apply(this, arguments);
    };

在请求和响应的时候都会打印出对应的数据,这个时候如果想要打断点的话,直接点击图片上的蓝色脚本在 hook 代码中打断点即可,向上查找调用栈即可找到 json 数据生成的位置。

定位 cookie 生成和读取

cookie 在逆向中也经常遇到,一般情况下会在本地通过 JS 生成一段 cookie,提交请求的时候发送给服务端验证,如果验证不通过,则拒绝。这个时候往往要先定位特定的 cookie 是在哪里生成的。

// ====== 核心:重写 document.cookie 的 getter/setter ======
    const cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') || {
        configurable: true,
        enumerable: true
    };

    Object.defineProperty(Document.prototype, 'cookie', {
        configurable: cookieDesc.configurable,
        enumerable: cookieDesc.enumerable,
        get: function() {
            const cookies = cookieDesc.get ? cookieDesc.get.call(this) : this._cookie || '';
            // 监控所有读取操作
            if (/(token|session|auth)/i.test(cookies)) {
                console.log('[Cookie Get]', cookies);
            }
            return cookies;
        },
        set: function(value) {
            // 监控所有写入操作
            console.log('[Cookie Set]', value);
            if (/(token=|session=|sign=)/i.test(value)) {
                console.trace('关键Cookie设置');
                
            }
            return cookieDesc.set ? cookieDesc.set.call(this, value) : (this._cookie = value);
        }
    });

手动获取 token 并且设置 token,可以看到均正常 hook 到了 cookie 操作并且打印了日志。

定位 eval 执行代码

eval 也是 JS逆向中常用的方式,将代码进行混淆加密后转成字符串形式,在运行时使用 eval 动态的加载并执行,这时可以通过 hook eval 函数的方式来定位动态加载的代码。

// 配置检测关键词(支持正则表达式)
    const TARGET_PATTERN = /login|encrypt|signature/;  // ← 修改这里
    
    // 保存原生eval
    const _nativeEval = window.eval;
    
    // 重定义eval
    window.eval = function(code) {
        console.log("[eval监控] 捕获关键代码:\n", code.slice(0, 200) + "...");
        // 调试触发逻辑
        if (TARGET_PATTERN.test(code)) {
            console.log("[eval监控] 捕获关键代码:\n", code.slice(0, 200) + "..."); // 截取前200
            debugger;  // 自动断点
        }
       
        // 执行原始eval
        return _nativeEval.call(window, code);
    };
    
    // 伪装成原生eval
    Object.defineProperty(window.eval, 'toString', {
        value: () =>'function eval() { [native code] }',
        writable: false,
        configurable: false
    });

可以看到,在执行 eval 的时候,会自动打印出所有 eval 执行的代码。

定位 Function 执行

Function 是 JS 中动态创建函数的一种方式,它是所有函数的构造函数。在 JS逆向中,很多时候会通过新建 Function 对象的方式来新建一个函数,从而在搜索某个加密函数的时候会搜索不到,因为它不是静态的,而是动态创建的。

它与 eval 的区别如下:

特性
Function
eval
作用域
在全局作用域执行
在当前作用域执行
返回值
返回新函数
返回最后一条语句的结果
安全性
相对隔离(但仍不安全)
更高风险
典型应用场景
动态生成函数
动态执行代码片段

Function 用法示例:

const code = 'return Date.now().toString(32)';
const getDynamicValue = new Function(code);
console.log(getDynamicValue()); // 输出类似 "1smn3v"
function hookFunction(func) {
    returnnewProxy(func, {
        construct(target, args) {
            console.log(`拦截构造函数: ${target.name}, 参数: ${args}`);
            returnReflect.construct(target, args);
        },
        apply(target, thisArg, args) {
            console.log(`拦截函数调用: ${target.name}, 参数: ${args}`);
            returnReflect.apply(target, thisArg, args);
        }
    });
}

// Hook 所有通过 Function 创建的函数
window.Function = hookFunction(window.Function);

使用代理的方式来拦截针对 Function 的调用,因为一般在使用 Function 的时候,会遇到比较强的校测,重写函数可能会被检测到,使用代理的隐蔽性更强,不会轻易被检测到。

定位 Ajax 请求

定位 Ajax 请求不使用 hook,只需要在浏览器中添加 XHR 断点即可。

可以选择对所有的 Ajax 请求或者某个含有特定字符串的请求打断点,这样在请求发起时,会自动断在 send 函数上。

快速定位 cookie 生成请求

如果想要快速定位某个特定的 cookie 是从哪个请求生成的,其实也可以不用写 hook 代码,直接点点鼠标就可以了。

来看方法:

 例如想要快速定位这个 sign 是在哪个请求生成的,网络请求有这么多,这个网站比较简单,如果是复杂的网站可能会达到几十个之多。

只需要在 cookie 上面点击右键,然后点显示涉及此 cookie 的请求,就会自动跳转到 network 选项卡,并且将 cookie 中有 sign 的请求全部都过滤出来,此时只要看第一个请求就可以了。

此方法其实就是 Chrome 自动添加了过滤条件,过滤出所有涉及到 cookie 的请求,对于快速定位 cookie 生成位置还是很有用的。

总结

以上就是本次分享的所有 hook 脚本,由于每个网站的加密内容都不同,大家可以根据上面的代码自行编写其他 hook 操作。

转自微信公众号

 

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容