代码混淆是一系列通过转换代码结构但保留功能的技术集合,目的是使代码难以理解和逆向工程。单一工具往往难以提供足够的保护强度,而结合多种技术的深度混淆方案能显著提高代码安全性。
Terser等工具通过删除空格、缩短变量名实现基础保护
通过控制流扁平化、字符串加密等技术增加复杂度
结合多种工具链和技术形成纵深防御体系
从基础到深度混淆的效果差异
| 混淆级别 | 使用工具 | 保护强度 | 适用场景 |
|---|---|---|---|
| 基础压缩 | Terser (基础配置) |
|
仅需减小体积,无安全需求 |
| 标准混淆 | Terser (高级配置) |
|
一般商业项目,防止简单复制 |
| 深度混淆 | Terser + 专业混淆工具 + 构建工具 |
|
核心算法、付费产品、敏感逻辑 |
快速回顾 Terser 的基础使用方法,为深度混淆做准备
安装 Node.js 和 Terser 基础环境
npm install -g terser
使用基本命令处理单个文件
terser input.js -o output.js
添加压缩和混淆参数增强效果
terser input.js -o output.js --compress --mangle
使用配置文件管理复杂规则
terser input.js -o output.js --config-file config.json
掌握 Terser 高级参数配置,为深度混淆打好基础
控制代码压缩和优化程度的关键参数
{
"compress": {
"drop_console": true, // 删除所有console语句
"dead_code": true, // 移除未使用的代码
"drop_debugger": true, // 删除debugger语句
"evaluate": true, // 计算常量表达式
"join_vars": true, // 合并连续变量声明
"collapse_vars": true, // 折叠单个使用的变量
"reduce_vars": true // 重命名变量以提高压缩率
}
}
控制变量名和函数名混淆的参数
{
"mangle": {
"toplevel": true, // 混淆顶层作用域的变量
"eval": true, // 混淆eval中的变量
"properties": { // 混淆对象属性
"regex": "^_" // 只混淆以下划线开头的属性
},
"reserved": ["$", "jQuery"] // 保留不混淆的名称
}
}
兼顾混淆强度和代码兼容性的平衡配置
// 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
单一工具防护有限,多种技术组合才能实现真正的深度混淆
JavaScript Obfuscator 是专业的代码混淆工具,提供控制流扁平化、字符串加密等高级功能,与 Terser 结合可大幅提升混淆强度。
安装 JavaScript Obfuscator 工具
npm install -g javascript-obfuscator
第一步:使用 Terser 进行压缩和初级混淆
terser input.js -o step1.js --config-file terser.config.json
第二步:使用 JavaScript Obfuscator 进行深度混淆
javascript-obfuscator step1.js -o final_obfuscated.js --config 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转义
}
对于前端工程化项目,可在构建流程中集成混淆步骤,通过Webpack插件实现自动化的Terser压缩与额外混淆处理,适合大型项目。
初始化项目并安装依赖
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
配置 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']) // 排除不需要混淆的文件
]
};
执行构建命令,自动生成混淆后的代码
npx webpack --mode production
对于极高安全需求的场景,可采用多重工具链组合,通过批处理脚本自动化多步骤混淆流程,最大化提升逆向难度。
整理需要混淆的源代码,移除调试信息
使用Babel将高版本JS转为ES5,增加逆向难度
npx babel input.js --out-file step1.js --presets @babel/preset-env
使用高级配置进行压缩和初级混淆
terser step1.js -o step2.js --config-file terser.config.json
应用控制流扁平化和字符串加密
javascript-obfuscator step2.js -o step3.js --config obfuscator.config.json
添加自定义加密逻辑,进一步保护核心代码
node custom-encrypt.js step3.js final-output.js
测试最终代码功能完整性和性能
@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));
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));
解决多工具组合混淆时可能遇到的问题