sanex3339
2017-07-27 01:43:37 +03:00
parent 0015db33c2
commit 0c357a0f2b
11 changed files with 221 additions and 27 deletions
+15 -14
View File
@@ -8,15 +8,16 @@ v0.10.0
* **Breaking change:** `disableConsoleOutput` option now disabled by default.
* **Breaking change:** `escapeUnicodeSequence` option now disabled by default.
* `controlFlowFlattening` now affects string literal nodes.
* increased runtime performance with `rc4` `stringArrayEncoding`.
* added support for async functions
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/65
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/60
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/59
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/54
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/57
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/58
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/58
* Increased runtime performance with `rc4` `stringArrayEncoding`.
* Added support for async functions
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/71
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/65
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/60
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/59
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/54
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/57
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/58
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/58
v0.9.3
---
@@ -70,15 +71,15 @@ v0.9.0-beta.1
v0.8.6
---
* additional fixes for https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
* Additional fixes for https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
v0.8.5
---
* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
v0.8.4
---
* fixed https://github.com/javascript-obfuscator/webpack-obfuscator/issues/13
* Fixed https://github.com/javascript-obfuscator/webpack-obfuscator/issues/13
v0.8.3
---
@@ -113,9 +114,9 @@ v0.7.3
v0.7.2
---
* runtime error fix [#7](https://github.com/sanex3339/webpack-obfuscator/issues/7)
* Runtime error fix [#7](https://github.com/sanex3339/webpack-obfuscator/issues/7)
* shorthand object expression fix [#16](https://github.com/sanex3339/javascript-obfuscator/issues/16)
* Shorthand object expression fix [#16](https://github.com/sanex3339/javascript-obfuscator/issues/16)
v0.7.1
---
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
import { injectable, inject } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
@@ -61,6 +62,35 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
});
}
/**
* @param {BlockStatement} blockStatementNode
* @returns {boolean}
*/
private static canTransformBlockStatementNode (blockStatementNode: ESTree.BlockStatement): boolean {
let canTransform: boolean = true;
estraverse.traverse(blockStatementNode, {
enter: (node: ESTree.Node): any => {
if (Node.isWhileStatementNode(node)) {
return estraverse.VisitorOption.Skip;
}
if (
Node.isBlockStatementNode(node)
&& BlockStatementControlFlowTransformer.blockStatementHasProhibitedStatements(node)
) {
canTransform = false;
}
}
});
if (blockStatementNode.body.length <= 4) {
canTransform = false;
}
return canTransform;
}
/**
* @return {IVisitor}
*/
@@ -82,17 +112,12 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
public transformNode (blockStatementNode: ESTree.BlockStatement, parentNode: ESTree.Node): ESTree.Node {
if (
this.randomGenerator.getMathRandom() > this.options.controlFlowFlatteningThreshold ||
BlockStatementControlFlowTransformer.blockStatementHasProhibitedStatements(blockStatementNode)
!BlockStatementControlFlowTransformer.canTransformBlockStatementNode(blockStatementNode)
) {
return blockStatementNode;
}
const blockStatementBody: ESTree.Statement[] = blockStatementNode.body;
if (blockStatementBody.length <= 4) {
return blockStatementNode;
}
const originalKeys: number[] = this.arrayUtils.arrayRange(blockStatementBody.length);
const shuffledKeys: number[] = this.arrayUtils.arrayShuffle(originalKeys);
const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
+8
View File
@@ -253,4 +253,12 @@ export class Node {
public static isVariableDeclaratorNode (node: ESTree.Node): node is ESTree.VariableDeclarator {
return node.type === NodeType.VariableDeclarator;
}
/**
* @param {Node} node
* @returns {boolean}
*/
public static isWhileStatementNode (node: ESTree.Node): node is ESTree.WhileStatement {
return node.type === NodeType.WhileStatement;
}
}
@@ -270,13 +270,13 @@ describe('BlockStatementControlFlowTransformer', function () {
});
});
describe('variant #6: block statement contain break statement', () => {
describe('variant #6: block statement contain break statement #1', () => {
const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *break; *console\['log'\]\(0x1\);/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/break-statement.js');
const code: string = readFileAsString(__dirname + '/fixtures/break-statement-1.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
@@ -294,13 +294,69 @@ describe('BlockStatementControlFlowTransformer', function () {
});
});
describe('variant #7: block statement contain continue statement', () => {
describe('variant #7: block statement contain break statement #2', () => {
const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *if *\(!!\[\]\) *\{ *break; *\} *console\['log'\]\(0x1\);/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/break-statement-2.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_CUSTOM_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
});
it('shouldn\'t transform block statement', () => {
assert.match(obfuscatedCode, statementRegExp);
});
});
describe('variant #8: block statement contain while statement with break statement', () => {
const switchCaseRegExp: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/;
const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
const expectedSwitchCaseLength: number = 5;
let obfuscatedCode: string,
switchCaseLength: number;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/break-statement-inside-while-statement.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_CUSTOM_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
switchCaseLength = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
});
it('should wrap block statement statements in switch-case structure', () => {
assert.match(obfuscatedCode, switchCaseRegExp);
});
it('each statement should be wrapped by switch-case structure', () => {
assert.equal(switchCaseLength, expectedSwitchCaseLength);
});
});
describe('variant #9: block statement contain continue statement #1', () => {
const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *continue; *console\['log'\]\(0x1\);/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/continue-statement.js');
const code: string = readFileAsString(__dirname + '/fixtures/continue-statement-1.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
@@ -318,7 +374,63 @@ describe('BlockStatementControlFlowTransformer', function () {
});
});
describe('variant #8: block statement contain function declaration', () => {
describe('variant #10: block statement contain continue statement #2', () => {
const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *if *\(!!\[\]\) *\{ *continue; *\} *console\['log'\]\(0x1\);/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/continue-statement-2.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_CUSTOM_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
});
it('shouldn\'t transform block statement', () => {
assert.match(obfuscatedCode, statementRegExp);
});
});
describe('variant #11: block statement contain while statement with continue statement', () => {
const switchCaseRegExp: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/;
const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
const expectedSwitchCaseLength: number = 5;
let obfuscatedCode: string,
switchCaseLength: number;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/continue-statement-inside-while-statement.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_CUSTOM_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
switchCaseLength = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
});
it('should wrap block statement statements in switch-case structure', () => {
assert.match(obfuscatedCode, switchCaseRegExp);
});
it('each statement should be wrapped by switch-case structure', () => {
assert.equal(switchCaseLength, expectedSwitchCaseLength);
});
});
describe('variant #12: block statement contain function declaration', () => {
const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-f0-9]){4,6} *\( *\) *\{ *\} *console\['log'\]\(0x1\);/
let obfuscatedCode: string;
@@ -342,7 +454,7 @@ describe('BlockStatementControlFlowTransformer', function () {
});
});
describe('variant #9: `controlFlowFlatteningThreshold` chance', () => {
describe('variant #13: `controlFlowFlatteningThreshold` chance', () => {
const samples: number = 1000;
const delta: number = 0.1;
@@ -0,0 +1,12 @@
(function () {
while (true) {
if (true) {
break;
}
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
})();
@@ -0,0 +1,12 @@
(function () {
while (true) {
while (true) {
break;
}
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
})();
@@ -0,0 +1,12 @@
(function () {
while (true) {
if (true) {
continue;
}
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
})();
@@ -0,0 +1,12 @@
(function () {
while (true) {
while (true) {
continue;
}
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
})();