【导语】:一个开源的代码混同器,能将 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...
装置应用
应用 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: '', log: false, 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.jsjavascript-obfuscator samples/sample.js --compact true --self-defending false// 这会创立一个新文件 output/output.jsjavascript-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
开源前哨
日常分享热门、乏味和实用的开源我的项目。参加保护 10万+ Star 的开源技术资源库,包含:Python、Java、C/C++、Go、JS、CSS、Node.js、PHP、.NET 等。