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

100% Statements 29/29
100% Branches 10/10
100% Functions 2/2
100% Lines 26/26

    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
    1081x
    1x

    1x
    1x

    1x
    1x

    1x
    1x

    1x

    1776x

    1776x

    20146x

    20189x
    1080x

    1080x

    19109x
    19090x
    607x

    18483x
    18483x

    18483x
    18483x

    18483x

    18483x

    1080x
    1037x

     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 { IOptions } from '../../interfaces/options/IOptions';
    import { IObfuscatorReplacer } from '../../interfaces/node-transformers/IObfuscatorReplacer';

    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 {IObfuscatorReplacer}
         */
        private readonly stringLiteralReplacer: IObfuscatorReplacer;

        /**
         * @param replacersFactory
         * @param options
         */
        constructor(
            @inject(ServiceIdentifiers['Factory<IObfuscatorReplacer>']) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscatorReplacer,
            @inject(ServiceIdentifiers.IOptions) options: IOptions
        ) {
            super(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
                };
            }
        }
    }