Prechádzať zdrojové kódy

wip runtime error fix

sanex3339 8 rokov pred
rodič
commit
5469d4d3ed

+ 25 - 57
dist/index.js

@@ -361,6 +361,7 @@ var NodeUtils = function () {
                         value = parentNode || node;
                     }
                     node['parentNode'] = value;
+                    node['obfuscated'] = false;
                 }
             });
         }
@@ -383,14 +384,14 @@ var NodeUtils = function () {
             var traverseType = arguments.length <= 3 || arguments[3] === undefined ? 'traverse' : arguments[3];
 
             estraverse[traverseType](node, {
-                enter: function enter(node) {
+                enter: function enter(node, parentNode) {
                     if (node.type === nodeType && visitor.enter) {
-                        visitor.enter(node);
+                        visitor.enter(node, parentNode);
                     }
                 },
-                leave: function leave(node) {
+                leave: function leave(node, parentNode) {
                     if (node.type === nodeType && visitor.leave) {
-                        visitor.leave(node);
+                        visitor.leave(node, parentNode);
                     }
                 }
             });
@@ -445,7 +446,8 @@ var Nodes = function () {
             return {
                 'type': NodeType_1.NodeType.Program,
                 'body': bodyNode,
-                'sourceType': 'script'
+                'sourceType': 'script',
+                'obfuscated': false
             };
         }
     }, {
@@ -458,6 +460,11 @@ var Nodes = function () {
         value: function isBlockStatementNode(node) {
             return node.type === NodeType_1.NodeType.BlockStatement;
         }
+    }, {
+        key: "isCallExpressionNode",
+        value: function isCallExpressionNode(node) {
+            return node.type === NodeType_1.NodeType.CallExpression;
+        }
     }, {
         key: "isFunctionDeclarationNode",
         value: function isFunctionDeclarationNode(node) {
@@ -757,15 +764,9 @@ var IdentifierReplacer = function (_AbstractReplacer_1$A) {
     _inherits(IdentifierReplacer, _AbstractReplacer_1$A);
 
     function IdentifierReplacer() {
-        var _ref;
-
         _classCallCheck(this, IdentifierReplacer);
 
-        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
-            args[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = IdentifierReplacer.__proto__ || Object.getPrototypeOf(IdentifierReplacer)).call.apply(_ref, [this].concat(args)));
+        var _this = _possibleConstructorReturn(this, (IdentifierReplacer.__proto__ || Object.getPrototypeOf(IdentifierReplacer)).apply(this, arguments));
 
         _this.namesMap = new Map();
         return _this;
@@ -1631,15 +1632,9 @@ var ConsoleOutputDisableExpressionNode = function (_AbstractCustomNode_) {
     _inherits(ConsoleOutputDisableExpressionNode, _AbstractCustomNode_);
 
     function ConsoleOutputDisableExpressionNode() {
-        var _ref;
-
         _classCallCheck(this, ConsoleOutputDisableExpressionNode);
 
-        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
-            args[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = ConsoleOutputDisableExpressionNode.__proto__ || Object.getPrototypeOf(ConsoleOutputDisableExpressionNode)).call.apply(_ref, [this].concat(args)));
+        var _this = _possibleConstructorReturn(this, (ConsoleOutputDisableExpressionNode.__proto__ || Object.getPrototypeOf(ConsoleOutputDisableExpressionNode)).apply(this, arguments));
 
         _this.appendState = AppendState_1.AppendState.BeforeObfuscation;
         return _this;
@@ -1860,15 +1855,9 @@ var DomainLockNode = function (_AbstractCustomNode_) {
     _inherits(DomainLockNode, _AbstractCustomNode_);
 
     function DomainLockNode() {
-        var _ref;
-
         _classCallCheck(this, DomainLockNode);
 
-        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
-            args[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = DomainLockNode.__proto__ || Object.getPrototypeOf(DomainLockNode)).call.apply(_ref, [this].concat(args)));
+        var _this = _possibleConstructorReturn(this, (DomainLockNode.__proto__ || Object.getPrototypeOf(DomainLockNode)).apply(this, arguments));
 
         _this.appendState = AppendState_1.AppendState.BeforeObfuscation;
         return _this;
@@ -1929,15 +1918,9 @@ var SelfDefendingUnicodeNode = function (_AbstractCustomNode_) {
     _inherits(SelfDefendingUnicodeNode, _AbstractCustomNode_);
 
     function SelfDefendingUnicodeNode() {
-        var _ref;
-
         _classCallCheck(this, SelfDefendingUnicodeNode);
 
-        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
-            args[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = SelfDefendingUnicodeNode.__proto__ || Object.getPrototypeOf(SelfDefendingUnicodeNode)).call.apply(_ref, [this].concat(args)));
+        var _this = _possibleConstructorReturn(this, (SelfDefendingUnicodeNode.__proto__ || Object.getPrototypeOf(SelfDefendingUnicodeNode)).apply(this, arguments));
 
         _this.appendState = AppendState_1.AppendState.AfterObfuscation;
         return _this;
@@ -2712,9 +2695,13 @@ var FunctionObfuscator = function (_AbstractNodeObfuscat) {
             var _this3 = this;
 
             var replaceVisitor = {
-                leave: function leave(node, parentNode) {
+                enter: function enter(node, parentNode) {
                     if (Nodes_1.Nodes.isReplaceableIdentifierNode(node, parentNode)) {
-                        node.name = _this3.identifierReplacer.replace(node.name);
+                        var newNodeName = _this3.identifierReplacer.replace(node.name);
+                        if (node.name !== newNodeName) {
+                            node.name = newNodeName;
+                            node.obfuscated = true;
+                        }
                     }
                 }
             };
@@ -2905,15 +2892,9 @@ var MethodDefinitionObfuscator = function (_AbstractNodeObfuscat) {
     _inherits(MethodDefinitionObfuscator, _AbstractNodeObfuscat);
 
     function MethodDefinitionObfuscator() {
-        var _ref;
-
         _classCallCheck(this, MethodDefinitionObfuscator);
 
-        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
-            args[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = MethodDefinitionObfuscator.__proto__ || Object.getPrototypeOf(MethodDefinitionObfuscator)).call.apply(_ref, [this].concat(args)));
+        var _this = _possibleConstructorReturn(this, (MethodDefinitionObfuscator.__proto__ || Object.getPrototypeOf(MethodDefinitionObfuscator)).apply(this, arguments));
 
         _this.ignoredNames = ['constructor'];
         return _this;
@@ -3091,23 +3072,10 @@ var VariableDeclarationObfuscator = function (_AbstractNodeObfuscat) {
         value: function replaceVariableNames(variableDeclarationNode, variableParentNode) {
             var _this3 = this;
 
-            var scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils_1.NodeUtils.getBlockScopeOfNode(variableDeclarationNode) : variableParentNode,
-                isNodeAfterVariableDeclaratorFlag = false;
+            var scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils_1.NodeUtils.getBlockScopeOfNode(variableDeclarationNode) : variableParentNode;
             estraverse.replace(scopeNode, {
                 enter: function enter(node, parentNode) {
-                    if (Nodes_1.Nodes.isArrowFunctionExpressionNode(node) || Nodes_1.Nodes.isFunctionDeclarationNode(node) || Nodes_1.Nodes.isFunctionExpressionNode(node)) {
-                        estraverse.replace(node, {
-                            enter: function enter(node, parentNode) {
-                                if (Nodes_1.Nodes.isReplaceableIdentifierNode(node, parentNode)) {
-                                    node.name = _this3.identifierReplacer.replace(node.name);
-                                }
-                            }
-                        });
-                    }
-                    if (Nodes_1.Nodes.isVariableDeclarationNode(node) && node === variableDeclarationNode) {
-                        isNodeAfterVariableDeclaratorFlag = true;
-                    }
-                    if (Nodes_1.Nodes.isReplaceableIdentifierNode(node, parentNode) && isNodeAfterVariableDeclaratorFlag) {
+                    if (!node.obfuscated && Nodes_1.Nodes.isReplaceableIdentifierNode(node, parentNode)) {
                         node.name = _this3.identifierReplacer.replace(node.name);
                     }
                 }

+ 6 - 5
src/NodeUtils.ts

@@ -148,6 +148,7 @@ export class NodeUtils {
                 }
 
                 node['parentNode'] = value;
+                node['obfuscated'] = false;
             }
         });
     }
@@ -186,18 +187,18 @@ export class NodeUtils {
     public static typedTraverse (
         node: ESTree.Node,
         nodeType: string,
-        visitor: {enter?: (node: ESTree.Node) => void, leave?: (node: ESTree.Node) => void},
+        visitor: estraverse.Visitor,
         traverseType: string = 'traverse'
     ): void {
         (<any>estraverse)[traverseType](node, {
-            enter: (node: ESTree.Node): any => {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (node.type === nodeType && visitor.enter) {
-                    visitor.enter(node);
+                    visitor.enter(node, parentNode);
                 }
             },
-            leave: (node: ESTree.Node): any => {
+            leave: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (node.type === nodeType && visitor.leave) {
-                    visitor.leave(node);
+                    visitor.leave(node, parentNode);
                 }
             }
         });

+ 10 - 1
src/Nodes.ts

@@ -13,7 +13,8 @@ export class Nodes {
         return {
             'type': NodeType.Program,
             'body': bodyNode,
-            'sourceType': 'script'
+            'sourceType': 'script',
+            'obfuscated': false
         };
     }
 
@@ -33,6 +34,14 @@ export class Nodes {
         return node.type === NodeType.BlockStatement;
     }
 
+    /**
+     * @param node
+     * @returns {boolean}
+     */
+    public static isCallExpressionNode (node: ESTree.Node): node is ESTree.CallExpression {
+        return node.type === NodeType.CallExpression;
+    }
+
     /**
      * @param node
      * @returns {boolean}

+ 1 - 0
src/declarations/ESTree.d.ts

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 declare module 'estree' {
     interface BaseNode {
         parentNode?: ESTree.Node;
+        obfuscated?: boolean;
     }
 
     interface SimpleLiteral extends ESTree.BaseNode, ESTree.BaseExpression {

+ 7 - 2
src/node-obfuscators/FunctionObfuscator.ts

@@ -60,9 +60,14 @@ export class FunctionObfuscator extends AbstractNodeObfuscator {
      */
     private replaceFunctionParams (functionNode: ESTree.Function): void {
         let replaceVisitor: estraverse.Visitor = {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node): any => {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (Nodes.isReplaceableIdentifierNode(node, parentNode)) {
-                    node.name = this.identifierReplacer.replace(node.name);
+                    const newNodeName: string = this.identifierReplacer.replace(node.name);
+
+                    if (node.name !== newNodeName) {
+                        node.name = newNodeName;
+                        node.obfuscated = true;
+                    }
                 }
             }
         };

+ 2 - 21
src/node-obfuscators/VariableDeclarationObfuscator.ts

@@ -69,30 +69,11 @@ export class VariableDeclarationObfuscator extends AbstractNodeObfuscator {
     private replaceVariableNames (variableDeclarationNode: ESTree.VariableDeclaration, variableParentNode: ESTree.Node): void {
         let scopeNode: ESTree.Node = variableDeclarationNode.kind === 'var' ? NodeUtils.getBlockScopeOfNode(
                 variableDeclarationNode
-            ) : variableParentNode,
-            isNodeAfterVariableDeclaratorFlag: boolean = false;
+            ) : variableParentNode;
 
         estraverse.replace(scopeNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
-                if (
-                    Nodes.isArrowFunctionExpressionNode(node) ||
-                    Nodes.isFunctionDeclarationNode(node) ||
-                    Nodes.isFunctionExpressionNode(node)
-                ) {
-                    estraverse.replace(node, {
-                        enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
-                            if (Nodes.isReplaceableIdentifierNode(node, parentNode)) {
-                                node.name = this.identifierReplacer.replace(node.name);
-                            }
-                        }
-                    });
-                }
-
-                if (Nodes.isVariableDeclarationNode(node) && node === variableDeclarationNode) {
-                    isNodeAfterVariableDeclaratorFlag = true;
-                }
-
-                if (Nodes.isReplaceableIdentifierNode(node, parentNode) && isNodeAfterVariableDeclaratorFlag) {
+                if (!node.obfuscated && Nodes.isReplaceableIdentifierNode(node, parentNode)) {
                     node.name = this.identifierReplacer.replace(node.name);
                 }
             }

+ 20 - 0
test/functional-tests/node-obfuscators/FunctionObfuscator.spec.ts

@@ -0,0 +1,20 @@
+import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
+
+import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
+
+import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
+
+const assert: Chai.AssertStatic = require('chai').assert;
+
+describe('FunctionObfuscator', () => {
+    describe('obfuscation of identifiers of FunctionDeclaration and FunctionExpression node body', () => {
+        it('should replace identifier name with obfuscated one', () => {
+            let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                `var test = 'test';`,
+                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            );
+
+            assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
+        });
+    });
+});

+ 59 - 1
test/functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec.ts

@@ -82,7 +82,65 @@ describe('VariableDeclarationObfuscator', () => {
         });
 
         it('should not obfuscate variable call (`identifier` node) before variable declaration', () => {
-            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(abc\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){5,6}\);/);
+        });
+    });
+
+    describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
+        let obfuscationResult: IObfuscationResult,
+            functionParamIdentifierName: string|null,
+            innerFunctionParamIdentifierName: string|null,
+            constructorIdentifierName: string|null,
+            objectIdentifierName: string|null,
+            variableDeclarationIdentifierName: string|null;
+
+        beforeEach(() => {
+            obfuscationResult = JavaScriptObfuscator.obfuscate(
+                `
+                    (function () {
+                        function foo (t, e) {
+                            return function () {
+                                function baz (t) {
+                                    console.log(t);
+                                }
+                        
+                                return {t: t};
+                                var t;
+                            }();
+                        }
+                    })();
+                `,
+                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            );
+        });
+
+        it('blablabla', () => {
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+            const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+                .match(/function *_0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\,(_0x[a-z0-9]{5,6})\) *\{/);
+            const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+                .match(/function _0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\) *\{/);
+            const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+                .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
+            const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+                .match(/return\{'\\x74':(_0x[a-z0-9]{5,6})\}/);
+            const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+                .match(/var *(_0x[a-z0-9]{5,6});/);
+
+            functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
+            innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
+            constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
+            objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
+            variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
+
+            assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
+            assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
+
+            assert.notEqual(functionParamIdentifierName, objectIdentifierName);
+            assert.notEqual(functionParamIdentifierName, variableDeclarationIdentifierName);
+
+            assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
+            assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
         });
     });
 

+ 25 - 12
test/mocks/NodeMocks.ts

@@ -12,7 +12,8 @@ export class NodeMocks {
         return {
             type: NodeType.Program,
             body: bodyNodes,
-            sourceType: 'script'
+            sourceType: 'script',
+            obfuscated: false
         };
     }
 
@@ -23,7 +24,8 @@ export class NodeMocks {
     public static getBlockStatementNode (bodyNodes: ESTree.Statement[] = []): ESTree.BlockStatement {
         return {
             type: NodeType.BlockStatement,
-            body: bodyNodes
+            body: bodyNodes,
+            obfuscated: false
         };
     }
 
@@ -35,7 +37,8 @@ export class NodeMocks {
         return {
             type: NodeType.CatchClause,
             param: NodeMocks.getIdentifierNode('err'),
-            body: NodeMocks.getBlockStatementNode(bodyNodes)
+            body: NodeMocks.getBlockStatementNode(bodyNodes),
+            obfuscated: false
         };
     }
 
@@ -51,7 +54,8 @@ export class NodeMocks {
         return {
             type: NodeType.CallExpression,
             callee: callee,
-            arguments: args
+            arguments: args,
+            obfuscated: false
         };
     }
 
@@ -64,7 +68,8 @@ export class NodeMocks {
     ): ESTree.ExpressionStatement {
         return {
             type: NodeType.ExpressionStatement,
-            expression: expression
+            expression: expression,
+            obfuscated: false
         };
     }
 
@@ -84,7 +89,8 @@ export class NodeMocks {
             id: NodeMocks.getIdentifierNode(functionName),
             params: params,
             body: blockStatementNode,
-            generator: false
+            generator: false,
+            obfuscated: false
         };
     }
 
@@ -98,9 +104,11 @@ export class NodeMocks {
             test: {
                 type: 'Literal',
                 value: true,
-                raw: 'true'
+                raw: 'true',
+                obfuscated: false
             },
-            consequent: blockStatementNode
+            consequent: blockStatementNode,
+            obfuscated: false
         };
     }
 
@@ -112,6 +120,7 @@ export class NodeMocks {
         return {
             type: NodeType.Identifier,
             name: identifierName,
+            obfuscated: false
         };
     }
 
@@ -127,7 +136,8 @@ export class NodeMocks {
             'x-verbatim-property': {
                 content: `'${value}'`,
                 precedence: escodegen.Precedence.Primary
-            }
+            },
+            obfuscated: false
         };
     }
 
@@ -144,7 +154,8 @@ export class NodeMocks {
             type: NodeType.MemberExpression,
             computed: false,
             object: object,
-            property: property
+            property: property,
+            obfuscated: false
         };
     }
 
@@ -160,7 +171,8 @@ export class NodeMocks {
         return {
             type: NodeType.VariableDeclaration,
             declarations: declarations,
-            kind: kind
+            kind: kind,
+            obfuscated: false
         };
     }
 
@@ -173,7 +185,8 @@ export class NodeMocks {
         return {
             type: NodeType.VariableDeclarator,
             id: id,
-            init: init
+            init: init,
+            obfuscated: false
         };
     }
 }

+ 2 - 1
webpack.config.js

@@ -5,7 +5,8 @@ var fs = require("fs"),
     webpack = require('webpack');
 
 function getLicenseText () {
-    return "/*\nCopyright (C) 2016 Timofey Kachalov <[email protected]>\n\n" + fs.readFileSync('./LICENSE.BSD', 'utf8') + "\n*/";
+    return "/*\nCopyright (C) 2016 Timofey Kachalov <[email protected]>\n\n" +
+        fs.readFileSync('./LICENSE.BSD', 'utf8') + "\n*/";
 }
 
 module.exports = {