JavaScript混淆防护与调试技术探析
字数 1472 2025-08-06 00:52:37

JavaScript混淆防护与调试技术探析

JavaScript的渊源

JavaScript最初由Brendan Eich于1995年为Netscape浏览器开发,目的是让网页具有交互性。它实现了网页动态效果,如:

  • 鼠标悬停显示提示信息
  • 表单数据验证
  • 动态加载内容

在浏览器中的执行(BS架构)

JavaScript在浏览器中的解析步骤:

  1. <script>标签处理
    • 无async/defer:立即执行,可能阻断HTML解析
    • async属性:异步加载,加载完成后立即执行
    • defer属性:异步加载,HTML解析完成后执行

在App中的应用(CS架构)

在移动应用中,JavaScript可用于:

  • 注入JS修改请求和响应(MITM攻击)
  • 去除APP开屏广告
  • 绕过功能限制
  • 修改应用行为

JavaScript混淆技术

混淆的起源:JS压缩

早期JS压缩技术:

  1. 删除空格、换行和注释
  2. 替换局部变量名为更短名称
  3. 合并多个JS文件
  4. 移除死代码
  5. 使用短语法:
    • 逻辑运算符简化条件表达式
    • 模板字符串代替字符串连接
    • 箭头函数简化函数表达式
    • 默认参数值
    • 解构赋值
  6. 预编译模板
  7. 使用CDN引入公共库

现代混淆技术

使代码不可读

  1. 变量名和函数名替换

    • 将有意义名称替换为无意义字符序列
  2. 字符串加密

    • 运行时解密字符串,增加逆向难度
  3. 改变代码结构

    • 使用IIFE(立即调用函数表达式)封装代码
    • 减少全局变量使用
  4. 插入死代码

    • 添加不会执行的无用代码片段
  5. 控制流混淆

    • 将简单逻辑改为复杂控制结构
    • 使用switch和循环结构伪装简单判断
  6. 高级算法和技术

    • 代理混淆(函数调用转为代理调用)
    • AST(抽象语法树)变形

使代码不可调试

  1. 无限debugger

    var c = new RegExp("1");
    c.toString = function () {
        setInterval(function() {
            debugger
        }, 1000);
    }
    console.log(c);
    
  2. 内存耗尽攻击

    var startTime = new Date();
    debugger;
    var endTime = new Date();
    var isDev = endTime - startTime > 100;
    var stack = [];
    
    if (isDev) {
        while (true) {
            stack.push(this);
            console.log(stack.length, this);
        }
    }
    
  3. 反直觉技术

    • 将JS代码隐藏在PNG图片元数据中
    • 通过Canvas API提取并执行隐藏代码

JavaScript反混淆技术

在线工具

  1. JavaScript Deobfuscator
  2. Relative.im Deobfuscator
  3. Beautifier.io

使用大模型(GPT)

大语言模型能有效还原混淆代码,还原度可达98%

Chrome开发者工具技巧

  1. 忽略无限debugger

    • 在Sources面板选中debugger语句
    • 右键选择"Add script to ignore list"
  2. 动态调试

    • 设置断点
    • 单步执行
    • 观察变量变化

实战案例

百度翻译接口逆向(2024.2.24)

  1. 分析请求参数:

    • sign和ts参数随query变化
    • transtype在realtime和enter间切换
  2. 定位关键函数:

    • 全局搜索"sign:"或"sign="
    • 在index.36217dc5.js中找到sign生成函数
  3. 提取sign生成算法:

    • 硬编码关键变量(window[d]值)
    • 重构n函数和a函数
  4. 最终生成脚本:

    function n(t, e) {
        // 算法实现...
    }
    
    a = function(t) {
        // 算法实现...
    }
    
    const query = "abandon";
    console.log(`from=en&to=zh&query=${query}&simple_means_flag=3&sign=${a(query)}&token=27e9578934647317beb78881e9e2300e&domain=common&ts=1708512893507`)
    

有道翻译接口逆向(2024.2.24)

  1. 分析请求:

    • sign和mysticTime参数变化
    • sign可能是MD5哈希
    • mysticTime是时间戳
  2. 定位关键函数:

    • 全局搜索"md5"或"createHash"
    • 找到sign生成函数
  3. 重构sign生成:

    const crypto = require('crypto')
    
    function c(e) {
        return crypto.createHash("md5").update(e.toString()).digest("hex")
    }
    
    function sign(e, t) {
        return c(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
    }
    
    const e = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4";
    const t = (new Date()).getTime();
    
    console.log(sign(e, t));
    
  4. 解密翻译结果:

    • 定位密文位置
    • 使用获取的key进行AES解密

关键点总结

  1. JavaScript混淆的核心目标是使代码不可读和不可调试
  2. 现代混淆技术结合了多种方法增加逆向难度
  3. 反混淆需要结合工具、大模型和动态调试技术
  4. 实战中定位关键函数是逆向的核心步骤
  5. Chrome开发者工具的高级功能能有效应对反调试
JavaScript混淆防护与调试技术探析 JavaScript的渊源 JavaScript最初由Brendan Eich于1995年为Netscape浏览器开发,目的是让网页具有交互性。它实现了网页动态效果,如: 鼠标悬停显示提示信息 表单数据验证 动态加载内容 在浏览器中的执行(BS架构) JavaScript在浏览器中的解析步骤: <script> 标签处理 无async/defer:立即执行,可能阻断HTML解析 async属性:异步加载,加载完成后立即执行 defer属性:异步加载,HTML解析完成后执行 在App中的应用(CS架构) 在移动应用中,JavaScript可用于: 注入JS修改请求和响应(MITM攻击) 去除APP开屏广告 绕过功能限制 修改应用行为 JavaScript混淆技术 混淆的起源:JS压缩 早期JS压缩技术: 删除空格、换行和注释 替换局部变量名为更短名称 合并多个JS文件 移除死代码 使用短语法: 逻辑运算符简化条件表达式 模板字符串代替字符串连接 箭头函数简化函数表达式 默认参数值 解构赋值 预编译模板 使用CDN引入公共库 现代混淆技术 使代码不可读 变量名和函数名替换 : 将有意义名称替换为无意义字符序列 字符串加密 : 运行时解密字符串,增加逆向难度 改变代码结构 : 使用IIFE(立即调用函数表达式)封装代码 减少全局变量使用 插入死代码 : 添加不会执行的无用代码片段 控制流混淆 : 将简单逻辑改为复杂控制结构 使用switch和循环结构伪装简单判断 高级算法和技术 : 代理混淆(函数调用转为代理调用) AST(抽象语法树)变形 使代码不可调试 无限debugger : 内存耗尽攻击 : 反直觉技术 : 将JS代码隐藏在PNG图片元数据中 通过Canvas API提取并执行隐藏代码 JavaScript反混淆技术 在线工具 JavaScript Deobfuscator Relative.im Deobfuscator Beautifier.io 使用大模型(GPT) 大语言模型能有效还原混淆代码,还原度可达98% Chrome开发者工具技巧 忽略无限debugger : 在Sources面板选中debugger语句 右键选择"Add script to ignore list" 动态调试 : 设置断点 单步执行 观察变量变化 实战案例 百度翻译接口逆向(2024.2.24) 分析请求参数: sign和ts参数随query变化 transtype在realtime和enter间切换 定位关键函数: 全局搜索"sign:"或"sign=" 在index.36217dc5.js中找到sign生成函数 提取sign生成算法: 硬编码关键变量(window[ d ]值) 重构n函数和a函数 最终生成脚本: 有道翻译接口逆向(2024.2.24) 分析请求: sign和mysticTime参数变化 sign可能是MD5哈希 mysticTime是时间戳 定位关键函数: 全局搜索"md5"或"createHash" 找到sign生成函数 重构sign生成: 解密翻译结果: 定位密文位置 使用获取的key进行AES解密 关键点总结 JavaScript混淆的核心目标是使代码不可读和不可调试 现代混淆技术结合了多种方法增加逆向难度 反混淆需要结合工具、大模型和动态调试技术 实战中定位关键函数是逆向的核心步骤 Chrome开发者工具的高级功能能有效应对反调试