查看原文
其他

7.8k Star!一个强大的 JS 代码混淆工具

小秋 开源前哨 2022-09-24

【导语】:一个开源的代码混淆器,能将 JS 代码混淆成可读性低的代码。

简介

JavaScript Obfuscator 是一款功能强大的免费 JavaScript 混淆器,包含多种功能,能将代码混淆成可读性低的代码,看上去是难以阅读的代码,其实具备和之前代码一样的功能,从而起到保护代码的作用。

原代码:

function hi() {
  console.log("Hello World!");
}
hi();

混淆后代码:

function _0x5737(){var _0x3de046=['13797910djQtgr','202NzEpzv','2273TLhUKk','6976590XeTkcs','4633335tPFIvf','460SzVdaa','1260225mbbZER','49056QtXjli','1736NJoeHX','42116DYgHBM'];_0x5737=function(){return _0x3de046;};return _0x5737();}function _0x5e71(_0x1e04fb,_0x168fdd){var _0x57378a=_0x5737();return _0x5e71=function(_0x5e7194,_0x30106f){_0x5e7194=_0x5e7194-0xb6;var _0x3c5c20=_0x57378a[_0x5e7194];return _0x3c5c20;},_0x5e71(_0x1e04fb,_0x168fdd);}(function(_0x41d572,_0x45db5e){var _0x306ede=_0x5e71,_0x408f15=_0x41d572();while(!![]){try{var _0x4c3c37=-parseInt(_0x306ede(0xbb))/0x1*(parseInt(_0x306ede(0xba))/0x2)+-parseInt(_0x306ede(0xbd))/0x3+parseInt(_0x306ede(0xb8))/0x4*(parseInt(_0x306ede(0xbe))/0x5)+-parseInt(_0x306ede(0xbc))/0x6+-parseInt(_0x306ede(0xb6))/0x7*(-parseInt(_0x306ede(0xb7))/0x8)+-parseInt(_0x306ede(0xbf))/0x9+parseInt(_0x306ede(0xb9))/0xa;if(_0x4c3c37===_0x45db5e)break;else _0x408f15['push'](_0x408f15['shift']());}catch(_0x8596b2){_0x408f15['push'](_0x408f15['shift']());}}}(_0x5737,0xc1743));function hi(){console['log']('Hello\x20World!');}hi();

主要特点:

  • 变量重命名
  • 字符串提取和加密
  • 随机添加无用代码进行混淆
  • 控制流扁平化
  • 各种代码转换 ...

支持的插件:

  • Webpack 插件: webpack-obfuscator
  • Webpack loader: obfuscator-loader
  • Gulp: gulp-javascript-obfuscator
  • Grunt: grunt-contrib-obfuscator
  • Rollup: rollup-plugin-javascript-obfuscator
  • Weex: weex-devtool
  • Malta: malta-js-obfuscator
  • Netlify 插件: netlify-plugin-js-obfuscator

项目地址是:

https://github.com/javascript-obfuscator/javascript-obfuscator

安装使用

使用 Yarn 或 Npm 安装

// yarn 安装
$ yarn add --dev javascript-obfuscator
// npm 安装
$ npm install --save-dev javascript-obfuscator

CDN 引入

<script src="https://cdn.jsdelivr.net/npm/javascript-obfuscator/dist/index.browser.js"></script>

用法

简单示例

var JavaScriptObfuscator = require('javascript-obfuscator');

var obfuscationResult = JavaScriptObfuscator.obfuscate(
    `
        (function(){
            var variable1 = '5' - 3;
            var variable2 = '5' + 3;
            var variable3 = '5' + - '2';
            var variable4 = ['10','10','10','10','10'].map(parseInt);
            var variable5 = 'foo ' + 1 + 1;
            console.log(variable1);
            console.log(variable2);
            console.log(variable3);
            console.log(variable4);
            console.log(variable5);
        })();
    `,
    {
        compact: false,
        controlFlowFlattening: true,
        controlFlowFlatteningThreshold: 1,
        numbersToExpressions: true,
        simplify: true,
        stringArrayShuffle: true,
        splitStrings: true,
        stringArrayThreshold: 1
    }
);

console.log(obfuscationResult.getObfuscatedCode());

输出结果:

var _0x9947 = [
    'map',
    'log',
    'foo\x20',
    'bvmqO',
    '133039ViRMWR',
    'xPfLC',
    'ytpdx',
    '1243717qSZCyh',
    '2|7|4|6|9|',
    '1ErtbCr',
    '1608314VKvthn',
    '1ZRaFKN',
    'XBoAA',
    '423266kQOYHV',
    '3|0|5|8|1',
    '235064xPNdKe',
    '13RUDZfG',
    '157gNPQGm',
    '1639212MvnHZL',
    'rDjOa',
    'iBHph',
    '9926iRHoRl',
    'split'
];
function _0x33e4(_0x1809b5, _0x37ef6e) {
    return _0x33e4 = function (_0x338a69, _0x39ad79) {
        _0x338a69 = _0x338a69 - (0x1939 + -0xf * 0x1f3 + 0x1 * 0x469);
        var _0x2b223a = _0x9947[_0x338a69];
        return _0x2b223a;
    }, _0x33e4(_0x1809b5, _0x37ef6e);
}
(function (_0x431d87, _0x156c7f) {
    var _0x10cf6e = _0x33e4;
    while (!![]) {
        try {
            var _0x330ad1 = -parseInt(_0x10cf6e(0x6c)) * -parseInt(_0x10cf6e(0x6d)) + -parseInt(_0x10cf6e(0x74)) * -parseInt(_0x10cf6e(0x78)) + parseInt(_0x10cf6e(0x6a)) + -parseInt(_0x10cf6e(0x70)) + parseInt(_0x10cf6e(0x6e)) * -parseInt(_0x10cf6e(0x75)) + parseInt(_0x10cf6e(0x72)) + -parseInt(_0x10cf6e(0x67)) * parseInt(_0x10cf6e(0x73));
            if (_0x330ad1 === _0x156c7f)
                break;
            else
                _0x431d87['push'](_0x431d87['shift']());
        } catch (_0x9f878) {
            _0x431d87['push'](_0x431d87['shift']());
        }
    }
}(_0x9947, -0xb6270 + 0x4dfd2 * 0x2 + 0x75460 * 0x2), function () {
    var _0x1f346d = _0x33e4, _0x860db8 = {
            'ytpdx': _0x1f346d(0x6b) + _0x1f346d(0x71),
            'bvmqO'function (_0x560787, _0x519b9e) {
                return _0x560787 - _0x519b9e;
            },
            'rDjOa'function (_0x4501fe, _0x2b07a3) {
                return _0x4501fe + _0x2b07a3;
            },
            'xPfLC'function (_0x5f3c9b, _0x434936) {
                return _0x5f3c9b + _0x434936;
            },
            'XBoAA'function (_0x535b8a, _0x42eef4) {
                return _0x535b8a + _0x42eef4;
            },
            'iBHph': _0x1f346d(0x65)
        }, _0x346c55 = _0x860db8[_0x1f346d(0x69)][_0x1f346d(0x79)]('|'), _0x3bf817 = 0x4bb * 0x1 + 0x801 + -0xcbc;
    while (!![]) {
        switch (_0x346c55[_0x3bf817++]) {
        case '0':
            console[_0x1f346d(0x7b)](_0x4c96d8);
            continue;
        case '1':
            console[_0x1f346d(0x7b)](_0x101028);
            continue;
        case '2':
            var _0x65977d = _0x860db8[_0x1f346d(0x66)]('5', -0x586 + -0x2195 + -0x6 * -0x685);
            continue;
        case '3':
            console[_0x1f346d(0x7b)](_0x65977d);
            continue;
        case '4':
            var _0x56d39b = _0x860db8[_0x1f346d(0x76)]('5', -'2');
            continue;
        case '5':
            console[_0x1f346d(0x7b)](_0x56d39b);
            continue;
        case '6':
            var _0x544285 = [
                '10',
                '10',
                '10',
                '10',
                '10'
            ][_0x1f346d(0x7a)](parseInt);
            continue;
        case '7':
            var _0x4c96d8 = _0x860db8[_0x1f346d(0x68)]('5', 0x622 * -0x6 + 0x4a * 0x3 + 0x1 * 0x23f1);
            continue;
        case '8':
            console[_0x1f346d(0x7b)](_0x544285);
            continue;
        case '9':
            var _0x101028 = _0x860db8[_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x77)], 0x6fb * 0x5 + 0x1ebf * 0x1 + -0x41a5), 0x209 * 0xa + 0x1314 + -0x276d);
            continue;
        }
        break;
    }
}());

obfuscate(sourceCode, options) 方法

该方法返回的对象 ObfuscationResult 包含以下公共方法:

  • getObfuscatedCode()- 返回混淆后的代码字符串(对 ObfuscationResult 对象调用 toString() 方法也将返回混淆代码);
  • getSourceMap()- 如果 sourceMapMode 选项设置为 inline,则返回原代码或空字符串;
  • getIdentifierNamesCache()- 如果 identifierNamesCache 选项为启用,则返回带有标识符名称的缓存对象,否则返回 null。

该方法包含两个参数:

  • sourceCode(string, default:null) – 字符串原代码;
  • options(Object, default:null) – 可选的设置选项 options 对象,具体有:
{
    compact: true,
    controlFlowFlattening: false,
    controlFlowFlatteningThreshold: 0.75,
    deadCodeInjection: false,
    deadCodeInjectionThreshold: 0.4,
    debugProtection: false,
    debugProtectionInterval: false,
    disableConsoleOutput: false,
    domainLock: [],
    domainLockRedirectUrl: 'about:blank',
    forceTransformStrings: [],
    identifierNamesCache: null,
    identifierNamesGenerator: 'hexadecimal',
    identifiersDictionary: [],
    identifiersPrefix: '',
    ignoreRequireImports: false,
    inputFileName: '',
    logfalse,
    numbersToExpressions: false,
    optionsPreset: 'default',
    renameGlobals: false,
    renameProperties: false,
    renamePropertiesMode: 'safe',
    reservedNames: [],
    reservedStrings: [],
    seed: 0,
    selfDefending: false,
    simplify: true,
    sourceMap: false,
    sourceMapBaseUrl: '',
    sourceMapFileName: '',
    sourceMapMode: 'separate',
    sourceMapSourcesMode: 'sources-content',
    splitStrings: false,
    splitStringsChunkLength: 10,
    stringArray: true,
    stringArrayIndexesType: [
        'hexadecimal-number'
    ],
    stringArrayEncoding: [],
    stringArrayIndexShift: true,
    stringArrayRotate: true,
    stringArrayShuffle: true,
    stringArrayWrappersCount: 1,
    stringArrayWrappersChainedCalls: true,
    stringArrayWrappersParametersMaxCount: 2,
    stringArrayWrappersType: 'variable',
    stringArrayThreshold: 0.75,
    target: 'browser',
    transformObjectKeys: false,
    unicodeEscapeSequence: false
}

obfuscateMultiple(sourceCodesObject, options) 方法

sourceCodesObject 是字典键值对象,其中键是源代码的标识符,值是原代码:

{
    foo: 'var foo = 1;',
    bar: 'var bar = 2;'
}

该方法也返回一个字典键值对象,其键是原代码的标识符,值是 ObfuscationResult对象。

命令行使用

混淆单个文件

带有 .js 扩展名的单个文件的混淆:

javascript-obfuscator input_file_name.js [options]
javascript-obfuscator input_file_name.js --output output_file_name.js [options]
javascript-obfuscator input_file_name.js --output output_folder_name [options]
javascript-obfuscator input_folder_name --output output_folder_name [options]

如果没有使用 --output 指定输出路径,则混淆后的结果文件将存放到输入文件的目录中:

// 这会创建一个新文件 samples/sample-obfuscated.js
javascript-obfuscator samples/sample.js --compact true --self-defending false

// 这会创建一个新文件 output/output.js
javascript-obfuscator samples/sample.js --output output/output.js --compact true --self-defending false

递归混淆目录下的文件

混淆输入目录下的所有 .js 文件。如果目录中包含已经带有 -obfuscated 后缀的混淆文件,则忽略这些文件。

// 输出结果到 ./dist 同级目录下带有 obfuscated 后缀的目录中
javascript-obfuscator ./dist [options]

// 输出结果到 ./dist/obfuscated 目录中
javascript-obfuscator ./dist --output ./dist/obfuscated [options]
// creates a folder structure with obfuscated files under `./dist/obfuscated` path


- EOF - 


更多优秀开源项目(点击下方图片可跳转)




开源前哨

日常分享热门、有趣和实用的开源项目。参与维护10万+star 的开源技术资源库,包括:Python, Java, C/C++, Go, JS, CSS, Node.js, PHP, .NET 等

关注后获取

回复 资源 获取 10万+ star 开源资源



分享点赞在看

支持我们分享更多优秀开源项目,谢谢!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存