Quellcode durchsuchen

additional tests for BlockStatementControlFlowTransformer

sanex3339 vor 8 Jahren
Ursprung
Commit
e8c76462ef

+ 2 - 1
dist/index.js

@@ -5090,6 +5090,7 @@ var ServiceIdentifiers_1 = __webpack_require__(4);
 var CustomNodes_1 = __webpack_require__(16);
 var CustomNodes_1 = __webpack_require__(16);
 var AbstractNodeTransformer_1 = __webpack_require__(18);
 var AbstractNodeTransformer_1 = __webpack_require__(18);
 var Node_1 = __webpack_require__(12);
 var Node_1 = __webpack_require__(12);
+var RandomGeneratorUtils_1 = __webpack_require__(9);
 var Utils_1 = __webpack_require__(13);
 var Utils_1 = __webpack_require__(13);
 var BlockStatementControlFlowTransformer = BlockStatementControlFlowTransformer_1 = function (_AbstractNodeTransfor) {
 var BlockStatementControlFlowTransformer = BlockStatementControlFlowTransformer_1 = function (_AbstractNodeTransfor) {
     (0, _inherits3.default)(BlockStatementControlFlowTransformer, _AbstractNodeTransfor);
     (0, _inherits3.default)(BlockStatementControlFlowTransformer, _AbstractNodeTransfor);
@@ -5106,7 +5107,7 @@ var BlockStatementControlFlowTransformer = BlockStatementControlFlowTransformer_
     (0, _createClass3.default)(BlockStatementControlFlowTransformer, [{
     (0, _createClass3.default)(BlockStatementControlFlowTransformer, [{
         key: "transformNode",
         key: "transformNode",
         value: function transformNode(blockStatementNode) {
         value: function transformNode(blockStatementNode) {
-            if (BlockStatementControlFlowTransformer_1.blockStatementHasProhibitedStatements(blockStatementNode)) {
+            if (RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold || BlockStatementControlFlowTransformer_1.blockStatementHasProhibitedStatements(blockStatementNode)) {
                 return blockStatementNode;
                 return blockStatementNode;
             }
             }
             var blockStatementBody = blockStatementNode.body;
             var blockStatementBody = blockStatementNode.body;

+ 5 - 1
src/node-transformers/node-control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -12,6 +12,7 @@ import { CustomNodes } from '../../enums/container/CustomNodes';
 
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
 import { Node } from '../../node/Node';
+import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 import { Utils } from '../../utils/Utils';
 import { Utils } from '../../utils/Utils';
 
 
 @injectable()
 @injectable()
@@ -53,7 +54,10 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
      * @returns {ESTree.Node}
      * @returns {ESTree.Node}
      */
      */
     public transformNode (blockStatementNode: ESTree.BlockStatement): ESTree.Node {
     public transformNode (blockStatementNode: ESTree.BlockStatement): ESTree.Node {
-        if (BlockStatementControlFlowTransformer.blockStatementHasProhibitedStatements(blockStatementNode)) {
+        if (
+            RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold ||
+            BlockStatementControlFlowTransformer.blockStatementHasProhibitedStatements(blockStatementNode)
+        ) {
             return blockStatementNode;
             return blockStatementNode;
         }
         }
 
 

+ 8 - 1
test/dev/dev.ts

@@ -11,7 +11,14 @@ if (!(<any>global)._babelPolyfill) {
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
         `
             (function () {
             (function () {
-                var abc = 1 + 1;
+                while (true) {
+                    break;
+                }
+                console.log(1);
+                console.log(2);
+                console.log(3);
+                console.log(4);
+                console.log(5);
             })();
             })();
         `,
         `,
         {
         {

+ 9 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-2.js

@@ -0,0 +1,9 @@
+(function () {
+    while (true) {
+        console.log(1);
+        console.log(2);
+        console.log(3);
+        console.log(4);
+        console.log(5);
+    }
+})();

+ 10 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-break-statement.js

@@ -0,0 +1,10 @@
+(function () {
+    while (true) {
+        break;
+        console.log(1);
+        console.log(2);
+        console.log(3);
+        console.log(4);
+        console.log(5);
+    }
+})();

+ 8 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-const-declaration.js

@@ -0,0 +1,8 @@
+(function () {
+    const variable = 1;
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

+ 10 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-continue-statement.js

@@ -0,0 +1,10 @@
+(function () {
+    while (true) {
+        continue;
+        console.log(1);
+        console.log(2);
+        console.log(3);
+        console.log(4);
+        console.log(5);
+    }
+})();

+ 8 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-function-declaration.js

@@ -0,0 +1,8 @@
+(function () {
+    function foo () {}
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

+ 8 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-let-declaration.js

@@ -0,0 +1,8 @@
+(function () {
+    let variable = 1;
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

+ 3 - 0
test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-one-statement.js

@@ -0,0 +1,3 @@
+(function () {
+    console.log(1);
+})();

+ 194 - 0
test/functional-tests/node-transformers/node-control-flow-transformers/BlockStatementControlFlowTransformer.spec.ts

@@ -56,5 +56,199 @@ describe('BlockStatementControlFlowTransformer', () => {
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
             });
             });
         });
         });
+
+        describe('variant #2: 5 simple statements inside while loop without break or continue statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-2.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1,
+                    unicodeEscapeSequence: false
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp1: RegExp = /console\['log'\]\(0x1\);/;
+            const statementRegExp2: RegExp = /console\['log'\]\(0x2\);/;
+            const statementRegExp3: RegExp = /console\['log'\]\(0x3\);/;
+            const statementRegExp4: RegExp = /console\['log'\]\(0x4\);/;
+            const statementRegExp5: RegExp = /console\['log'\]\(0x5\);/;
+
+            const switchCaseRegExp: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/;
+            const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
+            const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
+
+            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-z0-9]){4,6} *= *'(.*?)'/;
+            const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
+            const switchCaseMapMatch: string = switchCaseMapMatches[1];
+            const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
+
+            it('should save all statements', () => {
+                assert.match(obfuscatedCode, statementRegExp1);
+                assert.match(obfuscatedCode, statementRegExp2);
+                assert.match(obfuscatedCode, statementRegExp3);
+                assert.match(obfuscatedCode, statementRegExp4);
+                assert.match(obfuscatedCode, statementRegExp5);
+            });
+
+            it('should wrap block statement statements in switch case structure', () => {
+                assert.match(obfuscatedCode, switchCaseRegExp);
+                assert.equal(switchCaseLength, 5);
+            });
+
+            it('should create variable with order of switch cases sequence', () => {
+                assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
+            });
+        });
+
+        describe('variant #3: less then 5 statements', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-one-statement.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\); *\} *\( *\) *\);$/;
+
+            it('shouldn\'t transform block statement if statements length less than 5', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #4: const declaration inside block statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-const-declaration.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+
+            it('shouldn\'t transform block statement if block statement contain variable declaration with `const` kind', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #5: let declaration inside block statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-let-declaration.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+
+            it('shouldn\'t transform block statement if block statement contain variable declaration with `let` kind', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #6: break statement inside block statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-break-statement.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *break; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+
+            it('shouldn\'t transform block statement if block statement contain break statement', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #7: continue statement inside block statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-continue-statement.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *continue; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+
+            it('shouldn\'t transform block statement if block statement contain continue statement', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #8: function declaration inside block statement', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-function-declaration.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-z0-9]){4,6} *\( *\) *\{ *\} *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+
+            it('shouldn\'t transform block statement if block statement contain function declaration', () => {
+                assert.match(obfuscatedCode, statementRegExp);
+            });
+        });
+
+        describe('variant #9: `controlFlowFlatteningThreshold` chance', () => {
+            const samples: number = 1000;
+            const controlFlowFlatteningThreshold: number = 0.5;
+            const delta: number = 0.1;
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/block-statement-control-flow-transformer-1.js'
+                ).repeat(samples),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: controlFlowFlatteningThreshold,
+                }
+            );
+
+            const regExp1: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/g;
+            const regExp2: RegExp = /\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/g;
+            const transformedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
+            const untouchedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
+
+            it('should transform block statement with `controlFlowFlatteningThreshold` chance', () => {
+                console.log(obfuscationResult.getObfuscatedCode());
+                assert.closeTo(transformedStatementMatchesLength / samples, controlFlowFlatteningThreshold, delta);
+                assert.closeTo(untouchedStatementMatchesLength / samples, controlFlowFlatteningThreshold, delta);
+            });
+        });
     });
     });
 });
 });