Explorar o código

Improved `rotateStringArray` option WIP

sanex %!s(int64=4) %!d(string=hai) anos
pai
achega
efac711ce4
Modificáronse 24 ficheiros con 539 adicións e 266 borrados
  1. 1 0
      CHANGELOG.md
  2. 0 1
      dist/index.cli.js
  3. 0 1
      dist/index.js
  4. 1 0
      src/JavaScriptObfuscator.ts
  5. 5 0
      src/container/modules/node-transformers/StringArrayTransformersModule.ts
  6. 1 0
      src/custom-code-helpers/string-array/StringArrayCallsWrapperBase64CodeHelper.ts
  7. 1 0
      src/custom-code-helpers/string-array/StringArrayCallsWrapperRc4CodeHelper.ts
  8. 21 40
      src/custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper.ts
  9. 0 23
      src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts
  10. 2 1
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate.ts
  11. 3 2
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate.ts
  12. 0 81
      src/custom-code-helpers/string-array/templates/string-array-rotate-function/SelfDefendingTemplate.ts
  13. 16 7
      src/custom-code-helpers/string-array/templates/string-array-rotate-function/StringArrayRotateFunctionTemplate.ts
  14. 1 0
      src/enums/node-transformers/NodeTransformer.ts
  15. 14 85
      src/node-transformers/converting-transformers/NumberToNumericalExpressionTransformer.ts
  16. 205 0
      src/node-transformers/string-array-transformers/StringArrayRotateFunctionTransformer.ts
  17. 8 0
      src/node-transformers/string-array-transformers/StringArrayScopeCallsWrapperTransformer.ts
  18. 11 1
      src/node-transformers/string-array-transformers/StringArrayTransformer.ts
  19. 37 0
      src/node/NodeFactory.ts
  20. 131 0
      src/node/NumericalExpressionDataToNodeConverter.ts
  21. 1 1
      src/options/Options.ts
  22. 6 0
      src/types/node/TNumericalExpressionDataToNodeConverterLiteralNodeGetter.ts
  23. 68 5
      test/dev/dev.ts
  24. 6 18
      test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

+ 1 - 0
CHANGELOG.md

@@ -2,6 +2,7 @@ Change Log
 
 v2.10.0
 ---
+* `splitStringsChunkLength` minimum value is `3` now
 * Some internal refactoring related to node append events
 
 v2.9.4

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 1
dist/index.cli.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 1
dist/index.js


+ 1 - 0
src/JavaScriptObfuscator.ts

@@ -88,6 +88,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
         NodeTransformer.ParentificationTransformer,
         NodeTransformer.ScopeIdentifiersTransformer,
         NodeTransformer.SplitStringTransformer,
+        NodeTransformer.StringArrayRotateFunctionTransformer,
         NodeTransformer.StringArrayScopeCallsWrapperTransformer,
         NodeTransformer.StringArrayTransformer,
         NodeTransformer.TemplateLiteralTransformer,

+ 5 - 0
src/container/modules/node-transformers/StringArrayTransformersModule.ts

@@ -5,11 +5,16 @@ import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTra
 
 import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
 
+import { StringArrayRotateFunctionTransformer } from '../../../node-transformers/string-array-transformers/StringArrayRotateFunctionTransformer';
 import { StringArrayScopeCallsWrapperTransformer } from '../../../node-transformers/string-array-transformers/StringArrayScopeCallsWrapperTransformer';
 import { StringArrayTransformer } from '../../../node-transformers/string-array-transformers/StringArrayTransformer';
 
 export const stringArrayTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // strings transformers
+    bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
+        .to(StringArrayRotateFunctionTransformer)
+        .whenTargetNamed(NodeTransformer.StringArrayRotateFunctionTransformer);
+
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
         .to(StringArrayScopeCallsWrapperTransformer)
         .whenTargetNamed(NodeTransformer.StringArrayScopeCallsWrapperTransformer);

+ 1 - 0
src/custom-code-helpers/string-array/StringArrayCallsWrapperBase64CodeHelper.ts

@@ -25,6 +25,7 @@ export class StringArrayCallsWrapperBase64CodeHelper extends StringArrayCallsWra
                 atobPolyfill,
                 atobFunctionName,
                 selfDefendingCode,
+                stringArrayName: this.stringArrayName,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
             }
         );

+ 1 - 0
src/custom-code-helpers/string-array/StringArrayCallsWrapperRc4CodeHelper.ts

@@ -29,6 +29,7 @@ export class StringArrayCallsWrapperRc4CodeHelper extends StringArrayCallsWrappe
                 atobPolyfill,
                 rc4Polyfill,
                 selfDefendingCode,
+                stringArrayName: this.stringArrayName,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
             }
         );

+ 21 - 40
src/custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper.ts

@@ -1,3 +1,4 @@
+import type { Expression } from 'estree';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
@@ -6,37 +7,35 @@ import { TStatement } from '../../types/node/TStatement';
 
 import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
-import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { SelfDefendingTemplate } from './templates/string-array-rotate-function/SelfDefendingTemplate';
 import { StringArrayRotateFunctionTemplate } from './templates/string-array-rotate-function/StringArrayRotateFunctionTemplate';
 
 import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
-import { NumberUtils } from '../../utils/NumberUtils';
 
 @injectable()
 export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelper {
     /**
-     * @type {string}
+     * @type {number}
      */
     @initializable()
-    private stringArrayName!: string;
+    private comparisonValue!: number;
 
     /**
-     * @param {number}
+     * @type {Expression}
      */
     @initializable()
-    private stringArrayRotationAmount!: number;
+    private comparisonExpressionNode!: Expression;
 
     /**
-     * @type {IEscapeSequenceEncoder}
+     * @type {string}
      */
-    private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
+    @initializable()
+    private stringArrayName!: string;
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -44,7 +43,6 @@ export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelpe
      * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
-     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
@@ -52,8 +50,7 @@ export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelpe
         @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions,
-        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(
             identifierNamesGeneratorFactory,
@@ -62,20 +59,21 @@ export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelpe
             randomGenerator,
             options
         );
-
-        this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
 
     /**
      * @param {string} stringArrayName
-     * @param {number} stringArrayRotationAmount
+     * @param {number} comparisonValue
+     * @param {Expression} comparisonExpressionNode
      */
     public initialize (
         stringArrayName: string,
-        stringArrayRotationAmount: number
+        comparisonValue: number,
+        comparisonExpressionNode: Expression
     ): void {
         this.stringArrayName = stringArrayName;
-        this.stringArrayRotationAmount = stringArrayRotationAmount;
+        this.comparisonValue = comparisonValue;
+        this.comparisonExpressionNode = comparisonExpressionNode;
     }
 
     /**
@@ -90,31 +88,14 @@ export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelpe
      * @returns {string}
      */
     protected getCodeHelperTemplate (): string {
-        const timesName: string = this.identifierNamesGenerator.generateNext();
-        const whileFunctionName: string = this.identifierNamesGenerator.generateNext();
-        const preservedNames: string[] = [`^${this.stringArrayName}$`];
-
-        let code: string = '';
-
-        if (this.options.selfDefending) {
-            code = this.customCodeHelperFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
-                timesName,
-                whileFunctionName
-            });
-        } else {
-            code = `${whileFunctionName}(++${timesName})`;
-        }
+        const comparisonExpressionCode: string = NodeUtils.convertStructureToCode([this.comparisonExpressionNode]);
 
-        return this.customCodeHelperObfuscator.obfuscateTemplate(
-            this.customCodeHelperFormatter.formatTemplate(StringArrayRotateFunctionTemplate(), {
-                code,
-                timesName,
-                whileFunctionName,
-                stringArrayName: this.stringArrayName,
-                stringArrayRotationAmount: NumberUtils.toHex(this.stringArrayRotationAmount)
-            }),
+        return this.customCodeHelperFormatter.formatTemplate(
+            StringArrayRotateFunctionTemplate(),
             {
-                reservedNames: preservedNames
+                comparisonExpressionCode,
+                comparisonValue: this.comparisonValue,
+                stringArrayName: this.stringArrayName
             }
         );
     }

+ 0 - 23
src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts

@@ -22,7 +22,6 @@ import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGro
 import { NodeAppender } from '../../../node/NodeAppender';
 import { StringArrayCallsWrapperCodeHelper } from '../StringArrayCallsWrapperCodeHelper';
 import { StringArrayCodeHelper } from '../StringArrayCodeHelper';
-import { StringArrayRotateFunctionCodeHelper } from '../StringArrayRotateFunctionCodeHelper';
 
 @injectable()
 export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
@@ -102,14 +101,6 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
                 }
             );
         }
-
-        // stringArrayRotateFunction helper nodes append
-        this.appendCustomNodeIfExist(
-            CustomCodeHelper.StringArrayRotateFunction,
-            (customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>>) => {
-                NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), 1);
-            }
-        );
     }
 
     public initialize (): void {
@@ -133,7 +124,6 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
             const stringArrayCallsWrapperCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>> =
                 this.customCodeHelperFactory(stringArrayCallsWrapperCodeHelperName);
             const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName(stringArrayEncoding);
-
             stringArrayCallsWrapperCodeHelper.initialize(
                 stringArrayName,
                 stringArrayCallsWrapperName,
@@ -142,19 +132,6 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
 
             this.customCodeHelpers.set(stringArrayCallsWrapperCodeHelperName, stringArrayCallsWrapperCodeHelper);
         }
-
-        // stringArrayRotateFunction helper initialize
-        const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
-            this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
-
-        stringArrayRotateFunctionCodeHelper.initialize(
-            stringArrayName,
-            this.stringArrayStorage.getRotationAmount()
-        );
-
-        if (this.options.rotateStringArray) {
-            this.customCodeHelpers.set(CustomCodeHelper.StringArrayRotateFunction, stringArrayRotateFunctionCodeHelper);
-        }
     }
 
     /**

+ 2 - 1
src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate.ts

@@ -33,9 +33,10 @@ export function StringArrayBase64DecodeTemplate (
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
                   
+        const ignoreCache = {stringArrayName}[-1];
         const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
                         
-        if (cachedValue === undefined) {
+        if (ignoreCache || cachedValue === undefined) {
             {selfDefendingCode}
             
             value = {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier}(value);

+ 3 - 2
src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate.ts

@@ -13,7 +13,7 @@ export function StringArrayRC4DecodeTemplate (
     const rc4Identifier: string = randomGenerator.getRandomString(identifierLength);
     const dataIdentifier: string = randomGenerator.getRandomString(identifierLength);
     const onceIdentifier: string = randomGenerator.getRandomString(identifierLength);
-  
+
     return `
         if ({stringArrayCallsWrapperName}.${initializedIdentifier} === undefined) {
             {atobPolyfill}
@@ -26,9 +26,10 @@ export function StringArrayRC4DecodeTemplate (
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
   
+        const ignoreCache = {stringArrayName}[-1];
         const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
 
-        if (cachedValue === undefined) {
+        if (ignoreCache || cachedValue === undefined) {
             if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
                 {selfDefendingCode}
                 

+ 0 - 81
src/custom-code-helpers/string-array/templates/string-array-rotate-function/SelfDefendingTemplate.ts

@@ -1,81 +0,0 @@
-import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
-
-/**
- * SelfDefendingTemplate. Enter code in infinity loop.
- *
- * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
- * @returns {string}
- */
-export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
-    return `
-        const selfDefendingFunc = function () {
-            const object = {
-                data: {
-                    key: 'cookie',
-                    value: 'timeout'
-                },
-                setCookie: function (options, name, value, document) {
-                    document = document || {};
-                    
-                    let updatedCookie = name + "=" + value;
-                    let i = 0;
-                                                            
-                    for (let i = 0, len = options.length; i < len; i++) {
-                        const propName = options[i];
-                                     
-                        updatedCookie += "; " + propName;
-                        
-                        const propValue = options[propName];
-                        
-                        options.push(propValue);
-                        len = options.length;
-                                                                        
-                        if (propValue !== true) {
-                            updatedCookie += "=" + propValue;
-                        }
-                    }
-
-                    document['cookie'] = updatedCookie;
-                },
-                removeCookie: function(){return 'dev';},
-                getCookie: function (document, name) {
-                    document = document || function (value) { return value };
-                    const matches = document(new RegExp(
-                        "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
-                    ));
-                    
-                    const func = function (param1, param2) {
-                        param1(++param2);
-                    };
-                    
-                    func({whileFunctionName}, {timesName});
-                                        
-                    return matches ? decodeURIComponent(matches[1]) : undefined;
-                }
-            };
-            
-            const test1 = function () {
-                const regExp = new RegExp('${
-                    escapeSequenceEncoder.encode('\\w+ *\\(\\) *{\\w+ *[\'|"].+[\'|"];? *}', true)
-                }');
-                
-                return regExp.test(object.removeCookie.toString());
-            };
-            
-            object['updateCookie'] = test1;
-            
-            let cookie = '';
-            const result = object['updateCookie']();
-                                    
-            if (!result) {
-                object['setCookie'](['*'], 'counter', 1);
-            } else if (result) {
-                cookie = object['getCookie'](null, 'counter');
-            } else {
-                object['removeCookie']();
-            }
-        };
-        
-        selfDefendingFunc();
-    `;
-}

+ 16 - 7
src/custom-code-helpers/string-array/templates/string-array-rotate-function/StringArrayRotateFunctionTemplate.ts

@@ -3,14 +3,23 @@
  */
 export function StringArrayRotateFunctionTemplate (): string {
     return `
-        (function (array, {timesName}) {
-            const {whileFunctionName} = function (times) {
-                while (--times) {
+        (function (array, comparisonValue) {
+            array[-1] = true;
+
+            while (true) {
+                try {
+                    const expression = {comparisonExpressionCode};
+                                            
+                    if (expression === comparisonValue) {
+                        array[-1] = false;
+                        break;
+                    } else {
+                        array['push'](array['shift']());
+                    }
+                } catch (e) {
                     array['push'](array['shift']());
                 }
-            };
-            
-            {code}
-        })({stringArrayName}, {stringArrayRotationAmount});
+            }
+        })({stringArrayName}, {comparisonValue});
     `;
 }

+ 1 - 0
src/enums/node-transformers/NodeTransformer.ts

@@ -27,6 +27,7 @@ export enum NodeTransformer {
     ScopeThroughIdentifiersTransformer = 'ScopeThroughIdentifiersTransformer',
     SplitStringTransformer = 'SplitStringTransformer',
     StringArrayTransformer = 'StringArrayTransformer',
+    StringArrayRotateFunctionTransformer = 'StringArrayRotateFunctionTransformer',
     StringArrayScopeCallsWrapperTransformer = 'StringArrayScopeCallsWrapperTransformer',
     TemplateLiteralTransformer = 'TemplateLiteralTransformer',
     VariableDeclarationsMergeTransformer = 'VariableDeclarationsMergeTransformer',

+ 14 - 85
src/node-transformers/converting-transformers/NumberToNumericalExpressionTransformer.ts

@@ -15,7 +15,7 @@ import { NodeTransformationStage } from '../../enums/node-transformers/NodeTrans
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeFactory } from '../../node/NodeFactory';
-import { NumberUtils } from '../../utils/NumberUtils';
+import { NumericalExpressionDataToNodeConverter } from '../../node/NumericalExpressionDataToNodeConverter';
 
 /**
  * replaces:
@@ -87,89 +87,18 @@ export class NumberToNumericalExpressionTransformer extends AbstractNodeTransfor
 
         const numberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer.analyze(literalNode.value);
 
-        return this.convertNumericalExpressionDataToNode(numberNumericalExpressionData);
-    }
-
-    /**
-     * @param {TNumberNumericalExpressionData} numberNumericalExpressionData
-     * @param {ESTree.BinaryOperator} operator
-     * @returns {ESTree.BinaryExpression | ESTree.Literal | ESTree.UnaryExpression}
-     */
-    private convertNumericalExpressionDataToNode (
-        numberNumericalExpressionData: TNumberNumericalExpressionData,
-        operator: ESTree.BinaryOperator = '+'
-    ): ESTree.BinaryExpression | ESTree.Literal | ESTree.UnaryExpression {
-        const numberNumericalExpressionDataLength: number = numberNumericalExpressionData.length;
-
-        const leftParts: TNumberNumericalExpressionData = numberNumericalExpressionDataLength > 1
-            ? numberNumericalExpressionData.slice(0, numberNumericalExpressionDataLength - 1)
-            : [numberNumericalExpressionData[0]];
-        const rightParts: TNumberNumericalExpressionData = numberNumericalExpressionDataLength > 1
-            ? numberNumericalExpressionData.slice(-1)
-            : [];
-
-        // trailing iterations
-        if (rightParts.length) {
-            return this.convertPartsToBinaryExpression(operator, leftParts, rightParts);
-        }
-
-        const firstLeftPartOrNumber: number | number[] | null = leftParts[0] ?? null;
-
-        // last iteration when only single left part is left
-        return Array.isArray(firstLeftPartOrNumber)
-            ? this.convertNumericalExpressionDataToNode(firstLeftPartOrNumber, '*')
-            : this.convertPartOrNumberToLiteralNode(firstLeftPartOrNumber);
-    }
-
-    /**
-     * @param {ESTree.BinaryOperator} operator
-     * @param {TNumberNumericalExpressionData} leftParts
-     * @param {TNumberNumericalExpressionData} rightParts
-     * @returns {ESTree.BinaryExpression}
-     */
-    private convertPartsToBinaryExpression (
-        operator: ESTree.BinaryOperator,
-        leftParts: TNumberNumericalExpressionData,
-        rightParts: TNumberNumericalExpressionData
-    ): ESTree.BinaryExpression {
-        const rightPartOrNumber: number | number[] = rightParts[0];
-
-        if (Array.isArray(rightPartOrNumber)) {
-            // right part is array with multiply numbers
-            return NodeFactory.binaryExpressionNode(
-                operator,
-                this.convertNumericalExpressionDataToNode(leftParts),
-                this.convertNumericalExpressionDataToNode(rightPartOrNumber, '*')
-            );
-        } else {
-            // right part is number
-            return NodeFactory.binaryExpressionNode(
-                operator,
-                this.convertNumericalExpressionDataToNode(leftParts),
-                this.convertPartOrNumberToLiteralNode(rightPartOrNumber)
-            );
-        }
-    }
-
-    /**
-     * @param {number | number[]} partOrNumber
-     * @returns {ESTree.Literal}
-     */
-    private convertPartOrNumberToLiteralNode (
-        partOrNumber: number | number[]
-    ): ESTree.Literal | ESTree.UnaryExpression {
-        const number: number = Array.isArray(partOrNumber)
-            ? partOrNumber[0]
-            : partOrNumber;
-        const isPositiveNumber: boolean = NumberUtils.isPositive(number);
-
-        const literalNode: ESTree.Literal = NodeFactory.literalNode(Math.abs(number));
-
-        return isPositiveNumber
-            ? literalNode
-            : NodeFactory.unaryExpressionNode(
-                '-',
-                literalNode
-            );
+        return NumericalExpressionDataToNodeConverter.convert(
+            numberNumericalExpressionData,
+            (number: number, isPositiveNumber: boolean) => {
+                const numberLiteralNode: ESTree.Literal = NodeFactory.literalNode(number);
+
+                return isPositiveNumber
+                    ? numberLiteralNode
+                    : NodeFactory.unaryExpressionNode(
+                        '-',
+                        numberLiteralNode
+                    );
+            }
+        );
     }
 }

+ 205 - 0
src/node-transformers/string-array-transformers/StringArrayRotateFunctionTransformer.ts

@@ -0,0 +1,205 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+import { TCustomCodeHelperFactory } from '../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TInitialData } from '../../types/TInitialData';
+import { TNumberNumericalExpressionData } from '../../types/analyzers/number-numerical-expression-analyzer/TNumberNumericalExpressionData';
+import { TStatement } from '../../types/node/TStatement';
+
+import { ICustomCodeHelper } from '../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { INodeTransformersRunner } from '../../interfaces/node-transformers/INodeTransformersRunner';
+import { INumberNumericalExpressionAnalyzer } from '../../interfaces/analyzers/number-numerical-expression-analyzer/INumberNumericalExpressionAnalyzer';
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IStringArrayStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayStorage';
+import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
+
+import { CustomCodeHelper } from '../../enums/custom-code-helpers/CustomCodeHelper';
+import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
+
+import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeAppender } from '../../node/NodeAppender';
+import { NodeGuards } from '../../node/NodeGuards';
+import { NodeFactory } from '../../node/NodeFactory';
+import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
+import { NodeMetadata } from '../../node/NodeMetadata';
+import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
+import { NodeUtils } from '../../node/NodeUtils';
+import { NumericalExpressionDataToNodeConverter } from '../../node/NumericalExpressionDataToNodeConverter';
+import { StringArrayRotateFunctionCodeHelper } from '../../custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper';
+
+@injectable()
+export class StringArrayRotateFunctionTransformer extends AbstractNodeTransformer {
+    /**
+     * @type {NodeTransformer[]}
+     */
+    private static readonly stringArrayRotateFunctionTransformers: NodeTransformer[] = [
+        NodeTransformer.BooleanLiteralTransformer,
+        NodeTransformer.MemberExpressionTransformer,
+        NodeTransformer.NumberLiteralTransformer,
+        NodeTransformer.NumberToNumericalExpressionTransformer,
+        NodeTransformer.ParentificationTransformer,
+        NodeTransformer.ScopeIdentifiersTransformer
+    ];
+
+    /**
+     * @type {INumberNumericalExpressionAnalyzer}
+     */
+    private readonly numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer;
+
+    /**
+     * @type {IStringArrayStorage}
+     */
+    private readonly stringArrayStorage: IStringArrayStorage;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @type {INodeTransformersRunner}
+     */
+    private readonly transformersRunner: INodeTransformersRunner;
+
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     * @param {INodeTransformersRunner} transformersRunner
+     * @param {IStringArrayStorage} stringArrayStorage
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {INumberNumericalExpressionAnalyzer} numberNumericalExpressionAnalyzer
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.INodeTransformersRunner) transformersRunner: INodeTransformersRunner,
+        @inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.INumberNumericalExpressionAnalyzer)
+            numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer
+    ) {
+        super(randomGenerator, options);
+
+        this.stringArrayStorage = stringArrayStorage;
+        this.transformersRunner = transformersRunner;
+        this.customCodeHelperFactory = customCodeHelperFactory;
+        this.numberNumericalExpressionAnalyzer = numberNumericalExpressionAnalyzer;
+    }
+
+    /**
+     * @param {NodeTransformationStage} nodeTransformationStage
+     * @returns {IVisitor | null}
+     */
+    public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
+        if (!this.options.rotateStringArray) {
+            return null;
+        }
+
+        switch (nodeTransformationStage) {
+            case NodeTransformationStage.StringArray:
+                return {
+                    enter: (node: ESTree.Node): ESTree.Node | undefined => {
+                        if (NodeGuards.isProgramNode(node)) {
+                            this.transformNode(node);
+                        }
+
+                        return node;
+                    }
+                };
+
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @param {Program} programNode
+     * @returns {Node}
+     */
+    public transformNode (programNode: ESTree.Program): ESTree.Node {
+        const stringArrayRotateFunctionNode: TStatement = this.getStringArrayRotateFunctionNode();
+        const wrappedStringArrayRotateFunctionNode: ESTree.Program = NodeFactory.programNode([
+            stringArrayRotateFunctionNode
+        ]);
+
+        NodeUtils.parentizeAst(wrappedStringArrayRotateFunctionNode);
+
+        const transformationStages: NodeTransformationStage[] = [
+            NodeTransformationStage.Preparing,
+            NodeTransformationStage.Converting,
+            NodeTransformationStage.RenameIdentifiers,
+            NodeTransformationStage.Finalizing
+        ];
+
+        // custom transformation of string array rotate function node
+        for (const transformationStage of transformationStages) {
+            this.transformersRunner.transform(
+                wrappedStringArrayRotateFunctionNode,
+                StringArrayRotateFunctionTransformer.stringArrayRotateFunctionTransformers,
+                transformationStage
+            );
+        }
+
+        // mark all child nodes (except literals inside comparison expression)
+        // as ignored to prevent additional transformation of these nodes
+        estraverse.traverse(wrappedStringArrayRotateFunctionNode, {
+            enter: (node: ESTree.Node): void => {
+                if (
+                    NodeGuards.isLiteralNode(node)
+                    && NodeLiteralUtils.isStringLiteralNode(node)
+                    && !/\d/.test(node.value)
+                ) {
+                    NodeMetadata.set(node, {ignoredNode: true});
+                }
+            }
+        });
+
+        NodeAppender.prepend(programNode, [stringArrayRotateFunctionNode]);
+        NodeUtils.parentizeNode(stringArrayRotateFunctionNode, programNode);
+
+        return programNode;
+    }
+
+    /**
+     * @returns {TStatement}
+     */
+    private getStringArrayRotateFunctionNode (): TStatement {
+        const comparisonValue: number = this.randomGenerator.getRandomInteger(100000, 1_000_000);
+        const comparisonExpressionNumberNumericalExpressionData: TNumberNumericalExpressionData =
+            this.numberNumericalExpressionAnalyzer.analyze(comparisonValue);
+
+        const comparisonExpressionNode: ESTree.Expression = NumericalExpressionDataToNodeConverter.convert(
+            comparisonExpressionNumberNumericalExpressionData,
+            ((number: number, isPositiveNumber) => {
+                const literalNode: ESTree.Literal = NodeFactory.literalNode(number.toString());
+
+                return NodeFactory.callExpressionNode(
+                    NodeFactory.identifierNode('parseInt'),
+                    [
+                        isPositiveNumber
+                            ? literalNode
+                            : NodeFactory.unaryExpressionNode(
+                                '-',
+                                literalNode
+                            )
+                    ]
+                );
+            })
+        );
+
+        const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
+
+        stringArrayRotateFunctionCodeHelper.initialize(
+            this.stringArrayStorage.getStorageName(),
+            comparisonValue,
+            comparisonExpressionNode
+        );
+
+        return stringArrayRotateFunctionCodeHelper.getNode()[0];
+    }
+}

+ 8 - 0
src/node-transformers/string-array-transformers/StringArrayScopeCallsWrapperTransformer.ts

@@ -22,6 +22,7 @@ import { IStringArrayStorage } from '../../interfaces/storages/string-array-tran
 import { IVisitedLexicalScopeNodesStackStorage } from '../../interfaces/storages/string-array-transformers/IVisitedLexicalScopeNodesStackStorage';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
 import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
 import { StringArrayCustomNode } from '../../enums/custom-nodes/StringArrayCustomNode';
 import { StringArrayWrappersType } from '../../enums/node-transformers/string-array-transformers/StringArrayWrappersType';
@@ -34,6 +35,13 @@ import { StringArrayScopeCallsWrapperVariableNode } from '../../custom-nodes/str
 
 @injectable()
 export class StringArrayScopeCallsWrapperTransformer extends AbstractNodeTransformer {
+    /**
+     * @type {NodeTransformer[]}
+     */
+    public readonly runAfter: NodeTransformer[] = [
+        NodeTransformer.StringArrayRotateFunctionTransformer
+    ];
+
     /**
      * @type {IStringArrayStorage}
      */

+ 11 - 1
src/node-transformers/string-array-transformers/StringArrayTransformer.ts

@@ -26,6 +26,7 @@ import { IStringArrayStorageItemData } from '../../interfaces/storages/string-ar
 import { IVisitedLexicalScopeNodesStackStorage } from '../../interfaces/storages/string-array-transformers/IVisitedLexicalScopeNodesStackStorage';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
 import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
 import { StringArrayCustomNode } from '../../enums/custom-nodes/StringArrayCustomNode';
 import { StringArrayWrappersType } from '../../enums/node-transformers/string-array-transformers/StringArrayWrappersType';
@@ -49,6 +50,13 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
      */
     private static readonly maxShiftedIndexValue: number = 1000;
 
+    /**
+     * @type {NodeTransformer[]}
+     */
+    public readonly runAfter: NodeTransformer[] = [
+        NodeTransformer.StringArrayRotateFunctionTransformer
+    ];
+
 
     /**
      * @type {IIdentifierNamesGenerator}
@@ -158,7 +166,9 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
      * @param {Program} programNode
      */
     public prepareNode (programNode: ESTree.Program): void {
-        this.stringArrayStorageAnalyzer.analyze(programNode);
+        if (this.options.stringArray) {
+            this.stringArrayStorageAnalyzer.analyze(programNode);
+        }
 
         if (this.options.shuffleStringArray) {
             this.stringArrayStorage.shuffleStorage();

+ 37 - 0
src/node/NodeFactory.ts

@@ -137,6 +137,23 @@ export class NodeFactory {
         };
     }
 
+    /**
+     * @param {Pattern | null} param
+     * @param {BlockStatement} body
+     * @returns {CatchClause}
+     */
+    public static catchClauseNode (
+        param: ESTree.Pattern | null,
+        body: ESTree.BlockStatement
+    ): ESTree.CatchClause {
+        return {
+            type: NodeType.CatchClause,
+            param,
+            body,
+            metadata: { ignoredNode: false }
+        };
+    }
+
     /**
      * @param {ESTree.Expression} test
      * @param {ESTree.Expression} consequent
@@ -539,6 +556,26 @@ export class NodeFactory {
         };
     }
 
+    /**
+     * @param {BlockStatement} block
+     * @param {CatchClause | null} handler
+     * @param {BlockStatement | null} finalizer
+     * @returns {TryStatement}
+     */
+    public static tryStatement (
+        block: ESTree.BlockStatement,
+        handler?: ESTree.CatchClause | null,
+        finalizer?: ESTree.BlockStatement | null
+    ): ESTree.TryStatement {
+        return {
+            type: NodeType.TryStatement,
+            block,
+            handler,
+            finalizer,
+            metadata: { ignoredNode: false }
+        };
+    }
+
     /**
      * @param {VariableDeclarator[]} declarations
      * @param {string} kind

+ 131 - 0
src/node/NumericalExpressionDataToNodeConverter.ts

@@ -0,0 +1,131 @@
+import * as ESTree from 'estree';
+
+import { TNumericalExpressionDataToNodeConverterLiteralNodeGetter } from '../types/node/TNumericalExpressionDataToNodeConverterLiteralNodeGetter';
+import { TNumberNumericalExpressionData } from '../types/analyzers/number-numerical-expression-analyzer/TNumberNumericalExpressionData';
+
+import { NodeFactory } from './NodeFactory';
+import { NumberUtils } from '../utils/NumberUtils';
+
+/**
+ * Converts NumberNumericalExpressionData to node
+ */
+export class NumericalExpressionDataToNodeConverter {
+    /**
+     * @param {TNumberNumericalExpressionData} numberNumericalExpressionData
+     * @param {TNumericalExpressionDataToNodeConverterLiteralNodeGetter} literalNodeGetter
+     * @returns {Expression}
+     */
+    public static convert (
+        numberNumericalExpressionData: TNumberNumericalExpressionData,
+        literalNodeGetter: TNumericalExpressionDataToNodeConverterLiteralNodeGetter
+    ): ESTree.Expression {
+       return NumericalExpressionDataToNodeConverter.convertNumericalExpressionDataToNode(
+           numberNumericalExpressionData,
+           literalNodeGetter
+       );
+    }
+
+    /**
+     * @param {TNumberNumericalExpressionData} numberNumericalExpressionData
+     * @param {TNumericalExpressionDataToNodeConverterLiteralNodeGetter} literalNodeGetter
+     * @param {BinaryOperator} operator
+     * @returns {Expression}
+     */
+    private static convertNumericalExpressionDataToNode (
+        numberNumericalExpressionData: TNumberNumericalExpressionData,
+        literalNodeGetter: TNumericalExpressionDataToNodeConverterLiteralNodeGetter,
+        operator: ESTree.BinaryOperator = '+'
+    ): ESTree.Expression {
+        const numberNumericalExpressionDataLength: number = numberNumericalExpressionData.length;
+
+        const leftParts: TNumberNumericalExpressionData = numberNumericalExpressionDataLength > 1
+            ? numberNumericalExpressionData.slice(0, numberNumericalExpressionDataLength - 1)
+            : [numberNumericalExpressionData[0]];
+        const rightParts: TNumberNumericalExpressionData = numberNumericalExpressionDataLength > 1
+            ? numberNumericalExpressionData.slice(-1)
+            : [];
+
+        // trailing iterations
+        if (rightParts.length) {
+            return NumericalExpressionDataToNodeConverter
+                .convertPartsToBinaryExpression(operator, leftParts, rightParts, literalNodeGetter);
+        }
+
+        const firstLeftPartOrNumber: number | number[] | null = leftParts[0] ?? null;
+
+        // last iteration when only single left part is left
+        return Array.isArray(firstLeftPartOrNumber)
+            ? NumericalExpressionDataToNodeConverter.convertNumericalExpressionDataToNode(
+                firstLeftPartOrNumber,
+                literalNodeGetter,
+                '*'
+            )
+            : NumericalExpressionDataToNodeConverter.convertPartOrNumberToLiteralNode(
+                firstLeftPartOrNumber,
+                literalNodeGetter
+            );
+    }
+
+    /**
+     * @param {BinaryOperator} operator
+     * @param {TNumberNumericalExpressionData} leftParts
+     * @param {TNumberNumericalExpressionData} rightParts
+     * @param {TNumericalExpressionDataToNodeConverterLiteralNodeGetter} literalNodeGetter
+     * @returns {BinaryExpression}
+     */
+    private static convertPartsToBinaryExpression (
+        operator: ESTree.BinaryOperator,
+        leftParts: TNumberNumericalExpressionData,
+        rightParts: TNumberNumericalExpressionData,
+        literalNodeGetter: TNumericalExpressionDataToNodeConverterLiteralNodeGetter
+    ): ESTree.BinaryExpression {
+        const rightPartOrNumber: number | number[] = rightParts[0];
+
+        if (Array.isArray(rightPartOrNumber)) {
+            // right part is array with multiply numbers
+            return NodeFactory.binaryExpressionNode(
+                operator,
+                NumericalExpressionDataToNodeConverter.convertNumericalExpressionDataToNode(
+                    leftParts,
+                    literalNodeGetter
+                ),
+                NumericalExpressionDataToNodeConverter.convertNumericalExpressionDataToNode(
+                    rightPartOrNumber,
+                    literalNodeGetter,
+                    '*'
+                )
+            );
+        } else {
+            // right part is number
+            return NodeFactory.binaryExpressionNode(
+                operator,
+                NumericalExpressionDataToNodeConverter.convertNumericalExpressionDataToNode(
+                    leftParts,
+                    literalNodeGetter
+                ),
+                this.convertPartOrNumberToLiteralNode(
+                    rightPartOrNumber,
+                    literalNodeGetter
+                )
+            );
+        }
+    }
+
+    /**
+     * @param {number | number[]} partOrNumber
+     * @param {TNumericalExpressionDataToNodeConverterLiteralNodeGetter} literalNodeGetter
+     * @returns {Expression}
+     */
+    private static convertPartOrNumberToLiteralNode (
+        partOrNumber: number | number[],
+        literalNodeGetter: TNumericalExpressionDataToNodeConverterLiteralNodeGetter
+    ): ESTree.Expression {
+        const number: number = Array.isArray(partOrNumber)
+            ? partOrNumber[0]
+            : partOrNumber;
+        const isPositiveNumber: boolean = NumberUtils.isPositive(number);
+        const absoluteNumber: number = Math.abs(number);
+
+        return literalNodeGetter(absoluteNumber, isPositiveNumber);
+    }
+}

+ 1 - 1
src/options/Options.ts

@@ -299,7 +299,7 @@ export class Options implements IOptions {
      */
     @IsNumber()
     @ValidateIf((options: IOptions) => Boolean(options.splitStrings))
-    @Min(1)
+    @Min(3)
     public readonly splitStringsChunkLength!: number;
 
     /**

+ 6 - 0
src/types/node/TNumericalExpressionDataToNodeConverterLiteralNodeGetter.ts

@@ -0,0 +1,6 @@
+import * as ESTree from 'estree';
+
+export type TNumericalExpressionDataToNodeConverterLiteralNodeGetter = (
+    number: number,
+    isPositiveNumber: boolean
+) => ESTree.Expression;

+ 68 - 5
test/dev/dev.ts

@@ -1,23 +1,86 @@
 'use strict';
 
 import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
+import { StringArrayEncoding } from '../../src/enums/node-transformers/string-array-transformers/StringArrayEncoding';
+import { StringArrayIndexesType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayIndexesType';
+import { StringArrayWrappersType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayWrappersType';
 
 (function () {
     const JavaScriptObfuscator: any = require('../../index');
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
-            function hi() {
-              console.log("Hello World!");
-            }
-            hi();
+            (function(){
+                var variable1 = '5' - 3;
+                var variable2 = '5' + 3;
+                var variable3 = '5' + - '2';
+                var variable4 = ['10','10','10','10','10'].map(parseInt);
+                var variable5 = 'foo ' + 1 + 1;
+                console.log(variable1);
+                console.log(variable2);
+                console.log(variable3);
+                console.log(variable4);
+                console.log(variable5);
+            })();
+            
+            (function(){
+                if (true) {
+                    var foo = function () {
+                        console.log('abc');
+                        console.log('cde');
+                        console.log('efg');
+                        console.log('hij');
+                    };
+                    
+                    var bar = function () {
+                        console.log('klm');
+                        console.log('nop');
+                        console.log('qrs');
+                    };
+                
+                    var baz = function () {
+                        console.log('tuv');
+                        console.log('wxy');
+                        console.log('z');
+                    };
+                
+                    foo();
+                    bar();
+                    baz();
+                }
+            })();
         `,
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             compact: false,
+            controlFlowFlattening: true,
+            controlFlowFlatteningThreshold: 1,
+            deadCodeInjection: true,
+            deadCodeInjectionThreshold: 1,
+            numbersToExpressions: true,
+            simplify: true,
+            renameProperties: true,
+            rotateStringArray: true,
+            splitStrings: true,
+            splitStringsChunkLength: 3,
             stringArray: true,
+            stringArrayEncoding: [
+                StringArrayEncoding.None,
+                StringArrayEncoding.Base64,
+                StringArrayEncoding.Rc4
+            ],
+            stringArrayIndexesType: [
+                StringArrayIndexesType.HexadecimalNumber,
+                StringArrayIndexesType.HexadecimalNumericString
+            ],
+            stringArrayIndexShift: true,
+            stringArrayWrappersChainedCalls: true,
+            stringArrayWrappersCount: 5,
+            stringArrayWrappersParametersMaxCount: 5,
+            stringArrayWrappersType: StringArrayWrappersType.Function,
             stringArrayThreshold: 1,
-            rotateStringArray: true
+            transformObjectKeys: true,
+            unicodeEscapeSequence: true
         }
     ).getObfuscatedCode();
 

+ 6 - 18
test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

@@ -4,8 +4,6 @@ import { TInputOptions } from '../../src/types/options/TInputOptions';
 
 import { IdentifierNamesGenerator } from '../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
 import { StringArrayEncoding } from '../../src/enums/node-transformers/string-array-transformers/StringArrayEncoding';
-import { StringArrayIndexesType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayIndexesType';
-import { StringArrayWrappersType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayWrappersType';
 
 import { evaluateInWorker } from '../helpers/evaluateInWorker';
 import { readFileAsString } from '../helpers/readFileAsString';
@@ -20,38 +18,28 @@ const getEnvironmentCode = () => `
 
 describe('JavaScriptObfuscator runtime eval', function () {
     const baseOptions: TInputOptions = {
-        controlFlowFlattening: true,
-        controlFlowFlatteningThreshold: 1,
+        compact: false,
         deadCodeInjection: true,
         deadCodeInjectionThreshold: 1,
-        debugProtection: true,
-        disableConsoleOutput: true,
+        // debugProtection: true,
+        disableConsoleOutput: false,
         domainLock: ['obfuscator.io'],
         numbersToExpressions: true,
         simplify: true,
-        renameProperties: true,
         reservedNames: ['generate', 'sha256'],
-        rotateStringArray: true,
-        selfDefending: true,
+        rotateStringArray: false,
+        // selfDefending: true,
         splitStrings: true,
-        splitStringsChunkLength: 1,
+        splitStringsChunkLength: 3,
         stringArray: true,
         stringArrayEncoding: [
             StringArrayEncoding.None,
             StringArrayEncoding.Base64,
             StringArrayEncoding.Rc4
         ],
-        stringArrayIndexesType: [
-            StringArrayIndexesType.HexadecimalNumber,
-            StringArrayIndexesType.HexadecimalNumericString
-        ],
-        stringArrayIndexShift: true,
         stringArrayWrappersChainedCalls: true,
         stringArrayWrappersCount: 5,
-        stringArrayWrappersParametersMaxCount: 5,
-        stringArrayWrappersType: StringArrayWrappersType.Function,
         stringArrayThreshold: 1,
-        transformObjectKeys: true,
         unicodeEscapeSequence: true
     };
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio