瀏覽代碼

ArrayPattern and AssignmentPattern function parameters obfuscation + tests

sanex3339 8 年之前
父節點
當前提交
a295f77101

+ 28 - 4
dist/index.js

@@ -90,7 +90,7 @@ module.exports =
 /******/ 	__webpack_require__.p = "";
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 150);
+/******/ 	return __webpack_require__(__webpack_require__.s = 151);
 /******/ })
 /************************************************************************/
 /******/ ([
@@ -567,6 +567,11 @@ var Node = function () {
         value: function isArrowFunctionExpressionNode(node) {
             return node.type === NodeType_1.NodeType.ArrowFunctionExpression;
         }
+    }, {
+        key: "isAssignmentPatternNode",
+        value: function isAssignmentPatternNode(node) {
+            return node.type === NodeType_1.NodeType.AssignmentPattern;
+        }
     }, {
         key: "isBlockStatementNode",
         value: function isBlockStatementNode(node) {
@@ -635,6 +640,11 @@ var Node = function () {
         value: function isMemberExpressionNode(node) {
             return node.type === NodeType_1.NodeType.MemberExpression;
         }
+    }, {
+        key: "isObjectPatternNode",
+        value: function isObjectPatternNode(node) {
+            return node.type === NodeType_1.NodeType.ObjectPattern;
+        }
     }, {
         key: "isObjectExpressionNode",
         value: function isObjectExpressionNode(node) {
@@ -1002,6 +1012,7 @@ exports.NodeType = Utils_1.Utils.strEnumify({
     ArrayExpression: 'ArrayExpression',
     ArrowFunctionExpression: 'ArrowFunctionExpression',
     AssignmentExpression: 'AssignmentExpression',
+    AssignmentPattern: 'AssignmentPattern',
     BinaryExpression: 'BinaryExpression',
     BlockStatement: 'BlockStatement',
     BreakStatement: 'BreakStatement',
@@ -1020,6 +1031,7 @@ exports.NodeType = Utils_1.Utils.strEnumify({
     MemberExpression: 'MemberExpression',
     MethodDefinition: 'MethodDefinition',
     ObjectExpression: 'ObjectExpression',
+    ObjectPattern: 'ObjectPattern',
     Program: 'Program',
     Property: 'Property',
     ReturnStatement: 'ReturnStatement',
@@ -6032,9 +6044,20 @@ var FunctionTransformer = function (_AbstractNodeTransfor) {
             var _this2 = this;
 
             functionNode.params.forEach(function (paramsNode) {
-                if (Node_1.Node.isIdentifierNode(paramsNode)) {
-                    _this2.identifierReplacer.storeNames(paramsNode.name, nodeIdentifier);
+                if (Node_1.Node.isObjectPatternNode(paramsNode)) {
+                    return estraverse.VisitorOption.Skip;
                 }
+                estraverse.traverse(paramsNode, {
+                    enter: function enter(node) {
+                        if (Node_1.Node.isAssignmentPatternNode(node) && Node_1.Node.isIdentifierNode(node.left)) {
+                            _this2.identifierReplacer.storeNames(node.left.name, nodeIdentifier);
+                            return estraverse.VisitorOption.Skip;
+                        }
+                        if (Node_1.Node.isIdentifierNode(node)) {
+                            _this2.identifierReplacer.storeNames(node.name, nodeIdentifier);
+                        }
+                    }
+                });
             });
         }
     }, {
@@ -8121,7 +8144,8 @@ module.exports = require("mkdirp");
 module.exports = require("reflect-metadata");
 
 /***/ }),
-/* 150 */
+/* 150 */,
+/* 151 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";

+ 2 - 0
src/enums/NodeType.ts

@@ -4,6 +4,7 @@ export const NodeType: any = Utils.strEnumify({
     ArrayExpression: 'ArrayExpression',
     ArrowFunctionExpression: 'ArrowFunctionExpression',
     AssignmentExpression: 'AssignmentExpression',
+    AssignmentPattern: 'AssignmentPattern',
     BinaryExpression: 'BinaryExpression',
     BlockStatement: 'BlockStatement',
     BreakStatement: 'BreakStatement',
@@ -22,6 +23,7 @@ export const NodeType: any = Utils.strEnumify({
     MemberExpression: 'MemberExpression',
     MethodDefinition: 'MethodDefinition',
     ObjectExpression: 'ObjectExpression',
+    ObjectPattern: 'ObjectPattern',
     Program: 'Program',
     Property: 'Property',
     ReturnStatement: 'ReturnStatement',

+ 16 - 2
src/node-transformers/obfuscating-transformers/FunctionTransformer.ts

@@ -61,9 +61,23 @@ export class FunctionTransformer extends AbstractNodeTransformer {
     private storeFunctionParams (functionNode: ESTree.Function, nodeIdentifier: number): void {
         functionNode.params
             .forEach((paramsNode: ESTree.Node) => {
-                if (Node.isIdentifierNode(paramsNode)) {
-                    this.identifierReplacer.storeNames(paramsNode.name, nodeIdentifier);
+                if (Node.isObjectPatternNode(paramsNode)) {
+                    return estraverse.VisitorOption.Skip;
                 }
+
+                estraverse.traverse(paramsNode, {
+                    enter: (node: ESTree.Node): any => {
+                        if (Node.isAssignmentPatternNode(node) && Node.isIdentifierNode(node.left)) {
+                            this.identifierReplacer.storeNames(node.left.name, nodeIdentifier);
+
+                            return estraverse.VisitorOption.Skip;
+                        }
+
+                        if (Node.isIdentifierNode(node)) {
+                            this.identifierReplacer.storeNames(node.name, nodeIdentifier);
+                        }
+                    }
+                });
             });
     }
 

+ 16 - 0
src/node/Node.ts

@@ -13,6 +13,14 @@ export class Node {
         return node.type === NodeType.ArrowFunctionExpression;
     }
 
+    /**
+     * @param node
+     * @returns {boolean}
+     */
+    public static isAssignmentPatternNode (node: ESTree.Node): node is ESTree.AssignmentPattern {
+        return node.type === NodeType.AssignmentPattern;
+    }
+
     /**
      * @param node
      * @returns {boolean}
@@ -122,6 +130,14 @@ export class Node {
         return node.type === NodeType.MemberExpression;
     }
 
+    /**
+     * @param node
+     * @returns {boolean}
+     */
+    public static isObjectPatternNode (node: ESTree.Node): node is ESTree.ObjectPattern {
+        return node.type === NodeType.ObjectPattern;
+    }
+
     /**
      * @param node
      * @returns {boolean}

+ 4 - 77
test/dev/dev.ts

@@ -11,83 +11,10 @@ if (!(<any>global)._babelPolyfill) {
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
             (function(){
-                var result = 1,
-                    term1 = 0,
-                    term2 = 1,
-                    i = 1;
-                while(i < 10)
-                {
-                    var test = 10;
-                    result = term1 + term2;
-                    console.log(result);
-                    term1 = term2;
-                    term2 = result;
-                    i++;
-                }
-        
-                console.log(test);
-                
-                var test = function (test) {
-                    console.log(test);
-                    
-                    if (true) {
-                        var test = 5
-                    }
-                    
-                    return test;
-                }
-                
-                console.log(test(1));
-                
-                function test2 (abc) {
-                    function test1 () {
-                      console.log('inside', abc.item);
-                    }
-                    
-                    console.log('тест', abc);
-                    
-                    var abc = {};
-                    
-                    return abc.item = 15, test1();
-                };
-                
-                var regexptest = /version\\/(\\d+)/i;
-                console.log(regexptest);
-                
-                test2(22);
-                console.log(105.4);
-                console.log(true, false);
-                
-                var sA = 'shorthand1';
-                var sB = 'shorthand2';
-                
-                console.log({sA, sB});
-                
-                try {
-                } catch (error) {
-                    console.log(error);
-                }
-                
-                function foo () {
-                    return function () {
-                        var sum1 = 10 + 20;
-                        var sum2 = 20 + 30;
-                        var sum3 = 30 + 50;
-                        var sub = sum3 - sum2;
-                        
-                        return sum1 + sub;
-                    }
-                }
-                
-                console.log(foo()());
-                
-                if (true) {
-                    console.log(\`1\`);
-                    console.log(\`2\`);
-                    console.log(\`3\`);
-                    console.log(\`4\`);
-                    console.log(\`5\`);
-                }
+                 var foo = 1;
+                 var test = function (foo, abc = foo) {
+                    return foo, abc;
+                 }
             })();
         `,
         {

+ 86 - 0
test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/FunctionTransformer.spec.ts

@@ -52,4 +52,90 @@ describe('FunctionTransformer', () => {
             assert.match(obfuscatedCode, functionBodyMatch);
         });
     });
+
+    describe('assignment pattern as parameter', () => {
+        describe('literal as right value', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(__dirname + '/fixtures/assignment-pattern-as-parameter-1.js'),
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            it('should transform function parameter assignment pattern identifier', () => {
+                const functionParameterMatch: RegExp = /function *\(_0x[a-f0-9]{4,6} *= *0x1\) *\{/;
+                const functionBodyMatch: RegExp = /return *_0x[a-f0-9]{4,6};/;
+
+                assert.match(obfuscatedCode, functionParameterMatch);
+                assert.match(obfuscatedCode, functionBodyMatch);
+            });
+        });
+
+        describe('identifier as right value', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(__dirname + '/fixtures/assignment-pattern-as-parameter-2.js'),
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+            const variableDeclarationMatch: RegExp = /var *(_0x[a-f0-9]{4,6}) *= *0x1;/;
+            const functionParameterMatch: RegExp = /function *\((_0x[a-f0-9]{4,6}), *(_0x[a-f0-9]{4,6}) *= *(_0x[a-f0-9]{4,6})\) *\{/;
+            const functionBodyMatch: RegExp = /return *(_0x[a-f0-9]{4,6}) *\+ *(_0x[a-f0-9]{4,6});/;
+
+            const variableDeclarationIdentifierName: string = obfuscatedCode.match(variableDeclarationMatch)![1];
+            const functionParameterIdentifierName: string = obfuscatedCode.match(functionParameterMatch)![1];
+            const functionDefaultParameterIdentifierName1: string = obfuscatedCode.match(functionParameterMatch)![2];
+            const functionDefaultParameterIdentifierName2: string = obfuscatedCode.match(functionParameterMatch)![3];
+
+            const functionBodyIdentifierName1: string = obfuscatedCode.match(functionBodyMatch)![1];
+            const functionBodyIdentifierName2: string = obfuscatedCode.match(functionBodyMatch)![2];
+
+            it('should transform function parameter assignment pattern identifier', () => {
+                assert.match(obfuscatedCode, variableDeclarationMatch);
+                assert.match(obfuscatedCode, functionParameterMatch);
+                assert.match(obfuscatedCode, functionBodyMatch);
+            });
+
+            it('shouldn\'t keep same names variable declaration identifier and function parameters identifiers', () => {
+                assert.notEqual(variableDeclarationIdentifierName, functionParameterIdentifierName);
+                assert.notEqual(variableDeclarationIdentifierName, functionDefaultParameterIdentifierName1);
+                assert.notEqual(variableDeclarationIdentifierName, functionDefaultParameterIdentifierName2);
+            });
+
+            it('should keep same names for identifier in first function parameter and default value identifier of second function parameter', () => {
+                assert.equal(functionParameterIdentifierName, functionDefaultParameterIdentifierName2);
+            });
+
+            it('should keep same names for identifiers in function params and function body', () => {
+                assert.equal(functionParameterIdentifierName, functionBodyIdentifierName1);
+                assert.equal(functionDefaultParameterIdentifierName1, functionBodyIdentifierName2);
+            });
+        });
+    });
+
+    describe('array pattern as parameter', () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/array-pattern-as-parameter.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        const functionParameterMatch: RegExp = /function *\(\[(_0x[a-f0-9]{4,6}), *(_0x[a-f0-9]{4,6})\]\) *\{/;
+        const functionBodyMatch: RegExp = /return *(_0x[a-f0-9]{4,6}) *\+ *(_0x[a-f0-9]{4,6});/;
+
+        const arrayPatternIdentifierName1: string = obfuscatedCode.match(functionParameterMatch)![1];
+        const arrayPatternIdentifierName2: string = obfuscatedCode.match(functionParameterMatch)![2];
+        const functionBodyIdentifierName1: string = obfuscatedCode.match(functionBodyMatch)![1];
+        const functionBodyIdentifierName2: string = obfuscatedCode.match(functionBodyMatch)![2];
+
+        it('should keep same names for identifiers in function parameter array pattern and function body', () => {
+            assert.equal(arrayPatternIdentifierName1, functionBodyIdentifierName1);
+            assert.equal(arrayPatternIdentifierName2, functionBodyIdentifierName2);
+        });
+    });
 });

+ 5 - 0
test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/fixtures/array-pattern-as-parameter.js

@@ -0,0 +1,5 @@
+(function () {
+    var test = function ([foo, bar]) {
+        return foo + bar;
+    }
+})();

+ 5 - 0
test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/fixtures/assignment-pattern-as-parameter-1.js

@@ -0,0 +1,5 @@
+(function () {
+    var test = function (bar = 1) {
+        return bar;
+    }
+})();

+ 6 - 0
test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/fixtures/assignment-pattern-as-parameter-2.js

@@ -0,0 +1,6 @@
+(function () {
+    var foo = 1;
+    var test = function (foo, bar = foo) {
+        return foo + bar;
+    }
+})();