Forráskód Böngészése

Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/71

sanex3339 7 éve
szülő
commit
0c357a0f2b

+ 15 - 14
CHANGELOG.md

@@ -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
 ---

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/index.js


+ 31 - 6
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -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 - 0
src/node/Node.ts

@@ -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;
+    }
 }

+ 118 - 6
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts

@@ -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
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/break-statement.js → test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/break-statement-1.js


+ 12 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/break-statement-2.js

@@ -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);
+    }
+})();

+ 12 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/break-statement-inside-while-statement.js

@@ -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
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/continue-statement.js → test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/continue-statement-1.js


+ 12 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/continue-statement-2.js

@@ -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);
+    }
+})();

+ 12 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/continue-statement-inside-while-statement.js

@@ -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);
+    }
+})();

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott