Browse Source

Added more restrictions for object keys transformations
Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516

sanex3339 5 years ago
parent
commit
7b231fe308

+ 1 - 0
CHANGELOG.md

@@ -6,6 +6,7 @@ v0.24.0
 * Dynamic import and `import.meta` support. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/505
 * Now usage of some browser-related options with `target: 'node'` will cause a validation error
 * **CLI:** a file path will be displayed on obfuscation error. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/513
+* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/512
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/496
 * **Internal:** switched from `awesome-typescript-loader` on `ts-loader`

File diff suppressed because it is too large
+ 0 - 0
dist/index.browser.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.cli.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.24.0-rc.0",
+  "version": "0.24.0-rc.1",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",

+ 50 - 1
src/node-transformers/converting-transformers/properties-extractors/AbstractPropertiesExtractor.ts

@@ -89,6 +89,50 @@ export abstract class AbstractPropertiesExtractor implements IPropertiesExtracto
             || NodeGuards.isRestElementNode(node);
     }
 
+    /**
+     * @param {ObjectExpression} objectExpressionNode
+     * @param {Statement} hostStatement
+     * @returns {boolean}
+     */
+    protected static isProhibitedHostStatement (
+        objectExpressionNode: ESTree.ObjectExpression,
+        hostStatement: ESTree.Statement
+    ): boolean {
+        if (AbstractPropertiesExtractor.isProhibitedVariableDeclarationHostStatement(objectExpressionNode, hostStatement)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Fix of https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
+     * If object expression is placed inside any expression inside variable declaration with 2+ declarators
+     * - should mark host node as prohibited
+     *
+     * @param {ObjectExpression} objectExpressionNode
+     * @param {Statement} hostStatement
+     * @returns {boolean}
+     */
+    protected static isProhibitedVariableDeclarationHostStatement (
+        objectExpressionNode: ESTree.ObjectExpression,
+        hostStatement: ESTree.Statement
+    ): boolean {
+        if (!NodeGuards.isVariableDeclarationNode(hostStatement)) {
+            return false;
+        }
+
+        if (objectExpressionNode.parentNode && NodeGuards.isVariableDeclaratorNode(objectExpressionNode.parentNode)) {
+            return false;
+        }
+
+        if (hostStatement.declarations.length <= 1) {
+            return false;
+        }
+
+        return true;
+    }
+
     /**
      * @param {ObjectExpression} objectExpressionNode
      * @param {Node} hostNode
@@ -182,11 +226,16 @@ export abstract class AbstractPropertiesExtractor implements IPropertiesExtracto
         objectExpressionNode: ESTree.ObjectExpression,
         memberExpressionHostNode: ESTree.Expression
     ): ESTree.Node {
+        const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);
+
+        if (AbstractPropertiesExtractor.isProhibitedHostStatement(objectExpressionNode, hostStatement)) {
+            return objectExpressionNode;
+        }
+
         const properties: ESTree.Property[] = objectExpressionNode.properties;
         const [expressionStatements, removablePropertyIds]: [ESTree.ExpressionStatement[], number[]] = this
             .extractPropertiesToExpressionStatements(properties, memberExpressionHostNode);
 
-        const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);
         const hostNodeWithStatements: TNodeWithStatements = this.getHostNodeWithStatements(
             objectExpressionNode,
             hostStatement

+ 6 - 1
src/node-transformers/converting-transformers/properties-extractors/BasePropertiesExtractor.ts

@@ -67,6 +67,12 @@ export class BasePropertiesExtractor extends AbstractPropertiesExtractor {
         objectExpressionNode: ESTree.ObjectExpression,
         parentNode: ESTree.Node
     ): ESTree.Node {
+        const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);
+
+        if (AbstractPropertiesExtractor.isProhibitedHostStatement(objectExpressionNode, hostStatement)) {
+            return objectExpressionNode;
+        }
+
         const newObjectExpressionHostNode: ESTree.VariableDeclaration = this.getObjectExpressionHostNode();
         const newObjectExpressionIdentifier: ESTree.Identifier = this.getObjectExpressionIdentifierNode(newObjectExpressionHostNode);
 
@@ -79,7 +85,6 @@ export class BasePropertiesExtractor extends AbstractPropertiesExtractor {
             ...expressionStatements
         ];
 
-        const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);
         const hostNodeWithStatements: TNodeWithStatements = this.getHostNodeWithStatements(
             objectExpressionNode,
             hostStatement

+ 4 - 5
test/dev/dev.ts

@@ -7,11 +7,10 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
-            const foo = \`\${{
-                foo: 'bar',
-                baz: 'bark'
-            }.baz}\`;
-            console.log(foo);
+            var passthrough = (object) => object;
+            var foo = {foo: 1},\t
+                bar = passthrough({bar: foo.foo});
+            console.log(bar.bar);
         `,
         {
             ...NO_ADDITIONAL_NODES_PRESET,

+ 120 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts

@@ -479,6 +479,7 @@ describe('ObjectExpressionKeysTransformer', () => {
             });
         });
 
+        // issue https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
         describe('Variant #15: function default values', () => {
             const match: string = `` +
                 `var *${variableMatch} *= *{};` +
@@ -505,6 +506,125 @@ describe('ObjectExpressionKeysTransformer', () => {
                 assert.match(obfuscatedCode,  regExp);
             });
         });
+
+        // issue https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
+        describe('Variant #16: object expression inside inside variable declaration', () => {
+            describe('Without reference on other property', () => {
+                describe('Variant #1: Single variable declarator and object expression parent node is expression node', () => {
+                    const match: string = `` +
+                        `var *passthrough *= *${variableMatch} *=> *${variableMatch};` +
+                        `var *${variableMatch} *= *{};` +
+                        `${variableMatch}\\['foo'] *= *0x1;` +
+                        `var foo *= *passthrough *\\(${variableMatch}\\);` +
+                    ``;
+                    const regExp: RegExp = new RegExp(match);
+
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/object-expression-inside-variable-declaration-1.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                transformObjectKeys: true
+                            }
+                        ).getObfuscatedCode();
+                    });
+
+                    it('should transform object expression keys', () => {
+                        assert.match(obfuscatedCode,  regExp);
+                    });
+                });
+
+                describe('Variant #2: Multiple variable declarators and object expression parent node is variable declarator node', () => {
+                    const match: string = `` +
+                        `var foo *= *{}, *bar *= *{};` +
+                        `bar\\['bar'] *= *0x2;` +
+                        `foo\\['foo'] *= *0x1;` +
+                    ``;
+                    const regExp: RegExp = new RegExp(match);
+
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/object-expression-inside-variable-declaration-2.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                transformObjectKeys: true
+                            }
+                        ).getObfuscatedCode();
+                    });
+
+                    it('should transform object expressions keys', () => {
+                        assert.match(obfuscatedCode,  regExp);
+                    });
+                });
+            });
+
+            describe('With reference on other property', () => {
+                describe('Variant #1: Object expression parent node is variable declarator node', () => {
+                    const match: string = `` +
+                        `var *passthrough *= *${variableMatch} *=> *${variableMatch};` +
+                        `var *${variableMatch} *= *{};` +
+                        `${variableMatch}\\['foo'] *= *0x1;` +
+                        `var foo *= *${variableMatch}, *bar *= *{};` +
+                        `bar\\['bar'] *= *foo.foo;` +
+                    ``;
+                    const regExp: RegExp = new RegExp(match);
+
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/object-expression-inside-variable-declaration-3.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                transformObjectKeys: true
+                            }
+                        ).getObfuscatedCode();
+                    });
+
+                    it('should transform first object expression keys and ignore second object expression keys', () => {
+                        assert.match(obfuscatedCode,  regExp);
+                    });
+                });
+
+                describe('Variant #2: Object expression parent node is any expression node', () => {
+                    const match: string = `` +
+                        `var *passthrough *= *${variableMatch} *=> *${variableMatch};` +
+                        `var *${variableMatch} *= *{};` +
+                        `${variableMatch}\\['foo'] *= *0x1;` +
+                        `var foo *= *${variableMatch}, *bar *= *passthrough *\\({ *'bar' *: *foo\\['foo'] *}\\);` +
+                    ``;
+                    const regExp: RegExp = new RegExp(match);
+
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/object-expression-inside-variable-declaration-4.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                transformObjectKeys: true
+                            }
+                        ).getObfuscatedCode();
+                    });
+
+                    it('should transform first object expression keys and ignore second object expression keys', () => {
+                        assert.match(obfuscatedCode,  regExp);
+                    });
+                });
+            });
+        });
     });
 
     describe('member expression as host of object expression', () => {

+ 2 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/object-expression-inside-variable-declaration-1.js

@@ -0,0 +1,2 @@
+var passthrough = (object) => object;
+var foo = passthrough({foo: 1});

+ 2 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/object-expression-inside-variable-declaration-2.js

@@ -0,0 +1,2 @@
+var foo = {foo: 1},
+    bar = {bar: 2};

+ 3 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/object-expression-inside-variable-declaration-3.js

@@ -0,0 +1,3 @@
+var passthrough = (object) => object;
+var foo = {foo: 1},
+    bar = {bar: foo.foo};

+ 3 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/object-expression-inside-variable-declaration-4.js

@@ -0,0 +1,3 @@
+var passthrough = (object) => object;
+var foo = {foo: 1},
+    bar = passthrough({bar: foo.foo});

Some files were not shown because too many files changed in this diff