mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge branch 'dev'
# Conflicts: # CHANGELOG.md # dist/index.js # package.json # src/Nodes.ts # src/Obfuscator.ts # src/interfaces/nodes/INode.d.ts # src/node-obfuscators/CatchClauseObfuscator.ts # src/node-obfuscators/FunctionDeclarationObfuscator.ts # src/node-obfuscators/FunctionObfuscator.ts # src/node-obfuscators/MemberExpressionObfuscator.ts # src/node-obfuscators/ObjectExpressionObfuscator.ts # src/node-obfuscators/VariableDeclarationObfuscator.ts # test/functional-tests/node-obfuscators/FunctionObfuscator.spec.ts # test/functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec.ts # test/index.spec.ts # test/mocks/NodeMocks.ts # test/unit-tests/NodeUtils.spec.ts
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
import * as fs from 'fs';
|
||||
|
||||
if (!(<any>global)._babelPolyfill) {
|
||||
require('babel-polyfill');
|
||||
}
|
||||
|
||||
(function () {
|
||||
const JavaScriptObfuscator: any = require("../../index");
|
||||
|
||||
let start: any = new Date();
|
||||
|
||||
JavaScriptObfuscator.obfuscate(
|
||||
fs.readFileSync('test/fixtures/compile-performance.js', 'utf8')
|
||||
).getObfuscatedCode();
|
||||
|
||||
console.log(`Total time: ${<any>new Date() - start}`);
|
||||
})();
|
||||
@@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
|
||||
if (!(<any>global)._babelPolyfill) {
|
||||
require('babel-polyfill');
|
||||
}
|
||||
|
||||
(function () {
|
||||
const JavaScriptObfuscator: any = require("../../index");
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
var start = new Date();
|
||||
var log = console.log;
|
||||
console.log = function () {};
|
||||
|
||||
${String(`
|
||||
var result = 1,
|
||||
term1 = 0,
|
||||
term2 = 1,
|
||||
i = 1;
|
||||
while(i < 10)
|
||||
{
|
||||
var test = 10;
|
||||
result = term1 + term2;
|
||||
console.log(result);
|
||||
term1 = term2;
|
||||
term2 = result;
|
||||
i++;
|
||||
}
|
||||
|
||||
console.log(test);
|
||||
|
||||
var test = function (test) {
|
||||
console.log(test);
|
||||
|
||||
if (true) {
|
||||
var test = 5
|
||||
}
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
console.log(test(1));
|
||||
|
||||
function test2 (abc) {
|
||||
function test1 () {
|
||||
console.log('inside', abc.item);
|
||||
}
|
||||
|
||||
console.log('тест', abc);
|
||||
|
||||
var abc = {};
|
||||
|
||||
return abc.item = 15, test1();
|
||||
};
|
||||
|
||||
var regexptest = /version\\/(\\d+)/i;
|
||||
console.log(regexptest);
|
||||
|
||||
test2(22);
|
||||
console.log(105.4);
|
||||
console.log(true, false);
|
||||
|
||||
var sA = 'shorthand1';
|
||||
var sB = 'shorthand2';
|
||||
|
||||
console.log({sA, sB});
|
||||
|
||||
try {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
`).repeat(1000)}
|
||||
|
||||
console.log = log;
|
||||
console.log(new Date() - start);
|
||||
`,
|
||||
{
|
||||
disableConsoleOutput: false,
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
console.log(eval(obfuscatedCode));
|
||||
})();
|
||||
@@ -4,10 +4,11 @@ if (!(<any>global)._babelPolyfill) {
|
||||
require('babel-polyfill');
|
||||
}
|
||||
|
||||
const JavaScriptObfuscator: any = require("../../index");
|
||||
(function () {
|
||||
const JavaScriptObfuscator: any = require("../../index");
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
(function(){
|
||||
var result = 1,
|
||||
term1 = 0,
|
||||
@@ -67,11 +68,13 @@ let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
}
|
||||
})();
|
||||
`,
|
||||
{
|
||||
disableConsoleOutput: false,
|
||||
encodeUnicodeLiterals: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
{
|
||||
disableConsoleOutput: false,
|
||||
unicodeArrayEncoding: 'rc4',
|
||||
selfDefending: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
console.log(obfuscatedCode);
|
||||
console.log(eval(obfuscatedCode));
|
||||
console.log(obfuscatedCode);
|
||||
console.log(eval(obfuscatedCode));
|
||||
})();
|
||||
Vendored
+76382
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
var func = function () {
|
||||
return true;
|
||||
};
|
||||
var test = 1;
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
var test = 1;
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
bar();
|
||||
baz();
|
||||
foo();
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
var test = 1;
|
||||
}
|
||||
|
||||
bar();
|
||||
baz();
|
||||
foo();
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
var start = new Date();
|
||||
var log = console.log;
|
||||
|
||||
console.log = function () {};
|
||||
|
||||
(function () {
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
var test = 1;
|
||||
}
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
bar();
|
||||
})();
|
||||
console.log = log;
|
||||
console.log(new Date() - start);
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
var start = new Date();
|
||||
var log = console.log;
|
||||
|
||||
console.log = function () {};
|
||||
|
||||
(function () {
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
}
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
bar();
|
||||
})();
|
||||
console.log = log;
|
||||
console.log(new Date() - start);
|
||||
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
bar();
|
||||
baz();
|
||||
foo();
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
var test = 1;
|
||||
}
|
||||
|
||||
baz();
|
||||
foo();
|
||||
bar();
|
||||
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
baz();
|
||||
foo();
|
||||
bar();
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
var test = 1;
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
bar();
|
||||
baz();
|
||||
foo();
|
||||
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
bar();
|
||||
baz();
|
||||
foo();
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
var func = function () {
|
||||
return true;
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
var func1 = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
var func2 = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
var test = 1;
|
||||
|
||||
var func3 = function () {
|
||||
return 'string';
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
var func1 = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
var func2 = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
var func3 = function () {
|
||||
return 'string';
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
var test = 1;
|
||||
|
||||
var func = function () {
|
||||
return true;
|
||||
};
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
var func = function () {
|
||||
return true;
|
||||
};
|
||||
Vendored
+6
-1
@@ -46,8 +46,13 @@
|
||||
console.log(105.4);
|
||||
console.log(true, false);
|
||||
|
||||
var sA = 'shorthand1';
|
||||
var sB = 'shorthand2';
|
||||
|
||||
console.log({sA, sB});
|
||||
|
||||
try {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
})();
|
||||
})();
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
function inner2 () {
|
||||
var inner3 = function () {
|
||||
|
||||
};
|
||||
|
||||
inner3();
|
||||
}
|
||||
|
||||
inner2();
|
||||
inner1();
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
|
||||
baz();
|
||||
foo();
|
||||
bar();
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
bar();
|
||||
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
|
||||
}
|
||||
|
||||
function baz () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
inner1();
|
||||
}
|
||||
|
||||
baz();
|
||||
foo();
|
||||
@@ -0,0 +1,5 @@
|
||||
bar();
|
||||
|
||||
function bar () {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
var object = {
|
||||
foo: {
|
||||
baz: function () {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
bar: function () {
|
||||
function inner () {
|
||||
|
||||
}
|
||||
|
||||
inner();
|
||||
}
|
||||
};
|
||||
|
||||
var object1 = {
|
||||
foo: {
|
||||
baz: function () {
|
||||
|
||||
},
|
||||
|
||||
func: function () {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
'bar': function () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
inner1();
|
||||
}
|
||||
};
|
||||
|
||||
object1.foo.baz();
|
||||
object1['foo'].baz();
|
||||
object1['foo'].func();
|
||||
object1.bar();
|
||||
|
||||
object.bar();
|
||||
@@ -0,0 +1,27 @@
|
||||
bar();
|
||||
|
||||
function foo () {
|
||||
|
||||
}
|
||||
|
||||
function bar () {
|
||||
|
||||
}
|
||||
|
||||
function baz () {
|
||||
function inner1 () {
|
||||
|
||||
}
|
||||
|
||||
if (true) {
|
||||
switch (true) {
|
||||
case true:
|
||||
while (true) {
|
||||
inner1();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baz();
|
||||
foo();
|
||||
@@ -0,0 +1,7 @@
|
||||
function bar () {
|
||||
|
||||
}
|
||||
|
||||
function baz () {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
var bar = function () {
|
||||
};
|
||||
|
||||
bar();
|
||||
@@ -0,0 +1 @@
|
||||
bar();
|
||||
@@ -0,0 +1,11 @@
|
||||
(function foo (){
|
||||
(function bar (){
|
||||
!function baz (){
|
||||
inner();
|
||||
|
||||
function inner () {
|
||||
|
||||
}
|
||||
}();
|
||||
}());
|
||||
})();
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
|
||||
});
|
||||
|
||||
it('should returns object with obfuscated code with inline source map and empty `sourceMap` if `sourceMapMode` is `inline', () => {
|
||||
it('should returns object with obfuscated code with inline source map as Base64 string', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 1;`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
@@ -47,7 +47,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/sourceMappingURL=data:application\/json;base64/
|
||||
);
|
||||
assert.isNotOk(obfuscationResult.getSourceMap());
|
||||
assert.isOk(obfuscationResult.getSourceMap());
|
||||
});
|
||||
|
||||
it('should returns object with empty obfuscated code and source map with empty data if source code is empty', () => {
|
||||
@@ -102,29 +102,28 @@ describe('JavaScriptObfuscator', () => {
|
||||
});
|
||||
|
||||
it('should obfuscate simple code with literal variable value', () => {
|
||||
let pattern: RegExp = /^var _0x(\w){4} *= *\['(\\[x|u]\d+)+'\]; *var *test *= *_0x(\w){4}\[0x0\];$/;
|
||||
|
||||
assert.match(
|
||||
JavaScriptObfuscator.obfuscate(
|
||||
let pattern1: RegExp = /^var _0x(\w){4} *= *\['(\\[x|u]\d+)+'\];/,
|
||||
pattern2: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
|
||||
obfuscatedCode1: string = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'abc';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
).getObfuscatedCode(),
|
||||
pattern
|
||||
);
|
||||
|
||||
assert.match(
|
||||
JavaScriptObfuscator.obfuscate(
|
||||
obfuscatedCode2: string = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'абц';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
).getObfuscatedCode(),
|
||||
pattern
|
||||
);
|
||||
).getObfuscatedCode();
|
||||
|
||||
assert.match(obfuscatedCode1, pattern1);
|
||||
assert.match(obfuscatedCode1, pattern2);
|
||||
|
||||
assert.match(obfuscatedCode2, pattern1);
|
||||
assert.match(obfuscatedCode2, pattern2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,9 +2,9 @@ import * as fs from 'fs';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
import { StdoutWriteMock } from "../mocks/StdoutWriteMock";
|
||||
import { StdoutWriteMock } from '../mocks/StdoutWriteMock';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -87,34 +87,125 @@ describe('JavaScriptObfuscatorCLI', function (): void {
|
||||
describe('--sourceMap option is set', () => {
|
||||
let outputSourceMapPath: string = `${outputFilePath}.map`;
|
||||
|
||||
it('should creates file with source map in the same directory as output file', () => {
|
||||
JavaScriptObfuscator.runCLI([
|
||||
'node',
|
||||
'javascript-obfuscator',
|
||||
fixtureFilePath,
|
||||
'--output',
|
||||
outputFilePath,
|
||||
'--compact',
|
||||
'true',
|
||||
'--selfDefending',
|
||||
'0',
|
||||
'--sourceMap',
|
||||
'true'
|
||||
]);
|
||||
describe('--sourceMapMode option is `separate`', () => {
|
||||
it('should creates file with source map in the same directory as output file', () => {
|
||||
JavaScriptObfuscator.runCLI([
|
||||
'node',
|
||||
'javascript-obfuscator',
|
||||
fixtureFilePath,
|
||||
'--output',
|
||||
outputFilePath,
|
||||
'--compact',
|
||||
'true',
|
||||
'--selfDefending',
|
||||
'0',
|
||||
'--sourceMap',
|
||||
'true'
|
||||
]);
|
||||
|
||||
assert.equal(fs.existsSync(outputSourceMapPath), true);
|
||||
assert.equal(fs.existsSync(outputSourceMapPath), true);
|
||||
|
||||
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
|
||||
sourceMap: any = JSON.parse(content);
|
||||
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
|
||||
sourceMap: any = JSON.parse(content);
|
||||
|
||||
assert.property(sourceMap, 'version');
|
||||
assert.property(sourceMap, 'sources');
|
||||
assert.property(sourceMap, 'names');
|
||||
assert.property(sourceMap, 'version');
|
||||
assert.property(sourceMap, 'sources');
|
||||
assert.property(sourceMap, 'names');
|
||||
});
|
||||
|
||||
it('should creates file with source map in the same directory as output file if `sourceMapBaseUrl` is set', () => {
|
||||
JavaScriptObfuscator.runCLI([
|
||||
'node',
|
||||
'javascript-obfuscator',
|
||||
fixtureFilePath,
|
||||
'--output',
|
||||
outputFilePath,
|
||||
'--compact',
|
||||
'true',
|
||||
'--selfDefending',
|
||||
'0',
|
||||
'--sourceMap',
|
||||
'true',
|
||||
'--sourceMapBaseUrl',
|
||||
'http://localhost:9000/'
|
||||
]);
|
||||
|
||||
assert.equal(fs.existsSync(outputSourceMapPath), true);
|
||||
|
||||
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
|
||||
sourceMap: any = JSON.parse(content);
|
||||
|
||||
assert.property(sourceMap, 'version');
|
||||
assert.property(sourceMap, 'sources');
|
||||
assert.property(sourceMap, 'names');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.unlinkSync(outputSourceMapPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--sourceMapFileName option is set', () => {
|
||||
let sourceMapFileName: string = 'test',
|
||||
sourceMapFilePath: string = `${sourceMapFileName}.js.map`,
|
||||
outputSourceMapFilePath: string = `${outputDirName}/${sourceMapFilePath}`;
|
||||
|
||||
it('should creates source map file with given name in the same directory as output file', () => {
|
||||
JavaScriptObfuscator.runCLI([
|
||||
'node',
|
||||
'javascript-obfuscator',
|
||||
fixtureFilePath,
|
||||
'--output',
|
||||
outputFilePath,
|
||||
'--compact',
|
||||
'true',
|
||||
'--selfDefending',
|
||||
'0',
|
||||
'--sourceMap',
|
||||
'true',
|
||||
'--sourceMapFileName',
|
||||
sourceMapFileName
|
||||
]);
|
||||
|
||||
assert.equal(fs.existsSync(outputSourceMapFilePath), true);
|
||||
|
||||
const content: string = fs.readFileSync(outputSourceMapFilePath, { encoding: 'utf8' }),
|
||||
sourceMap: any = JSON.parse(content);
|
||||
|
||||
assert.property(sourceMap, 'version');
|
||||
assert.property(sourceMap, 'sources');
|
||||
assert.property(sourceMap, 'names');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.unlinkSync(outputSourceMapFilePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--sourceMapMode option is `inline`', () => {
|
||||
it('shouldn\'t create file with source map if `sourceMapMode` is `inline`', () => {
|
||||
JavaScriptObfuscator.runCLI([
|
||||
'node',
|
||||
'javascript-obfuscator',
|
||||
fixtureFilePath,
|
||||
'--output',
|
||||
outputFilePath,
|
||||
'--compact',
|
||||
'true',
|
||||
'--selfDefending',
|
||||
'0',
|
||||
'--sourceMap',
|
||||
'true',
|
||||
'--sourceMapMode',
|
||||
'inline'
|
||||
]);
|
||||
|
||||
assert.equal(fs.existsSync(outputSourceMapPath), false);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.unlinkSync(outputFilePath);
|
||||
fs.unlinkSync(outputSourceMapPath);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { JavaScriptObfuscatorInternal } from "../../src/JavaScriptObfuscatorInternal";
|
||||
import { JavaScriptObfuscatorInternal } from '../../src/JavaScriptObfuscatorInternal';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -10,28 +10,49 @@ describe('JavaScriptObfuscatorInternal', () => {
|
||||
describe(`setSourceMapUrl (url: string)`, () => {
|
||||
let javaScriptObfuscator: JavaScriptObfuscatorInternal,
|
||||
obfuscationResult: IObfuscationResult,
|
||||
sourceMapUrl: string = 'test.map.js';
|
||||
sourceMapUrl: string = 'test.js.map';
|
||||
|
||||
beforeEach(() => {
|
||||
it('should link obfuscated code with source map', () => {
|
||||
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
|
||||
`var test = 1;`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
sourceMapFileName: sourceMapUrl
|
||||
})
|
||||
);
|
||||
|
||||
javaScriptObfuscator.obfuscate();
|
||||
javaScriptObfuscator.setSourceMapUrl(sourceMapUrl);
|
||||
|
||||
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
|
||||
});
|
||||
|
||||
it('should link obfuscated code with source map', () => {
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
new RegExp(`sourceMappingURL=${sourceMapUrl}`))
|
||||
;
|
||||
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
|
||||
});
|
||||
|
||||
it('should properly add base url to source map import inside obfuscated code if `sourceMapBaseUrl` is set', () => {
|
||||
let sourceMapBaseUrl: string = 'http://localhost:9000';
|
||||
|
||||
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
|
||||
`var test = 1;`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
sourceMap: true,
|
||||
sourceMapBaseUrl: sourceMapBaseUrl,
|
||||
sourceMapFileName: sourceMapUrl
|
||||
})
|
||||
);
|
||||
|
||||
javaScriptObfuscator.obfuscate();
|
||||
|
||||
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
|
||||
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
new RegExp(`sourceMappingURL=${sourceMapBaseUrl}/${sourceMapUrl}$`))
|
||||
;
|
||||
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('ConsoleOutputDisableExpressionNode', () => {
|
||||
const regExp = /(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*)*'\]\['(\\x[a-f0-9]*)*'\] *= *_0x([a-z0-9]){4,6};){4}/;
|
||||
|
||||
it('should correctly appendNodeToOptimalBlockScope `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
disableConsoleOutput: true
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), regExp);
|
||||
});
|
||||
|
||||
it('should\'t appendNodeToOptimalBlockScope `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is not set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
disableConsoleOutput: false,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.notMatch(obfuscationResult.getObfuscatedCode(), regExp);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('DomainLockNode', () => {
|
||||
it('should correctly appendNodeToOptimalBlockScope `DomainLockNode` custom node into the obfuscated code if `domainLock` option is set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
domainLock: ['.example.com']
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
|
||||
});
|
||||
|
||||
it('should\'t appendNodeToOptimalBlockScope `DomainLockNode` custom node into the obfuscated code if `domainLock` option is not set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
domainLock: []
|
||||
})
|
||||
);
|
||||
|
||||
assert.notMatch(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
|
||||
});
|
||||
});
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('UnicodeArrayCallsWrapper', () => {
|
||||
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayCallsWrapper` custom node into the obfuscated code', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1,
|
||||
wrapUnicodeArrayCalls: true
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/var *_0x([a-z0-9]){4,6} *= *parseInt\(_0x([a-z0-9]){4,6}, *0x10\);/
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('UnicodeArrayNode', () => {
|
||||
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayNode` custom node into the obfuscated code if `unicodeArray` option is set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
|
||||
});
|
||||
|
||||
it('should\'t appendNodeToOptimalBlockScope `UnicodeArrayNode` custom node into the obfuscated code if `unicodeArray` option is not set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: false
|
||||
})
|
||||
);
|
||||
|
||||
assert.notMatch(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
|
||||
});
|
||||
});
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('UnicodeArrayRotateFunctionNode', () => {
|
||||
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayRotateFunctionNode` custom node into the obfuscated code if `rotateUnicodeArray` option is set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
rotateUnicodeArray: true,
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
|
||||
});
|
||||
|
||||
it('should\'t appendNodeToOptimalBlockScope `UnicodeArrayRotateFunctionNode` custom node into the obfuscated code if `rotateUnicodeArray` option is not set', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
rotateUnicodeArray: false,
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.notMatch(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -29,9 +29,9 @@ describe('FunctionObfuscator', () => {
|
||||
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
|
||||
|
||||
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/var _0x[a-z0-9]{5,6} *= *function *\((_0x[a-z0-9]{5,6})\) *\{/);
|
||||
.match(/var _0x[a-z0-9]{4,6} *= *function *\((_0x[a-z0-9]{4,6})\) *\{/);
|
||||
const functionBodyIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
|
||||
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
|
||||
|
||||
const functionParamIdentifierName: string = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
|
||||
const functionBodyIdentifierName: string = (<RegExpMatchArray>functionBodyIdentifierMatch)[1];
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('LiteralObfuscator', () => {
|
||||
describe('obfuscation of literal node with string value', () => {
|
||||
it('should replace literal node value with unicode value without encoding to base64', () => {
|
||||
it('should replace literal node value with unicode value without encoding', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
@@ -17,26 +17,72 @@ describe('LiteralObfuscator', () => {
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
|
||||
});
|
||||
|
||||
it('should replace literal node value with unicode value with encoding to base64', () => {
|
||||
it('should replace literal node value with unicode array value', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
encodeUnicodeLiterals: true,
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /^var *_0x([a-z0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/);
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/^var *_0x([a-z0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
|
||||
);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
|
||||
});
|
||||
|
||||
it('shouldn\'t replace short literal node value with unicode array value', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'te';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *'\\x74\\x65';/);
|
||||
});
|
||||
|
||||
it('should replace literal node value with unicode array value encoded using base64', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayEncoding: 'base64',
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/^var *_0x([a-z0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/
|
||||
);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
|
||||
});
|
||||
|
||||
it('should replace literal node value with unicode array value encoded using rc4', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 'test';`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
unicodeArray: true,
|
||||
unicodeArrayEncoding: 'rc4',
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
);
|
||||
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/var *test *= *_0x([a-z0-9]){4}\('0x0', '(\\x[a-f0-9]*){4}'\);/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should obfuscate literal node with boolean value', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = true;`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
encodeUnicodeLiterals: true,
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
@@ -49,7 +95,6 @@ describe('LiteralObfuscator', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`var test = 0;`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
|
||||
encodeUnicodeLiterals: true,
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 1
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('MemberExpressionObfuscator', () => {
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\[0x0\]\];/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('MemberExpressionObfuscator', () => {
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\[0x0\]\];/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
|
||||
});
|
||||
|
||||
it('should ignore square brackets call with identifier value', () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('MethodDefinitionObfuscator', () => {
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /\[_0x([a-z0-9]){4}\[0x0\]\]\(\)\{\}/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /\[_0x([a-z0-9]){4}\('0x0'\)\]\(\)\{\}/);
|
||||
});
|
||||
|
||||
it('should not obfuscate method definition node with `constructor` key', () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('ObjectExpressionObfuscator', () => {
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *\{'\\x66\\x6f\\x6f':0x0\};$/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
|
||||
});
|
||||
|
||||
it('should replace object expression node `key` property with identifier value by unicode value', () => {
|
||||
@@ -22,7 +22,25 @@ describe('ObjectExpressionObfuscator', () => {
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *\{'\\x66\\x6f\\x6f':0x0\};$/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
|
||||
});
|
||||
|
||||
it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
(function () {
|
||||
let a = 0;
|
||||
let b = 0;
|
||||
var test = {a, b};
|
||||
})();
|
||||
`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
|
||||
assert.match(
|
||||
obfuscationResult.getObfuscatedCode(),
|
||||
/var *_0x[a-z0-9]{4,6} *= *\{'\\x61': *_0x[a-z0-9]{4,6}\, *'\\x62': *_0x[a-z0-9]{4,6}\};/
|
||||
);
|
||||
});
|
||||
|
||||
it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
|
||||
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
|
||||
|
||||
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -38,64 +38,6 @@ describe('VariableDeclarationObfuscator', () => {
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
|
||||
});
|
||||
|
||||
describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
|
||||
let obfuscationResult: IObfuscationResult,
|
||||
functionParamIdentifierName: string|null,
|
||||
innerFunctionParamIdentifierName: string|null,
|
||||
constructorIdentifierName: string|null,
|
||||
objectIdentifierName: string|null,
|
||||
variableDeclarationIdentifierName: string|null;
|
||||
|
||||
beforeEach(() => {
|
||||
obfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
(function () {
|
||||
function foo (t, e) {
|
||||
return function () {
|
||||
function baz (t) {
|
||||
console.log(t);
|
||||
}
|
||||
|
||||
return {t: t};
|
||||
var t;
|
||||
}();
|
||||
}
|
||||
})();
|
||||
`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
});
|
||||
|
||||
it('should correct obfuscate variables inside function body', () => {
|
||||
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
|
||||
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/function *_0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\,(_0x[a-z0-9]{5,6})\) *\{/);
|
||||
const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/function _0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\) *\{/);
|
||||
const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
|
||||
const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/return\{'\\x74':(_0x[a-z0-9]{5,6})\}/);
|
||||
const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/var *(_0x[a-z0-9]{5,6});/);
|
||||
|
||||
functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
|
||||
innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
|
||||
constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
|
||||
objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
|
||||
variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
|
||||
|
||||
assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
|
||||
assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
|
||||
|
||||
assert.equal(functionParamIdentifierName, objectIdentifierName);
|
||||
assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
|
||||
|
||||
assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
|
||||
assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not obfuscate variable call (`identifier` node) outside of block scope of node in which this variable was declared with `let` kind', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
@@ -140,7 +82,106 @@ describe('VariableDeclarationObfuscator', () => {
|
||||
});
|
||||
|
||||
it('should not obfuscate variable call (`identifier` node) before variable declaration', () => {
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){5,6}\);/);
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
|
||||
let obfuscationResult: IObfuscationResult,
|
||||
functionParamIdentifierName: string|null,
|
||||
innerFunctionParamIdentifierName: string|null,
|
||||
constructorIdentifierName: string|null,
|
||||
objectIdentifierName: string|null,
|
||||
variableDeclarationIdentifierName: string|null;
|
||||
|
||||
beforeEach(() => {
|
||||
obfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
(function () {
|
||||
function foo (t, e) {
|
||||
return function () {
|
||||
function baz (t) {
|
||||
console.log(t);
|
||||
}
|
||||
|
||||
return {t: t};
|
||||
var t;
|
||||
}();
|
||||
}
|
||||
})();
|
||||
`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
});
|
||||
|
||||
it('should correct obfuscate variables inside function body', () => {
|
||||
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
|
||||
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/function *_0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\,(_0x[a-z0-9]{4,6})\) *\{/);
|
||||
const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/function _0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\) *\{/);
|
||||
const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
|
||||
const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/return\{'\\x74':(_0x[a-z0-9]{4,6})\}/);
|
||||
const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
|
||||
.match(/var *(_0x[a-z0-9]{4,6});/);
|
||||
|
||||
functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
|
||||
innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
|
||||
constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
|
||||
objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
|
||||
variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
|
||||
|
||||
assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
|
||||
assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
|
||||
|
||||
assert.equal(functionParamIdentifierName, objectIdentifierName);
|
||||
assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
|
||||
|
||||
assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
|
||||
assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('wrong replacement', () => {
|
||||
it('shouldn\'t replace property node identifier', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
function foo () {
|
||||
var test = 'abc';
|
||||
|
||||
var object = {
|
||||
test: 'cde'
|
||||
};
|
||||
|
||||
console.log(test);
|
||||
}
|
||||
`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
|
||||
});
|
||||
|
||||
it('shouldn\'t replace computed member expression identifier', () => {
|
||||
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
function foo () {
|
||||
var test = 'abc';
|
||||
|
||||
var object = {
|
||||
'test': 'cde'
|
||||
};
|
||||
|
||||
console.log(test);
|
||||
console.log(object.test);
|
||||
}
|
||||
`,
|
||||
Object.assign({}, NO_CUSTOM_NODES_PRESET)
|
||||
);
|
||||
|
||||
assert.match(obfuscationResult.getObfuscatedCode(), /_0x([a-z0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
import * as chai from 'chai';
|
||||
import * as estraverse from 'estraverse';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TNodeWithBlockStatement } from '../../../src/types/TNodeWithBlockStatement';
|
||||
|
||||
import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData';
|
||||
|
||||
import { readFileAsString } from '../../helpers/readFileAsString';
|
||||
|
||||
import { Nodes } from '../../../src/Nodes';
|
||||
import { NodeMocks } from '../../mocks/NodeMocks';
|
||||
import { NodeUtils } from '../../../src/NodeUtils';
|
||||
import { StackTraceAnalyzer } from '../../../src/stack-trace-analyzer/StackTraceAnalyzer';
|
||||
|
||||
const assert: any = chai.assert;
|
||||
|
||||
/**
|
||||
* @param astTree
|
||||
* @param name
|
||||
* @returns {ESTree.FunctionDeclaration|null}
|
||||
*/
|
||||
function getFunctionDeclarationByName (astTree: ESTree.Node, name: string): ESTree.FunctionDeclaration|null {
|
||||
let functionDeclarationNode: ESTree.FunctionDeclaration|null = null;
|
||||
|
||||
estraverse.traverse(astTree, {
|
||||
enter: (node: ESTree.Node): any => {
|
||||
if (
|
||||
Nodes.isFunctionDeclarationNode(node) &&
|
||||
Nodes.isIdentifierNode(node.id) &&
|
||||
node.id.name === name
|
||||
) {
|
||||
functionDeclarationNode = node;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return functionDeclarationNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param astTree
|
||||
* @param name
|
||||
* @returns {ESTree.FunctionExpression|null}
|
||||
*/
|
||||
function getFunctionExpressionByName (astTree: ESTree.Node, name: string): ESTree.FunctionExpression|null {
|
||||
let functionExpressionNode: ESTree.FunctionExpression|null = null;
|
||||
|
||||
estraverse.traverse(astTree, {
|
||||
enter: (node: ESTree.Node): any => {
|
||||
if (
|
||||
Nodes.isVariableDeclaratorNode(node) &&
|
||||
node.init &&
|
||||
Nodes.isFunctionExpressionNode(node.init) &&
|
||||
Nodes.isIdentifierNode(node.id) &&
|
||||
node.id.name === name
|
||||
) {
|
||||
functionExpressionNode = node.init;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return functionExpressionNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param astTree
|
||||
* @param id
|
||||
* @returns {ESTree.FunctionExpression|null}
|
||||
*/
|
||||
function getFunctionExpressionById (astTree: ESTree.Node, id: string): ESTree.FunctionExpression|null {
|
||||
let functionExpressionNode: ESTree.FunctionExpression|null = null;
|
||||
|
||||
estraverse.traverse(astTree, {
|
||||
enter: (node: ESTree.Node): any => {
|
||||
if (
|
||||
Nodes.isFunctionExpressionNode(node) &&
|
||||
node.id &&
|
||||
Nodes.isIdentifierNode(node.id) &&
|
||||
node.id.name === id
|
||||
) {
|
||||
functionExpressionNode = node;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return functionExpressionNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param astTree
|
||||
* @param objectName
|
||||
* @param name
|
||||
* @returns {ESTree.FunctionExpression|null}
|
||||
*/
|
||||
function getObjectFunctionExpressionByName (astTree: ESTree.Node, objectName: string, name: string): ESTree.FunctionExpression|null {
|
||||
let functionExpressionNode: ESTree.FunctionExpression|null = null,
|
||||
targetObjectExpressionNode: ESTree.ObjectExpression|null = null;
|
||||
|
||||
estraverse.traverse(astTree, {
|
||||
enter: (node: ESTree.Node): any => {
|
||||
if (
|
||||
Nodes.isVariableDeclaratorNode(node) &&
|
||||
Nodes.isIdentifierNode(node.id) &&
|
||||
node.init &&
|
||||
Nodes.isObjectExpressionNode(node.init) &&
|
||||
node.id.name === objectName
|
||||
) {
|
||||
targetObjectExpressionNode = node.init;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!targetObjectExpressionNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
estraverse.traverse(targetObjectExpressionNode, {
|
||||
enter: (node: ESTree.Node): any => {
|
||||
if (
|
||||
Nodes.isPropertyNode(node) &&
|
||||
Nodes.isFunctionExpressionNode(node.value) &&
|
||||
(
|
||||
(Nodes.isIdentifierNode(node.key) && node.key.name === name) ||
|
||||
(Nodes.isLiteralNode(node.key) && node.key.value === name)
|
||||
)
|
||||
) {
|
||||
functionExpressionNode = node.value;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return functionExpressionNode;
|
||||
}
|
||||
|
||||
describe('StackTraceAnalyzer', () => {
|
||||
describe('extract (): IStackTraceData[]', () => {
|
||||
let astTree: TNodeWithBlockStatement,
|
||||
stackTraceData: IStackTraceData[],
|
||||
expectedStackTraceData: IStackTraceData[];
|
||||
|
||||
it('should returns correct IStackTraceData - variant #1: basic-1', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/basic-1.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'baz',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'foo',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner2',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner2')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner3',
|
||||
callee: (<ESTree.FunctionExpression>getFunctionExpressionByName(astTree, 'inner3')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'inner1',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #2: basic-2', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/basic-2.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner1',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'foo',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
|
||||
stackTrace: []
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #3: deep conditions nesting', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/deep-conditions-nesting.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner1',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'foo',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
|
||||
stackTrace: []
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #4: call before declaration', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/call-before-declaration.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
|
||||
stackTrace: []
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #5: call expression of object member', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/call-expression-of-object-member.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'baz',
|
||||
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'baz')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'baz')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'func',
|
||||
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'func')).body,
|
||||
stackTrace: []
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'bar')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner1',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
|
||||
stackTrace: [
|
||||
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object', 'bar')).body,
|
||||
stackTrace: [
|
||||
{
|
||||
name: 'inner',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner')).body,
|
||||
stackTrace: [
|
||||
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #6: no call expressions', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/no-call-expressions.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #7: only call expression', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/only-call-expression.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #8: self-invoking functions', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/self-invoking-functions.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: null,
|
||||
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'foo')).body,
|
||||
stackTrace: [{
|
||||
name: null,
|
||||
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'bar')).body,
|
||||
stackTrace: [{
|
||||
name: null,
|
||||
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'baz')).body,
|
||||
stackTrace: [{
|
||||
name: 'inner',
|
||||
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner')).body,
|
||||
stackTrace: []
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
|
||||
it('should returns correct BlockScopeTraceData - variant #9: no recursion', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/stack-trace-analyzer/no-recursion.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedStackTraceData = [
|
||||
{
|
||||
name: 'bar',
|
||||
callee: (<ESTree.FunctionExpression>getFunctionExpressionByName(astTree, 'bar')).body,
|
||||
stackTrace: []
|
||||
}
|
||||
];
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
|
||||
assert.deepEqual(stackTraceData, expectedStackTraceData);
|
||||
});
|
||||
});
|
||||
});
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import 'format-unicorn';
|
||||
|
||||
import { DomainLockNodeTemplate } from '../../../../../src/templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
|
||||
|
||||
import { Utils } from '../../../../../src/Utils';
|
||||
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
/**
|
||||
* @param templateData
|
||||
* @param callsControllerFunctionName
|
||||
* @param currentDomain
|
||||
* @returns {Function}
|
||||
*/
|
||||
function getFunctionFromTemplate (templateData: any, callsControllerFunctionName: string, currentDomain: string) {
|
||||
let domainLockTemplate: string = DomainLockNodeTemplate().formatUnicorn(templateData);
|
||||
|
||||
return Function(`
|
||||
document = {
|
||||
domain: '${currentDomain}'
|
||||
};
|
||||
|
||||
var ${callsControllerFunctionName} = (function(){
|
||||
return function (context, fn){
|
||||
return function () {
|
||||
return fn.apply(context, arguments);
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
${domainLockTemplate}
|
||||
`)();
|
||||
}
|
||||
|
||||
describe('DomainLockNodeTemplate (): string', () => {
|
||||
let domainsString: string,
|
||||
currentDomain: string,
|
||||
hiddenDomainsString: string,
|
||||
diff: string,
|
||||
singleNodeCallControllerFunctionName: string = 'callsController';
|
||||
|
||||
it('should correctly runs code inside template if current domain matches with `domainsString`', () => {
|
||||
domainsString = ['www.example.com'].join(';');
|
||||
currentDomain = 'www.example.com';
|
||||
[
|
||||
hiddenDomainsString,
|
||||
diff
|
||||
] = Utils.hideString(domainsString, domainsString.length * 3);
|
||||
|
||||
assert.doesNotThrow(() => getFunctionFromTemplate({
|
||||
domainLockFunctionName: 'domainLockFunction',
|
||||
diff: diff,
|
||||
domains: hiddenDomainsString,
|
||||
singleNodeCallControllerFunctionName
|
||||
}, singleNodeCallControllerFunctionName, currentDomain));
|
||||
});
|
||||
|
||||
it('should correctly runs code inside template if current domain matches with base domain of `domainsString` item', () => {
|
||||
domainsString = ['www.test.com', '.example.com'].join(';');
|
||||
currentDomain = 'subdomain.example.com';
|
||||
[
|
||||
hiddenDomainsString,
|
||||
diff
|
||||
] = Utils.hideString(domainsString, domainsString.length * 3);
|
||||
|
||||
assert.doesNotThrow(() => getFunctionFromTemplate({
|
||||
domainLockFunctionName: 'domainLockFunction',
|
||||
diff: diff,
|
||||
domains: hiddenDomainsString,
|
||||
singleNodeCallControllerFunctionName
|
||||
}, singleNodeCallControllerFunctionName, currentDomain));
|
||||
});
|
||||
|
||||
it('should throw an error if current domain doesn\'t match with `domainsString`', () => {
|
||||
domainsString = ['www.example.com'].join(';');
|
||||
currentDomain = 'www.test.com';
|
||||
[
|
||||
hiddenDomainsString,
|
||||
diff
|
||||
] = Utils.hideString(domainsString, domainsString.length * 3);
|
||||
|
||||
assert.throws(() => getFunctionFromTemplate({
|
||||
domainLockFunctionName: 'domainLockFunction',
|
||||
diff: diff,
|
||||
domains: hiddenDomainsString,
|
||||
singleNodeCallControllerFunctionName
|
||||
}, singleNodeCallControllerFunctionName, currentDomain));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete (<any>global).promisePolyfillActivationFlag;
|
||||
});
|
||||
});
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import 'format-unicorn';
|
||||
|
||||
import { AtobTemplate } from '../../../../../src/templates/custom-nodes/AtobTemplate';
|
||||
import { Rc4Template } from '../../../../../src/templates/custom-nodes/Rc4Template';
|
||||
import { UnicodeArrayBase64DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayBase64DecodeNodeTemplate';
|
||||
import { UnicodeArrayCallsWrapperTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayCallsWrapperTemplate';
|
||||
import { UnicodeArrayRc4DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayRC4DecodeNodeTemplate';
|
||||
|
||||
import { Utils } from '../../../../../src/Utils';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
/**
|
||||
* @param templateData
|
||||
* @param unicodeArrayName
|
||||
* @param unicodeArrayCallsWrapperName
|
||||
* @param index
|
||||
* @returns {Function}
|
||||
*/
|
||||
function getFunctionFromTemplateBase64Encoding (
|
||||
templateData: any,
|
||||
unicodeArrayName: string,
|
||||
unicodeArrayCallsWrapperName: string,
|
||||
index: string
|
||||
) {
|
||||
let unicodeArrayCallsWrapperTemplate: string = UnicodeArrayCallsWrapperTemplate().formatUnicorn(templateData);
|
||||
|
||||
return Function(`
|
||||
var ${unicodeArrayName} = ['${Utils.btoa('test1')}'];
|
||||
|
||||
${unicodeArrayCallsWrapperTemplate}
|
||||
|
||||
return ${unicodeArrayCallsWrapperName}(${index});
|
||||
`)();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param templateData
|
||||
* @param unicodeArrayName
|
||||
* @param unicodeArrayCallsWrapperName
|
||||
* @param index
|
||||
* @param key
|
||||
* @returns {Function}
|
||||
*/
|
||||
function getFunctionFromTemplateRc4Encoding (
|
||||
templateData: any,
|
||||
unicodeArrayName: string,
|
||||
unicodeArrayCallsWrapperName: string,
|
||||
index: string,
|
||||
key: string
|
||||
) {
|
||||
let unicodeArrayCallsWrapperTemplate: string = UnicodeArrayCallsWrapperTemplate().formatUnicorn(templateData);
|
||||
|
||||
return Function(`
|
||||
var ${unicodeArrayName} = ['${Utils.btoa(Utils.rc4('test1', key))}'];
|
||||
|
||||
${unicodeArrayCallsWrapperTemplate}
|
||||
|
||||
return ${unicodeArrayCallsWrapperName}('${index}', '${key}');
|
||||
`)();
|
||||
}
|
||||
|
||||
describe('UnicodeArrayCallsWrapperNodeTemplate (): string', () => {
|
||||
let unicodeArrayName: string = 'unicodeArrayName',
|
||||
unicodeArrayCallsWrapperName: string = 'unicodeArrayCallsWrapperName',
|
||||
atobDecodeNodeTemplate: string = UnicodeArrayBase64DecodeNodeTemplate().formatUnicorn({
|
||||
atobPolyfill: AtobTemplate(),
|
||||
selfDefendingCode: '',
|
||||
unicodeArrayCallsWrapperName
|
||||
}),
|
||||
rc4DecodeNodeTemplate: string = UnicodeArrayRc4DecodeNodeTemplate().formatUnicorn({
|
||||
atobPolyfill: AtobTemplate(),
|
||||
rc4Polyfill: Rc4Template(),
|
||||
selfDefendingCode: '',
|
||||
unicodeArrayCallsWrapperName
|
||||
});
|
||||
|
||||
it('should correctly returns decoded value with base64 encoding', () => {
|
||||
assert.deepEqual(getFunctionFromTemplateBase64Encoding({
|
||||
decodeNodeTemplate: atobDecodeNodeTemplate,
|
||||
unicodeArrayCallsWrapperName,
|
||||
unicodeArrayName
|
||||
}, unicodeArrayName, unicodeArrayCallsWrapperName, '0x0'), 'test1');
|
||||
});
|
||||
|
||||
it('should correctly returns decoded value with rc4 encoding', () => {
|
||||
assert.deepEqual(getFunctionFromTemplateRc4Encoding({
|
||||
decodeNodeTemplate: rc4DecodeNodeTemplate,
|
||||
unicodeArrayCallsWrapperName,
|
||||
unicodeArrayName
|
||||
}, unicodeArrayName, unicodeArrayCallsWrapperName, '0x0', 'key'), 'test1');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* @returns {string}
|
||||
*/
|
||||
export function readFileAsString (path: string): string {
|
||||
return fs.readFileSync(path, 'utf8');
|
||||
}
|
||||
@@ -7,6 +7,7 @@ BabelPolyfill.append();
|
||||
/**
|
||||
* Unit tests
|
||||
*/
|
||||
import './unit-tests/NodeAppender.spec';
|
||||
import './unit-tests/NodeUtils.spec';
|
||||
import './unit-tests/ObfuscationResult.spec';
|
||||
import './unit-tests/OptionsNormalizer.spec';
|
||||
@@ -16,6 +17,7 @@ import './unit-tests/cli/CLIUtils.spec';
|
||||
import './unit-tests/node-obfuscators/CatchClauseObfuscator.spec';
|
||||
import './unit-tests/node-obfuscators/FunctionDeclarationObfuscator.spec';
|
||||
import './unit-tests/node-obfuscators/FunctionObfuscator.spec';
|
||||
import './unit-tests/stack-trace-analyzer/StackTraceAnalyzer.spec';
|
||||
|
||||
/**
|
||||
* Functional tests
|
||||
@@ -23,9 +25,22 @@ import './unit-tests/node-obfuscators/FunctionObfuscator.spec';
|
||||
import './functional-tests/JavaScriptObfuscator.spec';
|
||||
import './functional-tests/JavaScriptObfuscatorCLI.spec';
|
||||
import './functional-tests/JavaScriptObfuscatorInternal.spec';
|
||||
import './functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec';
|
||||
import './functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec';
|
||||
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayCallsWrapper.spec';
|
||||
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayRotateFunctionNode.spec';
|
||||
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayNode.spec';
|
||||
import './functional-tests/node-obfuscators/FunctionObfuscator.spec';
|
||||
import './functional-tests/node-obfuscators/LiteralObfuscator.spec';
|
||||
import './functional-tests/node-obfuscators/MemberExpressionObfuscator.spec';
|
||||
import './functional-tests/node-obfuscators/MethodDefinitionObfuscator.spec';
|
||||
import './functional-tests/node-obfuscators/ObjectExpressionObfuscator.spec';
|
||||
import './functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec';
|
||||
import './functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec';
|
||||
import './functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec';
|
||||
import './functional-tests/templates/custom-nodes/unicode-array-nodes/UnicodeArrayCallsWrapperNodeTemplate.spec';
|
||||
|
||||
/**
|
||||
* Performance tests
|
||||
*/
|
||||
import './performance-tests/JavaScriptObfuscatorPerformance.spec';
|
||||
|
||||
+36
-52
@@ -1,30 +1,16 @@
|
||||
import * as escodegen from 'escodegen';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TExpression } from "../../src/types/nodes/TExpression";
|
||||
import { TStatement } from "../../src/types/nodes/TStatement";
|
||||
import { TStatement } from '../../src/types/TStatement';
|
||||
|
||||
import { IBlockStatementNode } from "../../src/interfaces/nodes/IBlockStatementNode";
|
||||
import { ICallExpressionNode } from "../../src/interfaces/nodes/ICallExpressionNode";
|
||||
import { ICatchClauseNode } from "../../src/interfaces/nodes/ICatchClauseNode";
|
||||
import { IExpressionStatementNode } from "../../src/interfaces/nodes/IExpressionStatementNode";
|
||||
import { IFunctionDeclarationNode } from "../../src/interfaces/nodes/IFunctionDeclarationNode";
|
||||
import { IIdentifierNode } from "../../src/interfaces/nodes/IIdentifierNode";
|
||||
import { IIfStatementNode } from "../../src/interfaces/nodes/IIfStatementNode";
|
||||
import { ILiteralNode } from "../../src/interfaces/nodes/ILiteralNode";
|
||||
import { IMemberExpressionNode } from "../../src/interfaces/nodes/IMemberExpressionNode";
|
||||
import { IProgramNode } from "../../src/interfaces/nodes/IProgramNode";
|
||||
import { ISpreadElementNode } from "../../src/interfaces/nodes/ISpreadElementNode";
|
||||
import { IVariableDeclarationNode } from "../../src/interfaces/nodes/IVariableDeclarationNode";
|
||||
import { IVariableDeclaratorNode } from "../../src/interfaces/nodes/IVariableDeclaratorNode";
|
||||
|
||||
import { NodeType } from "../../src/enums/NodeType";
|
||||
import { NodeType } from '../../src/enums/NodeType';
|
||||
|
||||
export class NodeMocks {
|
||||
/**
|
||||
* @param bodyNodes
|
||||
* @returns {IProgramNode}
|
||||
* @returns {ESTree.Program}
|
||||
*/
|
||||
public static getProgramNode (bodyNodes: TStatement[] = []): IProgramNode {
|
||||
public static getProgramNode (bodyNodes: TStatement[] = []): ESTree.Program {
|
||||
return {
|
||||
type: NodeType.Program,
|
||||
body: bodyNodes,
|
||||
@@ -35,9 +21,9 @@ export class NodeMocks {
|
||||
|
||||
/**
|
||||
* @param bodyNodes
|
||||
* @returns {IBlockStatementNode}
|
||||
* @returns {ESTree.BlockStatement}
|
||||
*/
|
||||
public static getBlockStatementNode (bodyNodes: TStatement[] = []): IBlockStatementNode {
|
||||
public static getBlockStatementNode (bodyNodes: ESTree.Statement[] = []): ESTree.BlockStatement {
|
||||
return {
|
||||
type: NodeType.BlockStatement,
|
||||
body: bodyNodes,
|
||||
@@ -47,9 +33,9 @@ export class NodeMocks {
|
||||
|
||||
/**
|
||||
* @param bodyNodes
|
||||
* @returns {ICatchClauseNode}
|
||||
* @returns {ESTree.CatchClause}
|
||||
*/
|
||||
public static getCatchClauseNode (bodyNodes: TStatement[] = []): ICatchClauseNode {
|
||||
public static getCatchClauseNode (bodyNodes: ESTree.Statement[] = []): ESTree.CatchClause {
|
||||
return {
|
||||
type: NodeType.CatchClause,
|
||||
param: NodeMocks.getIdentifierNode('err'),
|
||||
@@ -61,12 +47,12 @@ export class NodeMocks {
|
||||
/**
|
||||
* @param callee
|
||||
* @param args
|
||||
* @returns {ICallExpressionNode}
|
||||
* @returns {ESTree.CallExpression}
|
||||
*/
|
||||
public static getCallExpressionNode (
|
||||
callee: TExpression,
|
||||
args: TExpression[] | ISpreadElementNode[] = []
|
||||
): ICallExpressionNode {
|
||||
callee: ESTree.Expression,
|
||||
args: ESTree.Expression[] | ESTree.SpreadElement[] = []
|
||||
): ESTree.CallExpression {
|
||||
return {
|
||||
type: NodeType.CallExpression,
|
||||
callee: callee,
|
||||
@@ -77,11 +63,11 @@ export class NodeMocks {
|
||||
|
||||
/**
|
||||
* @param expression
|
||||
* @returns {IExpressionStatementNode}
|
||||
* @returns {ESTree.ExpressionStatement}
|
||||
*/
|
||||
public static getExpressionStatementNode (
|
||||
expression: TExpression = NodeMocks.getIdentifierNode()
|
||||
): IExpressionStatementNode {
|
||||
expression: ESTree.Expression = NodeMocks.getIdentifierNode()
|
||||
): ESTree.ExpressionStatement {
|
||||
return {
|
||||
type: NodeType.ExpressionStatement,
|
||||
expression: expression,
|
||||
@@ -93,29 +79,28 @@ export class NodeMocks {
|
||||
* @param functionName
|
||||
* @param blockStatementNode
|
||||
* @param params
|
||||
* @returns {IFunctionDeclarationNode}
|
||||
* @returns {ESTree.FunctionDeclaration}
|
||||
*/
|
||||
public static getFunctionDeclarationNode (
|
||||
functionName: string,
|
||||
blockStatementNode: IBlockStatementNode,
|
||||
params: IIdentifierNode[] = []
|
||||
): IFunctionDeclarationNode {
|
||||
blockStatementNode: ESTree.BlockStatement,
|
||||
params: ESTree.Identifier[] = []
|
||||
): ESTree.FunctionDeclaration {
|
||||
return {
|
||||
type: NodeType.FunctionDeclaration,
|
||||
id: NodeMocks.getIdentifierNode(functionName),
|
||||
params: params,
|
||||
body: blockStatementNode,
|
||||
generator: false,
|
||||
expression: false,
|
||||
obfuscated: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blockStatementNode
|
||||
* @returns {IIfStatementNode}
|
||||
* @returns {ESTree.IfStatement}
|
||||
*/
|
||||
public static getIfStatementNode (blockStatementNode: IBlockStatementNode): IIfStatementNode {
|
||||
public static getIfStatementNode (blockStatementNode: ESTree.BlockStatement): ESTree.IfStatement {
|
||||
return {
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
@@ -125,16 +110,15 @@ export class NodeMocks {
|
||||
obfuscated: false
|
||||
},
|
||||
consequent: blockStatementNode,
|
||||
alternate: null,
|
||||
obfuscated: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param identifierName
|
||||
* @returns {IIdentifierNode}
|
||||
* @returns {ESTree.Identifier}
|
||||
*/
|
||||
public static getIdentifierNode (identifierName: string = 'identifier'): IIdentifierNode {
|
||||
public static getIdentifierNode (identifierName: string = 'identifier'): ESTree.Identifier {
|
||||
return {
|
||||
type: NodeType.Identifier,
|
||||
name: identifierName,
|
||||
@@ -144,9 +128,9 @@ export class NodeMocks {
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* @returns {ILiteralNode}
|
||||
* @returns {ESTree.Literal}
|
||||
*/
|
||||
public static getLiteralNode (value: boolean|number|string = 'value'): ILiteralNode {
|
||||
public static getLiteralNode (value: boolean|number|string = 'value'): ESTree.Literal {
|
||||
return {
|
||||
type: NodeType.Literal,
|
||||
value: value,
|
||||
@@ -162,12 +146,12 @@ export class NodeMocks {
|
||||
/**
|
||||
* @param object
|
||||
* @param property
|
||||
* @return {IMemberExpressionNode}
|
||||
* @return {ESTree.MemberExpression}
|
||||
*/
|
||||
public static getMemberExpressionNode (
|
||||
object: IIdentifierNode,
|
||||
property: IIdentifierNode|ILiteralNode
|
||||
): IMemberExpressionNode {
|
||||
object: ESTree.Identifier,
|
||||
property: ESTree.Identifier|ESTree.Literal
|
||||
): ESTree.MemberExpression {
|
||||
return {
|
||||
type: NodeType.MemberExpression,
|
||||
computed: false,
|
||||
@@ -180,12 +164,12 @@ export class NodeMocks {
|
||||
/**
|
||||
* @param declarations
|
||||
* @param kind
|
||||
* @returns {IVariableDeclarationNode}
|
||||
* @returns {ESTree.VariableDeclaration}
|
||||
*/
|
||||
public static getVariableDeclarationNode (
|
||||
declarations: IVariableDeclaratorNode[] = [],
|
||||
kind: string = 'var'
|
||||
): IVariableDeclarationNode {
|
||||
declarations: ESTree.VariableDeclarator[] = [],
|
||||
kind: 'var' | 'let' | 'const' = 'var'
|
||||
): ESTree.VariableDeclaration {
|
||||
return {
|
||||
type: NodeType.VariableDeclaration,
|
||||
declarations: declarations,
|
||||
@@ -197,9 +181,9 @@ export class NodeMocks {
|
||||
/**
|
||||
* @param id
|
||||
* @param init
|
||||
* @returns {IVariableDeclaratorNode}
|
||||
* @returns {ESTree.VariableDeclarator}
|
||||
*/
|
||||
public static getVariableDeclaratorNode (id: IIdentifierNode, init: any): IVariableDeclaratorNode {
|
||||
public static getVariableDeclaratorNode (id: ESTree.Identifier, init: any): ESTree.VariableDeclarator {
|
||||
return {
|
||||
type: NodeType.VariableDeclarator,
|
||||
id: id,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { readFileAsString } from '../helpers/readFileAsString';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('JavaScriptObfuscator performance', () => {
|
||||
const iterationsCount: number = 500;
|
||||
|
||||
describe('performance: multiple calls', () => {
|
||||
it('shows performance time with multiple obfuscator calls', function (): void {
|
||||
this.timeout(100000);
|
||||
|
||||
for (let i: number = 0; i < iterationsCount; i++) {
|
||||
JavaScriptObfuscator.obfuscate(readFileAsString('./test/fixtures/sample.js'));
|
||||
}
|
||||
|
||||
assert.isOk(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('performance: large source code', () => {
|
||||
it('shows performance time with large code size', function (): void {
|
||||
this.timeout(100000);
|
||||
|
||||
JavaScriptObfuscator.obfuscate(readFileAsString('./test/fixtures/sample.js').repeat(iterationsCount));
|
||||
|
||||
assert.isOk(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,244 @@
|
||||
import * as chai from 'chai';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TStatement } from '../../src/types/TStatement';
|
||||
|
||||
import { IStackTraceData } from '../../src/interfaces/stack-trace-analyzer/IStackTraceData';
|
||||
|
||||
import { readFileAsString } from '../helpers/readFileAsString';
|
||||
|
||||
import { NodeAppender } from '../../src/NodeAppender';
|
||||
import { NodeMocks } from '../mocks/NodeMocks';
|
||||
import { NodeUtils } from '../../src/NodeUtils';
|
||||
import { StackTraceAnalyzer } from '../../src/stack-trace-analyzer/StackTraceAnalyzer';
|
||||
|
||||
const assert: any = chai.assert;
|
||||
|
||||
describe('NodeAppender', () => {
|
||||
describe('appendNode (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[]): void', () => {
|
||||
let astTree: ESTree.Program,
|
||||
expectedAstTree: ESTree.Program,
|
||||
node: TStatement[];
|
||||
|
||||
beforeEach(() => {
|
||||
node = NodeUtils.convertCodeToStructure(`
|
||||
var test = 1;
|
||||
`);
|
||||
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
NodeUtils.parentize(astTree);
|
||||
NodeUtils.parentize(expectedAstTree);
|
||||
|
||||
NodeAppender.appendNode(astTree, node);
|
||||
});
|
||||
|
||||
it('should append given node to a `BlockStatement` node body', () => {
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
});
|
||||
|
||||
describe('appendNodeToOptimalBlockScope (blockScopeStackTraceData: IStackTraceData[], blockScopeNode: TNodeWithBlockStatement, nodeBodyStatements: TStatement[], index: number = 0): void', () => {
|
||||
let astTree: ESTree.Program,
|
||||
expectedAstTree: ESTree.Program,
|
||||
node: TStatement[],
|
||||
stackTraceData: IStackTraceData[];
|
||||
|
||||
beforeEach(() => {
|
||||
node = NodeUtils.convertCodeToStructure(`
|
||||
var test = 1;
|
||||
`);
|
||||
});
|
||||
|
||||
it('should append node into first and deepest function call in calls trace - variant #1', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-1.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-1-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node);
|
||||
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
|
||||
it('should append node into first and deepest function call in calls trace - variant #2', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-2.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-2-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node);
|
||||
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
|
||||
describe('append by specific index', () => {
|
||||
let astTree: ESTree.Program;
|
||||
|
||||
beforeEach(() => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index.js')
|
||||
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should append node into deepest function call by specified index in calls trace - variant #1', () => {
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-1-expected.js')
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 2);
|
||||
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
|
||||
it('should append node into deepest function call by specified index in calls trace - variant #2', () => {
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-2-expected.js')
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 1);
|
||||
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
|
||||
it('should append node into deepest function call by specified index in calls trace - variant #3', () => {
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-3.js')
|
||||
)
|
||||
);
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-3-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
|
||||
NodeAppender.appendNodeToOptimalBlockScope(
|
||||
stackTraceData,
|
||||
astTree,
|
||||
node,
|
||||
NodeAppender.getRandomStackTraceIndex(stackTraceData.length)
|
||||
);
|
||||
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRandomStackTraceIndex (stackTraceRootLength: number): number', () => {
|
||||
it('should returns random index between 0 and stack trace data root length', () => {
|
||||
let index: number;
|
||||
|
||||
for (let i: number = 0; i < 100; i++) {
|
||||
index = NodeAppender.getRandomStackTraceIndex(100);
|
||||
|
||||
assert.isAtLeast(index, 0);
|
||||
assert.isAtMost(index, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('insertNodeAtIndex (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[], index: number): void', () => {
|
||||
let astTree: ESTree.Program,
|
||||
expectedAstTree: ESTree.Program,
|
||||
node: TStatement[];
|
||||
|
||||
beforeEach(() => {
|
||||
node = NodeUtils.convertCodeToStructure(`
|
||||
var test = 1;
|
||||
`);
|
||||
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/insert-node-at-index.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/insert-node-at-index-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
NodeUtils.parentize(astTree);
|
||||
NodeUtils.parentize(expectedAstTree);
|
||||
|
||||
NodeAppender.insertNodeAtIndex(astTree, node, 2);
|
||||
});
|
||||
|
||||
it('should insert given node in `BlockStatement` node body at index', () => {
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prependNode (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[]): void', () => {
|
||||
let astTree: ESTree.Program,
|
||||
expectedAstTree: ESTree.Program,
|
||||
node: TStatement[];
|
||||
|
||||
beforeEach(() => {
|
||||
node = NodeUtils.convertCodeToStructure(`
|
||||
var test = 1;
|
||||
`);
|
||||
|
||||
astTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/prepend-node.js')
|
||||
)
|
||||
);
|
||||
|
||||
expectedAstTree = NodeMocks.getProgramNode(
|
||||
NodeUtils.convertCodeToStructure(
|
||||
readFileAsString('./test/fixtures/node-appender/prepend-node-expected.js')
|
||||
)
|
||||
);
|
||||
|
||||
NodeUtils.parentize(astTree);
|
||||
NodeUtils.parentize(expectedAstTree);
|
||||
|
||||
NodeAppender.prependNode(astTree, node);
|
||||
});
|
||||
|
||||
it('should prepend given node to a `BlockStatement` node body', () => {
|
||||
assert.deepEqual(astTree, expectedAstTree);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,15 +1,5 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { IBlockStatementNode } from "../../src/interfaces/nodes/IBlockStatementNode";
|
||||
import { IExpressionStatementNode } from "../../src/interfaces/nodes/IExpressionStatementNode";
|
||||
import { IFunctionDeclarationNode } from "../../src/interfaces/nodes/IFunctionDeclarationNode";
|
||||
import { IIdentifierNode } from "../../src/interfaces/nodes/IIdentifierNode";
|
||||
import { IIfStatementNode } from "../../src/interfaces/nodes/IIfStatementNode";
|
||||
import { ILiteralNode } from "../../src/interfaces/nodes/ILiteralNode";
|
||||
import { INode } from "../../src/interfaces/nodes/INode";
|
||||
import { IProgramNode } from "../../src/interfaces/nodes/IProgramNode";
|
||||
import { IVariableDeclarationNode } from "../../src/interfaces/nodes/IVariableDeclarationNode";
|
||||
import { IVariableDeclaratorNode } from "../../src/interfaces/nodes/IVariableDeclaratorNode";
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { NodeMocks } from '../mocks/NodeMocks';
|
||||
import { NodeUtils } from '../../src/NodeUtils';
|
||||
@@ -17,7 +7,7 @@ import { NodeUtils } from '../../src/NodeUtils';
|
||||
const assert: any = chai.assert;
|
||||
|
||||
describe('NodeUtils', () => {
|
||||
describe('addXVerbatimPropertyToLiterals (node: INode): void', () => {
|
||||
describe('addXVerbatimPropertyToLiterals (node: ESTree.Node): void', () => {
|
||||
let literalNode: any,
|
||||
expectedLiteralNode: any;
|
||||
|
||||
@@ -35,43 +25,13 @@ describe('NodeUtils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('appendNode (blockScopeBody: INode[], node: INode): void', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
expectedBlockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode: IExpressionStatementNode;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode = NodeMocks.getExpressionStatementNode();
|
||||
|
||||
blockStatementNode = NodeMocks.getBlockStatementNode();
|
||||
|
||||
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
expressionStatementNode
|
||||
]);
|
||||
|
||||
NodeUtils.appendNode(blockStatementNode.body, expressionStatementNode);
|
||||
});
|
||||
|
||||
it('should append given node to a `BlockStatement` node body', () => {
|
||||
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
|
||||
});
|
||||
|
||||
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
|
||||
assert.doesNotChange(
|
||||
() => NodeUtils.appendNode(blockStatementNode.body, <INode>{}),
|
||||
blockStatementNode,
|
||||
'body'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('convertCodeToStructure (code: string): INode', () => {
|
||||
describe('convertCodeToStructure (code: string): ESTree.Node[]', () => {
|
||||
let code: string,
|
||||
identifierNode: IIdentifierNode,
|
||||
literalNode: ILiteralNode,
|
||||
programNode: IProgramNode,
|
||||
variableDeclarationNode: IVariableDeclarationNode,
|
||||
variableDeclaratorNode: IVariableDeclaratorNode;
|
||||
identifierNode: ESTree.Identifier,
|
||||
literalNode: ESTree.Literal,
|
||||
programNode: ESTree.Program,
|
||||
variableDeclarationNode: ESTree.VariableDeclaration,
|
||||
variableDeclaratorNode: ESTree.VariableDeclarator;
|
||||
|
||||
beforeEach(() => {
|
||||
code = `
|
||||
@@ -99,15 +59,15 @@ describe('NodeUtils', () => {
|
||||
literalNode['parentNode'] = variableDeclaratorNode;
|
||||
});
|
||||
|
||||
it('should convert code to `INode` structure', () => {
|
||||
assert.deepEqual(NodeUtils.convertCodeToStructure(code), variableDeclarationNode);
|
||||
it('should convert code to `ESTree.Node[]` structure array', () => {
|
||||
assert.deepEqual(NodeUtils.convertCodeToStructure(code), [variableDeclarationNode]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBlockStatementNodeByIndex (node: INode, index: number = 0): INode', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode;
|
||||
describe('getBlockStatementNodeByIndex (node: ESTree.Node, index: number = 0): ESTree.Node', () => {
|
||||
let blockStatementNode: ESTree.BlockStatement,
|
||||
expressionStatementNode1: ESTree.ExpressionStatement,
|
||||
expressionStatementNode2: ESTree.ExpressionStatement;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
|
||||
@@ -133,17 +93,17 @@ describe('NodeUtils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBlockScopeOfNode (node: INode, depth: number = 0): TNodeWithBlockStatement', () => {
|
||||
let functionDeclarationBlockStatementNode: IBlockStatementNode,
|
||||
ifStatementBlockStatementNode1: IBlockStatementNode,
|
||||
ifStatementBlockStatementNode2: IBlockStatementNode,
|
||||
ifStatementNode1: IIfStatementNode,
|
||||
ifStatementNode2: IIfStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode,
|
||||
expressionStatementNode3: IExpressionStatementNode,
|
||||
functionDeclarationNode: IFunctionDeclarationNode,
|
||||
programNode: IProgramNode;
|
||||
describe('getBlockScopeOfNode (node: ESTree.Node, depth: number = 0): TNodeWithBlockStatement', () => {
|
||||
let functionDeclarationBlockStatementNode: ESTree.BlockStatement,
|
||||
ifStatementBlockStatementNode1: ESTree.BlockStatement,
|
||||
ifStatementBlockStatementNode2: ESTree.BlockStatement,
|
||||
ifStatementNode1: ESTree.IfStatement,
|
||||
ifStatementNode2: ESTree.IfStatement,
|
||||
expressionStatementNode1: ESTree.ExpressionStatement,
|
||||
expressionStatementNode2: ESTree.ExpressionStatement,
|
||||
expressionStatementNode3: ESTree.ExpressionStatement,
|
||||
functionDeclarationNode: ESTree.FunctionDeclaration,
|
||||
programNode: ESTree.Program;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
|
||||
@@ -199,47 +159,12 @@ describe('NodeUtils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
expectedBlockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
|
||||
expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
|
||||
|
||||
blockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
expressionStatementNode1
|
||||
]);
|
||||
|
||||
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
expressionStatementNode1,
|
||||
expressionStatementNode1
|
||||
]);
|
||||
|
||||
NodeUtils.insertNodeAtIndex(blockStatementNode.body, expressionStatementNode2, 1);
|
||||
});
|
||||
|
||||
it('should insert given node in `BlockStatement` node body at index', () => {
|
||||
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
|
||||
});
|
||||
|
||||
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
|
||||
assert.doesNotChange(
|
||||
() => NodeUtils.insertNodeAtIndex(blockStatementNode.body, <INode>{}, 1),
|
||||
blockStatementNode,
|
||||
'body'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parentize (node: INode): void', () => {
|
||||
let ifStatementNode: IIfStatementNode,
|
||||
ifStatementBlockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode,
|
||||
programNode: IProgramNode;
|
||||
describe('parentize (node: ESTree.Node): void', () => {
|
||||
let ifStatementNode: ESTree.IfStatement,
|
||||
ifStatementBlockStatementNode: ESTree.BlockStatement,
|
||||
expressionStatementNode1: ESTree.ExpressionStatement,
|
||||
expressionStatementNode2: ESTree.ExpressionStatement,
|
||||
programNode: ESTree.Program;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
|
||||
@@ -281,39 +206,4 @@ describe('NodeUtils', () => {
|
||||
assert.deepEqual(expressionStatementNode2['parentNode'], ifStatementBlockStatementNode);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prependNode (blockScopeBody: INode[], node: INode): void', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
expectedBlockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
|
||||
expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
|
||||
|
||||
blockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
expressionStatementNode1
|
||||
]);
|
||||
|
||||
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
expressionStatementNode2,
|
||||
expressionStatementNode1
|
||||
]);
|
||||
|
||||
NodeUtils.prependNode(blockStatementNode.body, expressionStatementNode2);
|
||||
});
|
||||
|
||||
it('should prepend given node to a `BlockStatement` node body', () => {
|
||||
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
|
||||
});
|
||||
|
||||
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
|
||||
assert.doesNotChange(
|
||||
() => NodeUtils.prependNode(blockStatementNode.body, <INode>{}),
|
||||
blockStatementNode,
|
||||
'body'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
|
||||
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
|
||||
|
||||
import { ObfuscationResult } from "../../src/ObfuscationResult";
|
||||
import { ObfuscationResult } from '../../src/ObfuscationResult';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IObfuscatorOptions } from "../../src/interfaces/IObfuscatorOptions";
|
||||
import { IOptions } from "../../src/interfaces/IOptions";
|
||||
import { IObfuscatorOptions } from '../../src/interfaces/IObfuscatorOptions';
|
||||
import { IOptions } from '../../src/interfaces/IOptions';
|
||||
|
||||
import { DEFAULT_PRESET } from '../../src/preset-options/DefaultPreset';
|
||||
|
||||
import { Options } from "../../src/options/Options";
|
||||
import { Options } from '../../src/options/Options';
|
||||
import { OptionsNormalizer } from '../../src/options/OptionsNormalizer';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
@@ -24,39 +24,45 @@ describe('OptionsNormalizer', () => {
|
||||
optionsPreset1 = Object.assign({}, DEFAULT_PRESET, {
|
||||
compact: false,
|
||||
rotateUnicodeArray: true,
|
||||
sourceMapBaseUrl: 'http://localhost:9000',
|
||||
unicodeArray: false,
|
||||
unicodeArrayThreshold: 0.5,
|
||||
wrapUnicodeArrayCalls: true
|
||||
unicodeArrayEncoding: 'rc4',
|
||||
unicodeArrayThreshold: 0.5
|
||||
});
|
||||
optionsPreset2 = Object.assign({}, DEFAULT_PRESET, {
|
||||
rotateUnicodeArray: true,
|
||||
sourceMapBaseUrl: 'http://localhost:9000',
|
||||
sourceMapFileName: '//outputSourceMapName',
|
||||
unicodeArray: true,
|
||||
unicodeArrayThreshold: 0,
|
||||
wrapUnicodeArrayCalls: true
|
||||
unicodeArrayThreshold: 0
|
||||
});
|
||||
optionsPreset3 = Object.assign({}, DEFAULT_PRESET, {
|
||||
domainLock: ['//localhost:9000', 'https://google.ru/abc?cde=fgh'],
|
||||
sourceMapFileName: '/outputSourceMapName.map',
|
||||
unicodeArray: true,
|
||||
encodeUnicodeLiterals: true,
|
||||
wrapUnicodeArrayCalls: false
|
||||
unicodeArrayEncoding: true
|
||||
});
|
||||
|
||||
expectedOptionsPreset1 = Object.assign({}, DEFAULT_PRESET, {
|
||||
compact: true,
|
||||
rotateUnicodeArray: false,
|
||||
sourceMapBaseUrl: '',
|
||||
unicodeArray: false,
|
||||
unicodeArrayThreshold: 0,
|
||||
wrapUnicodeArrayCalls: false
|
||||
unicodeArrayEncoding: false,
|
||||
unicodeArrayThreshold: 0
|
||||
});
|
||||
expectedOptionsPreset2 = Object.assign({}, DEFAULT_PRESET, {
|
||||
rotateUnicodeArray: false,
|
||||
sourceMapBaseUrl: 'http://localhost:9000/',
|
||||
sourceMapFileName: 'outputSourceMapName.js.map',
|
||||
unicodeArray: false,
|
||||
unicodeArrayThreshold: 0,
|
||||
wrapUnicodeArrayCalls: false
|
||||
unicodeArrayThreshold: 0
|
||||
});
|
||||
expectedOptionsPreset3 = Object.assign({}, DEFAULT_PRESET, {
|
||||
domainLock: ['localhost', 'google.ru'],
|
||||
sourceMapFileName: 'outputSourceMapName.js.map',
|
||||
unicodeArray: true,
|
||||
encodeUnicodeLiterals: true,
|
||||
wrapUnicodeArrayCalls: true
|
||||
unicodeArrayEncoding: 'base64'
|
||||
});
|
||||
|
||||
options1 = new Options(optionsPreset1);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
|
||||
import { ISourceMapCorrector } from "../../src/interfaces/ISourceMapCorrector";
|
||||
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
|
||||
import { ISourceMapCorrector } from '../../src/interfaces/ISourceMapCorrector';
|
||||
|
||||
import { TSourceMapMode } from "../../src/types/TSourceMapMode";
|
||||
import { TSourceMapMode } from '../../src/types/TSourceMapMode';
|
||||
|
||||
import { SourceMapMode } from "../../src/enums/SourceMapMode";
|
||||
import { SourceMapMode } from '../../src/enums/SourceMapMode';
|
||||
|
||||
import { ObfuscationResult } from "../../src/ObfuscationResult";
|
||||
import { SourceMapCorrector } from "../../src/SourceMapCorrector";
|
||||
import { ObfuscationResult } from '../../src/ObfuscationResult';
|
||||
import { SourceMapCorrector } from '../../src/SourceMapCorrector';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
@@ -57,10 +57,6 @@ describe('SourceMapCorrector', () => {
|
||||
it('should add source map to obfuscated code as base64 encoded string', () => {
|
||||
assert.match(expectedObfuscationResult.getObfuscatedCode(), /data:application\/json;base64/);
|
||||
});
|
||||
|
||||
it('should clear original source map', () => {
|
||||
assert.equal(expectedObfuscationResult.getSourceMap(), '');
|
||||
});
|
||||
});
|
||||
|
||||
it('should add source map import to obfuscated code if source map mode is `separate`', () => {
|
||||
|
||||
@@ -50,6 +50,16 @@ describe('Utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractDomainFromUrl (url: string): string', () => {
|
||||
it('should extract domain from the given URL', () => {
|
||||
assert.equal(Utils.extractDomainFromUrl('http://google.ru'), 'google.ru');
|
||||
assert.equal(Utils.extractDomainFromUrl('http://www.google.ru'), 'www.google.ru');
|
||||
assert.equal(Utils.extractDomainFromUrl('https://www.google.ru:9000'), 'www.google.ru');
|
||||
assert.equal(Utils.extractDomainFromUrl('//google.ru/abc'), 'google.ru');
|
||||
assert.equal(Utils.extractDomainFromUrl('//localhost:9000'), 'localhost');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRandomVariableName (length: number = 6): string', () => {
|
||||
it('should return a string of given length with random variable name', () => {
|
||||
assert.match(Utils.getRandomVariableName(4), /^_0x(\w){4}$/);
|
||||
@@ -80,4 +90,15 @@ describe('Utils', () => {
|
||||
assert.equal(Utils.stringToUnicode('string'), expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hideString (str: string, length: number): [string, string]', () => {
|
||||
let original1: string = 'example.com',
|
||||
[str1, diff] = Utils.hideString(original1, 30);
|
||||
|
||||
it('should return a string with the original string within', () => {
|
||||
assert.isTrue(str1.length > original1.length);
|
||||
assert.equal(str1.replace(new RegExp('[' + diff + ']', 'g'), ''), original1);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import { ICatchClauseNode } from "../../../src/interfaces/nodes/ICatchClauseNode";
|
||||
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
|
||||
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
|
||||
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
|
||||
|
||||
import { NodeType } from "../../../src/enums/NodeType";
|
||||
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
|
||||
|
||||
import { NodeType } from '../../../src/enums/NodeType';
|
||||
|
||||
import { CatchClauseObfuscator } from '../../../src/node-obfuscators/CatchClauseObfuscator';
|
||||
import { NodeMocks } from "../../mocks/NodeMocks";
|
||||
import { Options } from "../../../src/options/Options";
|
||||
import { NodeMocks } from '../../mocks/NodeMocks';
|
||||
import { Options } from '../../../src/options/Options';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('CatchClauseObfuscator', () => {
|
||||
describe('obfuscateNode (catchClauseNode: ICatchClauseNode): void', () => {
|
||||
let catchClauseObfuscator: CatchClauseObfuscator,
|
||||
catchClauseNode: ICatchClauseNode;
|
||||
catchClauseNode: ESTree.CatchClause;
|
||||
|
||||
beforeEach(() => {
|
||||
let expressionStatementNode: IExpressionStatementNode = {
|
||||
let expressionStatementNode: ESTree.ExpressionStatement = {
|
||||
type: NodeType.ExpressionStatement,
|
||||
expression: {
|
||||
type: NodeType.CallExpression,
|
||||
@@ -64,7 +64,7 @@ describe('CatchClauseObfuscator', () => {
|
||||
|
||||
it('should obfuscate catch clause param calls in catch clause node body', () => {
|
||||
assert.match(
|
||||
catchClauseNode.param.name,
|
||||
(<ESTree.Identifier>catchClauseNode.param).name,
|
||||
/^_0x\w+$/
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import { IBlockStatementNode } from "../../../src/interfaces/nodes/IBlockStatementNode";
|
||||
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
|
||||
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
|
||||
import { IFunctionDeclarationNode } from "../../../src/interfaces/nodes/IFunctionDeclarationNode";
|
||||
import { IProgramNode } from "../../../src/interfaces/nodes/IProgramNode";
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
|
||||
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
|
||||
|
||||
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
|
||||
|
||||
import { FunctionDeclarationObfuscator } from '../../../src/node-obfuscators/FunctionDeclarationObfuscator';
|
||||
import { NodeMocks } from "../../mocks/NodeMocks";
|
||||
import { Options } from "../../../src/options/Options";
|
||||
import { NodeMocks } from '../../mocks/NodeMocks';
|
||||
import { Options } from '../../../src/options/Options';
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('FunctionDeclarationObfuscator', () => {
|
||||
describe('obfuscateNode (functionDeclarationNode: IFunctionDeclarationNode, parentNode: INode): void', () => {
|
||||
let expressionStatementNode: IExpressionStatementNode,
|
||||
let expressionStatementNode: ESTree.ExpressionStatement,
|
||||
functionDeclarationObfuscator: FunctionDeclarationObfuscator,
|
||||
functionDeclarationNode: IFunctionDeclarationNode,
|
||||
functionDeclarationNode: ESTree.FunctionDeclaration,
|
||||
functionName: string = 'functionDeclaration',
|
||||
programNode: IProgramNode;
|
||||
programNode: ESTree.Program;
|
||||
|
||||
beforeEach(() => {
|
||||
expressionStatementNode = NodeMocks.getExpressionStatementNode(
|
||||
@@ -37,8 +35,8 @@ describe('FunctionDeclarationObfuscator', () => {
|
||||
});
|
||||
|
||||
describe('if `functionDeclaration` node parent node is not a Program node', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
functionDeclarationParentNode: IFunctionDeclarationNode;
|
||||
let blockStatementNode: ESTree.BlockStatement,
|
||||
functionDeclarationParentNode: ESTree.FunctionDeclaration;
|
||||
|
||||
beforeEach(() => {
|
||||
blockStatementNode = NodeMocks.getBlockStatementNode([
|
||||
|
||||
@@ -1,33 +1,30 @@
|
||||
import { IBlockStatementNode } from "../../../src/interfaces/nodes/IBlockStatementNode";
|
||||
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
|
||||
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
|
||||
import { IFunctionDeclarationNode } from "../../../src/interfaces/nodes/IFunctionDeclarationNode";
|
||||
import { IIdentifierNode } from "../../../src/interfaces/nodes/IIdentifierNode";
|
||||
import { IProgramNode } from "../../../src/interfaces/nodes/IProgramNode";
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
|
||||
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
|
||||
|
||||
import { FunctionObfuscator } from "../../../src/node-obfuscators/FunctionObfuscator";
|
||||
import { NodeMocks } from "../../mocks/NodeMocks";
|
||||
import { Options } from "../../../src/options/Options";
|
||||
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
|
||||
|
||||
import { FunctionObfuscator } from '../../../src/node-obfuscators/FunctionObfuscator';
|
||||
import { NodeMocks } from '../../mocks/NodeMocks';
|
||||
import { Options } from '../../../src/options/Options';
|
||||
|
||||
|
||||
const assert: Chai.AssertStatic = require('chai').assert;
|
||||
|
||||
describe('FunctionObfuscator', () => {
|
||||
describe('obfuscateNode (functionNode: IFunctionNode): void', () => {
|
||||
let blockStatementNode: IBlockStatementNode,
|
||||
expressionStatementNode1: IExpressionStatementNode,
|
||||
expressionStatementNode2: IExpressionStatementNode,
|
||||
let blockStatementNode: ESTree.BlockStatement,
|
||||
expressionStatementNode1: ESTree.ExpressionStatement,
|
||||
expressionStatementNode2: ESTree.ExpressionStatement,
|
||||
functionObfuscator: FunctionObfuscator,
|
||||
functionDeclarationNode: IFunctionDeclarationNode,
|
||||
functionDeclarationNode: ESTree.FunctionDeclaration,
|
||||
functionName: string = 'functionDeclaration',
|
||||
identifierName: string = 'identifierName',
|
||||
identifierNode1: IIdentifierNode,
|
||||
identifierNode2: IIdentifierNode,
|
||||
identifierNode3: IIdentifierNode,
|
||||
identifierNode1: ESTree.Identifier,
|
||||
identifierNode2: ESTree.Identifier,
|
||||
identifierNode3: ESTree.Identifier,
|
||||
paramName: string = 'param1',
|
||||
programNode: IProgramNode;
|
||||
programNode: ESTree.Program;
|
||||
|
||||
before(() => {
|
||||
identifierNode1 = NodeMocks.getIdentifierNode(paramName);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { StackTraceAnalyzer } from '../../../src/stack-trace-analyzer/StackTraceAnalyzer';
|
||||
|
||||
const assert: any = chai.assert;
|
||||
|
||||
describe('StackTraceAnalyzer', () => {
|
||||
describe('getLimitIndex (blockScopeBodyLength: number): number', () => {
|
||||
it('should returns correct limit index based on block scope body length', () => {
|
||||
const blockScopeBodyLength1: number = 10000;
|
||||
const blockScopeBodyLength2: number = 1000;
|
||||
const blockScopeBodyLength3: number = 25;
|
||||
const blockScopeBodyLength4: number = 5;
|
||||
|
||||
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength1), 44);
|
||||
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength2), 26);
|
||||
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength3), 24);
|
||||
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength4), 4);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user