深度 JavaScript 代码混淆技术

结合 Terser 与多种混淆技术,打造难以逆向的安全代码方案

什么是代码混淆?

从基础压缩到深度保护

代码混淆是一系列通过转换代码结构但保留功能的技术集合,目的是使代码难以理解和逆向工程。单一工具往往难以提供足够的保护强度,而结合多种技术的深度混淆方案能显著提高代码安全性。

压缩混淆

Terser等工具通过删除空格、缩短变量名实现基础保护

转换混淆

通过控制流扁平化、字符串加密等技术增加复杂度

多层保护

结合多种工具链和技术形成纵深防御体系

不同混淆级别的对比

从基础到深度混淆的效果差异

混淆级别 使用工具 保护强度 适用场景
基础压缩 Terser (基础配置)
仅需减小体积,无安全需求
标准混淆 Terser (高级配置)
一般商业项目,防止简单复制
深度混淆 Terser + 专业混淆工具 + 构建工具
核心算法、付费产品、敏感逻辑
基础操作

Terser 基础使用步骤

快速回顾 Terser 的基础使用方法,为深度混淆做准备

1

环境准备

安装 Node.js 和 Terser 基础环境

npm install -g terser
2

基础混淆

使用基本命令处理单个文件

terser input.js -o output.js
3

高级参数

添加压缩和混淆参数增强效果

terser input.js -o output.js --compress --mangle
4

配置文件

使用配置文件管理复杂规则

terser input.js -o output.js --config-file config.json
Terser 进阶

Terser 高级混淆参数

掌握 Terser 高级参数配置,为深度混淆打好基础

核心混淆参数详解

压缩配置 (--compress)

控制代码压缩和优化程度的关键参数

{
  "compress": {
    "drop_console": true,    // 删除所有console语句
    "dead_code": true,       // 移除未使用的代码
    "drop_debugger": true,   // 删除debugger语句
    "evaluate": true,        // 计算常量表达式
    "join_vars": true,       // 合并连续变量声明
    "collapse_vars": true,   // 折叠单个使用的变量
    "reduce_vars": true      // 重命名变量以提高压缩率
  }
}

混淆配置 (--mangle)

控制变量名和函数名混淆的参数

{
  "mangle": {
    "toplevel": true,        // 混淆顶层作用域的变量
    "eval": true,            // 混淆eval中的变量
    "properties": {          // 混淆对象属性
      "regex": "^_"          // 只混淆以下划线开头的属性
    },
    "reserved": ["$", "jQuery"]  // 保留不混淆的名称
  }
}

完整Terser配置示例

兼顾混淆强度和代码兼容性的平衡配置

// terser.config.json
{
  "compress": {
    "drop_console": true,
    "dead_code": true,
    "drop_debugger": true,
    "evaluate": true,
    "join_vars": true,
    "collapse_vars": true,
    "reduce_vars": true,
    "booleans": true,
    "comparisons": true,
    "conditionals": true,
    "loops": true,
    "unused": true
  },
  "mangle": {
    "toplevel": true,
    "eval": true,
    "properties": {
      "regex": "^_"
    },
    "reserved": ["$", "exports", "require"]
  },
  "output": {
    "comments": false,
    "beautify": false,
    "indent_level": 0
  }
}

使用方法:

terser input.js -o output.js --config-file terser.config.json

深度保护方案

结合其他技术的深度混淆

单一工具防护有限,多种技术组合才能实现真正的深度混淆

1

Terser + JavaScript Obfuscator

JavaScript Obfuscator 是专业的代码混淆工具,提供控制流扁平化、字符串加密等高级功能,与 Terser 结合可大幅提升混淆强度。

实施步骤:

  1. 1

    安装 JavaScript Obfuscator 工具

    npm install -g javascript-obfuscator
  2. 2

    第一步:使用 Terser 进行压缩和初级混淆

    terser input.js -o step1.js --config-file terser.config.json
  3. 3

    第二步:使用 JavaScript Obfuscator 进行深度混淆

    javascript-obfuscator step1.js -o final_obfuscated.js --config obfuscator.config.json

JavaScript Obfuscator 配置文件 (obfuscator.config.json):

{
  "compact": true,                // 紧凑输出
  "controlFlowFlattening": true,  // 控制流扁平化(显著增加复杂度)
  "controlFlowFlatteningThreshold": 0.75,
  "deadCodeInjection": true,      // 注入死代码
  "deadCodeInjectionThreshold": 0.4,
  "debugProtection": false,       // 防调试保护(会影响性能)
  "debugProtectionInterval": false,
  "disableConsoleOutput": true,   // 禁用console输出
  "identifierNamesGenerator": "hexadecimal", // 标识符生成方式
  "log": false,
  "numbersToExpressions": true,   // 数字转为表达式
  "renameGlobals": false,         // 不重命名全局变量
  "selfDefending": true,          // 自我保护(防止格式化)
  "simplify": true,
  "splitStrings": true,           // 分割字符串
  "splitStringsChunkLength": 5,
  "stringArray": true,            // 字符串数组加密
  "stringArrayCallsTransform": true,
  "stringArrayCallsTransformThreshold": 0.75,
  "stringArrayEncoding": ["base64"], // 字符串编码方式
  "stringArrayIndexShift": true,
  "stringArrayRotate": true,
  "stringArrayShuffle": true,
  "stringArrayWrappersCount": 2,
  "stringArrayWrappersChainedCalls": true,
  "stringArrayWrappersType": "function",
  "stringArrayThreshold": 0.75,
  "transformObjectKeys": true,    // 转换对象键名
  "unicodeEscapeSequence": false  // 不使用Unicode转义
}

优点

  • 极高的混淆强度,逆向难度大
  • 多种混淆技术组合,防护全面
  • 可定制性强,能平衡安全性和性能

缺点

  • 代码体积显著增加(2-5倍)
  • 可能影响代码性能(10-30%损耗)
  • 复杂配置可能导致兼容性问题
2

Terser + Webpack + 混淆插件

对于前端工程化项目,可在构建流程中集成混淆步骤,通过Webpack插件实现自动化的Terser压缩与额外混淆处理,适合大型项目。

实施步骤:

  1. 1

    初始化项目并安装依赖

    npm init -y
    npm install --save-dev webpack webpack-cli
    npm install --save-dev terser-webpack-plugin
    npm install --save-dev javascript-obfuscator webpack-obfuscator
  2. 2

    配置 webpack.config.js

    const TerserPlugin = require('terser-webpack-plugin');
    const JavaScriptObfuscator = require('webpack-obfuscator');
    
    module.exports = {
      entry: './src/index.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
      mode: 'production',
      optimization: {
        minimizer: [
          new TerserPlugin({
            terserOptions: {
              // Terser 配置(参考之前的高级配置)
              compress: {
                drop_console: true,
                dead_code: true
              },
              mangle: {
                toplevel: true
              },
              output: {
                comments: false
              }
            }
          })
        ]
      },
      plugins: [
        // 在Terser处理后应用深度混淆
        new JavaScriptObfuscator({
          compact: true,
          controlFlowFlattening: true,
          stringArray: true,
          stringArrayEncoding: ['base64'],
          selfDefending: true
        }, ['exclude.js']) // 排除不需要混淆的文件
      ]
    };
  3. 3

    执行构建命令,自动生成混淆后的代码

    npx webpack --mode production

最佳实践:

  • 只在生产环境构建时启用深度混淆
  • 对第三方库和不需要保护的代码进行排除
  • 保留source map用于内部调试(但不要部署到生产环境)
  • 定期测试混淆后的代码功能完整性
3

多工具链组合深度混淆

对于极高安全需求的场景,可采用多重工具链组合,通过批处理脚本自动化多步骤混淆流程,最大化提升逆向难度。

工具链组合方案:

1
初始代码准备

整理需要混淆的源代码,移除调试信息

2
Babel 转换

使用Babel将高版本JS转为ES5,增加逆向难度

npx babel input.js --out-file step1.js --presets @babel/preset-env
3
Terser 压缩混淆

使用高级配置进行压缩和初级混淆

terser step1.js -o step2.js --config-file terser.config.json
4
JavaScript Obfuscator 处理

应用控制流扁平化和字符串加密

javascript-obfuscator step2.js -o step3.js --config obfuscator.config.json
5
自定义加密层

添加自定义加密逻辑,进一步保护核心代码

node custom-encrypt.js step3.js final-output.js
6
功能验证

测试最终代码功能完整性和性能

自动化批处理脚本 (obfuscate.bat):

@echo off
echo 开始多步骤深度混淆...

REM 设置输入输出文件名
set INPUT_FILE=source.js
set OUTPUT_FILE=final_obfuscated.js

REM 步骤1: Babel转换
echo 步骤1/5: Babel转换...
npx babel %INPUT_FILE% --out-file step1.js --presets @babel/preset-env

REM 步骤2: Terser压缩混淆
echo 步骤2/5: Terser处理...
terser step1.js -o step2.js --config-file terser.config.json

REM 步骤3: JavaScript Obfuscator处理
echo 步骤3/5: 高级混淆处理...
javascript-obfuscator step2.js -o step3.js --config obfuscator.config.json

REM 步骤4: 自定义加密
echo 步骤4/5: 应用自定义加密...
node custom-encrypt.js step3.js %OUTPUT_FILE%

REM 清理临时文件
echo 步骤5/5: 清理临时文件...
del step1.js step2.js step3.js

echo 混淆完成! 输出文件: %OUTPUT_FILE%
pause
效果展示

不同混淆方案的效果对比

直观了解单一工具与深度混淆方案的差异

原始代码

// 计算斐波那契数列
function fibonacci(n) {
  // 检查输入是否为正整数
  if (typeof n !== 'number' || n < 0 || !Number.isInteger(n)) {
    throw new Error('输入必须是正整数');
  }
  
  // 基础情况
  if (n === 0) return 0;
  if (n === 1) return 1;
  
  // 递归计算
  return fibonacci(n - 1) + fibonacci(n - 2);
}

// 测试函数
console.log('斐波那契数列第10项: ', fibonacci(10));

仅Terser混淆

function fibonacci(n){if("number"!=typeof n||n<0||!Number.isInteger(n))throw new Error("输入必须是正整数");if(0===n)return 0;if(1===n)return 1;return fibonacci(n-1)+fibonacci(n-2)}console.log("斐波那契数列第10项: ",fibonacci(10))

深度混淆方案

var _0x4e25=['log','斐波那契数列第10项: '];(function(_0x1f9a97,_0x4e2599){var _0x49f8f3=function(_0x55ae81){while(--_0x55ae81){_0x1f9a97['push'](_0x1f9a97['shift']());}};_0x49f8f3(++_0x4e2599);}(_0x4e25,0x14));var _0x49f8=function(_0x1f9a97,_0x4e2599){_0x1f9a97=_0x1f9a97-0x0;var _0x55ae81=_0x4e25[_0x1f9a97];return _0x55ae81;};function fibonacci(_0x55ae81){var _0x21e96d=function(){var _0x3f75f5=!![];return function(_0x191979,_0x35a8e0){var _0x145b16=_0x3f75f5?function(){if(_0x35a8e0){var _0x347f5a=_0x35a8e0['apply'](_0x191979,arguments);_0x35a8e0=null;return _0x347f5a;}}:function(){};};}();var _0x191979=_0x21e96d();_0x191979(this,function(){var _0x3f75f5=function(){var _0x347f5a=!![];return function(_0x29f76d,_0x3a595c){var _0x30795c=_0x347f5a?function(){if(_0x3a595c){var _0x1f9a97=_0x3a595c['apply'](_0x29f76d,arguments);_0x3a595c=null;return _0x1f9a97;}}:function(){};};}();var _0x35a8e0=_0x3f75f5();_0x35a8e0(this,function(){});});if('number'!==typeof _0x55ae81||_0x55ae81<0x0||!Number['isInteger'](_0x55ae81))throw new Error('输入必须是正整数');if(0x0===_0x55ae81)return 0x0;if(0x1===_0x55ae81)return 0x1;return fibonacci(_0x55ae81-0x1)+fibonacci(_0x55ae81-0x2);}console[_0x49f8('0x0')](_0x49f8('0x1'),fibonacci(0xa));

混淆指标对比

问题解答

深度混淆常见问题

解决多工具组合混淆时可能遇到的问题

选择适合的混淆方案

没有放之四海而皆准的混淆方案,需根据项目安全需求、性能要求和开发成本综合选择。对于核心代码,建议采用本文介绍的深度混淆方案,结合多种技术构建多层次防护体系。

回顾深度混淆方案