Code coverage report for src/node-transformers/node-obfuscators/MemberExpressionObfuscator.ts

# All files / src/node-transformers/node-obfuscators MemberExpressionObfuscator.ts

100% Statements 28/28
100% Branches 10/10
100% Functions 2/2
100% Lines 27/27

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    1121x
    1x

    1x
    1x

    1x
    1x

    1x
    1x

    1x
    1x

    2586x

    2586x

    31646x

    31654x
    5097x

    5097x

    26557x
    26553x
    1573x

    24980x
    24980x

    24980x
    24980x

    24980x

    24980x

    5097x
    4077x

     import { injectable, inject } from 'inversify';
    import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';

    import * as escodegen from 'escodegen';
    import * as estraverse from 'estraverse';
    import * as ESTree from 'estree';

    import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
    import { IOptions } from '../../interfaces/options/IOptions';
    import { IReplacer } from '../../interfaces/node-transformers/IReplacer';
    import { IStorage } from '../../interfaces/storages/IStorage';

    import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscatorsReplacers';
    import { NodeType } from '../../enums/NodeType';

    import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
    import { Node } from '../../node/Node';

    @injectable()
    export class MemberExpressionObfuscator extends AbstractNodeTransformer {
        /**
         * @type {IReplacer}
         */
        private readonly stringLiteralReplacer: IReplacer;

        /**
         * @param customNodesStorage
         * @param replacersFactory
         * @param options
         */
        constructor(
            @inject(ServiceIdentifiers['IStorage<ICustomNode>']) customNodesStorage: IStorage<ICustomNode>,
            @inject(ServiceIdentifiers['Factory<IReplacer>']) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IReplacer,
            @inject(ServiceIdentifiers.IOptions) options: IOptions
        ) {
            super(customNodesStorage, options);

            this.stringLiteralReplacer = replacersFactory(NodeObfuscatorsReplacers.StringLiteralReplacer);
        }

        /**
         * @param memberExpressionNode
         */
        public transformNode (memberExpressionNode: ESTree.MemberExpression): void {
            estraverse.traverse(memberExpressionNode.property, {
                enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                    if (Node.isLiteralNode(node)) {
                        this.obfuscateLiteralProperty(node);

                        return;
                    }

                    if (Node.isIdentifierNode(node)) {
                        if (memberExpressionNode.computed) {
                            return;
                        }

                        memberExpressionNode.computed = true;
                        this.obfuscateIdentifierProperty(node);
                    }
                }
            });
        }

        /**
         * replaces:
         *     object.identifier = 1;
         *
         * on:
         *     object[_0x23d45[25]] = 1;
         *
         * and skip:
         *     object[identifier] = 1;
         *
         * @param node
         */
        private obfuscateIdentifierProperty (node: ESTree.Identifier): void {
            const nodeValue: string = node.name;
            const literalNode: ESTree.Literal = {
                raw: `'${nodeValue}'`,
                'x-verbatim-property': {
                    content: this.stringLiteralReplacer.replace(nodeValue),
                    precedence: escodegen.Precedence.Primary
                },
                type: NodeType.Literal,
                value: nodeValue
            };

            delete node.name;

            Object.assign(node, literalNode);
        }

        /**
         * replaces:
         *     object['literal'] = 1;
         *
         * on:
         *     object[_0x23d45[25]] = 1;
         *
         * @param node
         */
        private obfuscateLiteralProperty (node: ESTree.Literal): void {
            if (typeof node.value === 'string' && !node['x-verbatim-property']) {
                node['x-verbatim-property'] = {
                    content : this.stringLiteralReplacer.replace(node.value),
                    precedence: escodegen.Precedence.Primary
                };
            }
        }
    }