Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Change Log

v2.3.1
---
* Fixed a rare bug with `identifierNamesGenerator: 'mangled'` option that causes wrong identifier names generation

v2.3.0
---
* **New option:** `stringArrayWrappersType` allows to select a type of the wrappers that are appending by the `stringArrayWrappersCount` option
Expand Down
4 changes: 2 additions & 2 deletions dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "2.3.0",
"version": "2.3.1",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down Expand Up @@ -54,7 +54,7 @@
"@types/mkdirp": "1.0.1",
"@types/mocha": "8.0.3",
"@types/multimatch": "4.0.0",
"@types/node": "14.10.3",
"@types/node": "14.11.1",
"@types/rimraf": "3.0.0",
"@types/sinon": "9.0.5",
"@types/string-template": "1.0.2",
Expand All @@ -69,7 +69,7 @@
"eslint-plugin-jsdoc": "30.5.1",
"eslint-plugin-no-null": "1.0.2",
"eslint-plugin-prefer-arrow": "1.2.2",
"eslint-plugin-unicorn": "21.0.0",
"eslint-plugin-unicorn": "22.0.0",
"fork-ts-checker-notifier-webpack-plugin": "3.0.0",
"fork-ts-checker-webpack-plugin": "5.2.0",
"mocha": "8.1.3",
Expand All @@ -79,10 +79,10 @@
"rimraf": "3.0.2",
"sinon": "9.0.3",
"threads": "1.6.3",
"ts-loader": "8.0.3",
"ts-loader": "8.0.4",
"ts-node": "9.0.0",
"typescript": "4.0.2",
"webpack": "4.44.1",
"typescript": "4.0.3",
"webpack": "4.44.2",
"webpack-cli": "3.3.12",
"webpack-node-externals": "2.5.2"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
* @param {string} prevName
* @returns {boolean}
*/
// eslint-disable-next-line complexity
public static isIncrementedMangledName (nextName: string, prevName: string): boolean {
if (nextName === prevName) {
return false;
Expand All @@ -76,6 +77,8 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
return nextNameLength > prevNameLength;
}

let isIncrementedPrevCharacter: boolean = false;

for (let i: number = 0; i < nextNameLength; i++) {
const nextNameCharacter: string = nextName[i];
const prevNameCharacter: string = prevName[i];
Expand All @@ -84,6 +87,17 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
continue;
}

const isDigitNextNameCharacter: boolean = MangledIdentifierNamesGenerator.isDigitCharacter(nextNameCharacter);
const isDigitPrevNameCharacter: boolean = MangledIdentifierNamesGenerator.isDigitCharacter(prevNameCharacter);

if (
isIncrementedPrevCharacter
&& isDigitNextNameCharacter
&& !isDigitPrevNameCharacter
) {
return true;
}

const isUpperCaseNextNameCharacter: boolean = MangledIdentifierNamesGenerator.isUpperCaseCharacter(nextNameCharacter);
const isUpperCasePrevNameCharacter: boolean = MangledIdentifierNamesGenerator.isUpperCaseCharacter(prevNameCharacter);

Expand All @@ -98,6 +112,12 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
) {
return false;
}

isIncrementedPrevCharacter = nextNameCharacter > prevNameCharacter;

if (nextNameCharacter < prevNameCharacter) {
return false;
}
}

return nextName > prevName;
Expand All @@ -111,6 +131,14 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
return /^[A-Z]*$/.test(string);
}

/**
* @param {string} character
* @returns {boolean}
*/
private static isDigitCharacter (string: string): boolean {
return /^[0-9]*$/.test(string);
}

/**
* Generates next name based on a global previous mangled name
* We can ignore nameLength parameter here, it hasn't sense with this generator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,52 @@ describe('JavaScriptObfuscator', () => {
});
});

describe('Eval `Hello World`', function () {
this.timeout(20000);

const samplesCount: number = 100;
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
let isEvaluationSuccessful: boolean = true;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/eval-hello-world.js');

for (let i = 0; i < samplesCount; i++) {
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
disableConsoleOutput: true,
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
renameProperties: true,
simplify: false,
stringArray: true,
stringArrayThreshold: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersCount: 1,
stringArrayWrappersType: StringArrayWrappersType.Variable
}
).getObfuscatedCode();

const evaluationResult: string = eval(obfuscatedCode);

if (evaluationResult !== expectedEvaluationResult) {
isEvaluationSuccessful = false;
break;
}
}
});

it('should correctly evaluate obfuscated code', () => {
assert.equal(isEvaluationSuccessful, true);
});
});

describe('Identifier names collision between base code and appended string array nodes', function () {
this.timeout(10000);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function func () {
var foo = 'aaa';
var bar = 'bbb';
var baz = 'ccc';
var bark = 'ddd';
var hawk = 'eee';

return foo + bar + baz + bark + hawk;
}

func();
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {

describe('Variant #2: option value is bigger then count `literal` nodes in the scope', () => {
const stringArrayCallRegExp: RegExp = new RegExp(
'return _0x([a-f0-9]){4,6};' +
'return _0x([a-f0-9]){4,6};' +
'};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
Expand Down Expand Up @@ -116,11 +116,11 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #1: option value is lower then count `literal` nodes in the scope', () => {
const stringArrayCallRegExp: RegExp = new RegExp(
'function test *\\( *\\) *{' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'}'
);

Expand Down Expand Up @@ -148,12 +148,12 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #2: option value is bigger then count `literal` nodes in the scope', () => {
const stringArrayCallRegExp: RegExp = new RegExp(
'function test *\\(\\) *{' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'}'
);

Expand Down Expand Up @@ -181,11 +181,11 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #3: correct wrappers order', () => {
const stringArrayCallRegExp: RegExp = new RegExp(
'function test *\\( *\\) *{' +
'const h *= *b;' +
'const i *= *b;' +
'const c *= *[h|i]\\(\'0x3\'\\);' +
'const d *= *[h|i]\\(\'0x4\'\\);' +
'const e *= *[h|i]\\(\'0x5\'\\);' +
'const h *= *b;' +
'const i *= *b;' +
'const c *= *[h|i]\\(\'0x3\'\\);' +
'const d *= *[h|i]\\(\'0x4\'\\);' +
'const e *= *[h|i]\\(\'0x5\'\\);' +
'}'
);

Expand Down Expand Up @@ -249,7 +249,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
const stringArrayCallRegExp: RegExp = new RegExp(
'var c *= *b;' +
'if *\\(!!\\[]\\) *{' +
'var foo *= *c\\(\'0x0\'\\);' +
'var foo *= *c\\(\'0x0\'\\);' +
'}'
);

Expand Down Expand Up @@ -306,7 +306,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {

describe('Variant #4: prevailing kind of variables', () => {
const stringArrayCallRegExp: RegExp = new RegExp(
'return _0x([a-f0-9]){4,6};' +
'return _0x([a-f0-9]){4,6};' +
'};' +
'var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
Expand Down Expand Up @@ -368,22 +368,22 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
'const q *= *b;' +
'const foo *= *q\\(\'0x0\'\\);' +
'function test\\(c, *d\\) *{' +
'const r *= *q;' +
'const e *= *r\\(\'0x1\'\\);' +
'const f *= *r\\(\'0x2\'\\);' +
'function g\\(h, *i\\) *{' +
'const s *= *r;' +
'const j *= *s\\(\'0x3\'\\);' +
'const k *= *s\\(\'0x4\'\\);' +
'function l\\(m, *n *\\) *{' +
'const t *= *s;' +
'const o *= *t\\(\'0x3\'\\);' +
'const p *= *t\\(\'0x4\'\\);' +
'return o *\\+ *p;' +
'}' +
'return j *\\+ *k;' +
'}' +
'return e *\\+ *f *\\+ *g\\(\\);' +
'const r *= *q;' +
'const e *= *r\\(\'0x1\'\\);' +
'const f *= *r\\(\'0x2\'\\);' +
'function g\\(h, *i\\) *{' +
'const s *= *r;' +
'const j *= *s\\(\'0x3\'\\);' +
'const k *= *s\\(\'0x4\'\\);' +
'function l\\(m, *n *\\) *{' +
'const t *= *s;' +
'const o *= *t\\(\'0x3\'\\);' +
'const p *= *t\\(\'0x4\'\\);' +
'return o *\\+ *p;' +
'}' +
'return j *\\+ *k;' +
'}' +
'return e *\\+ *f *\\+ *g\\(\\);' +
'}'
);

Expand Down Expand Up @@ -869,7 +869,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #1: root scope', () => {
describe('Variant #1: `1` scope calls wrapper for each encoding type', () => {
const stringArrayWrappersRegExp: RegExp = new RegExp(
'return _0x([a-f0-9]){4,6};' +
'return _0x([a-f0-9]){4,6};' +
'};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
// this one may be added or not depends on:
Expand Down Expand Up @@ -907,7 +907,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {

describe('Variant #2: `2` scope calls wrappers for each encoding type', () => {
const stringArrayWrappersRegExp: RegExp = new RegExp(
'return _0x([a-f0-9]){4,6};' +
'return _0x([a-f0-9]){4,6};' +
'};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
Expand Down Expand Up @@ -949,13 +949,13 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #1: `1` scope calls wrapper for each encoding type', () => {
const stringArrayWrappersRegExp: RegExp = new RegExp(
'function test *\\( *\\) *{' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
// this one may be added or not depends on:
// if all literal values encoded with a single encoding or not
'(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
// this one may be added or not depends on:
// if all literal values encoded with a single encoding or not
'(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'}'
);

Expand Down Expand Up @@ -987,14 +987,14 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
describe('Variant #2: `2` scope calls wrappers for each encoding type', () => {
const stringArrayWrappersRegExp: RegExp = new RegExp(
'function test *\\( *\\) *{' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
// this one may be added or not depends on:
// if all literal values encoded with a single encoding or not
'(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
// this one may be added or not depends on:
// if all literal values encoded with a single encoding or not
'(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x3\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x4\'\\);' +
'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\\(\'0x5\'\\);' +
'}'
);

Expand Down
Loading