Kaynağa Gözat

New option: `stringArrayIndexShift` enables additional index shift for all string array calls

sanex 4 yıl önce
ebeveyn
işleme
4f33c76da1

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 
+v2.9.0
+---
+* New option: `stringArrayIndexShift` enables additional index shift for all string array calls
+
 v2.8.1
 ---
 * Fixed incorrect rename of the identifiers of the added helpers in some rare cases. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/804

+ 13 - 0
README.md

@@ -365,6 +365,7 @@ Following options are available for the JS Obfuscator:
     splitStringsChunkLength: 10,
     stringArray: true,
     stringArrayEncoding: [],
+    stringArrayIndexShift: true,
     stringArrayWrappersCount: 1,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersType: 'variable',
@@ -418,6 +419,7 @@ Following options are available for the JS Obfuscator:
     --split-strings-chunk-length <number>
     --string-array <boolean>
     --string-array-encoding '<list>' (comma separated) [none, base64, rc4]
+    --string-array-index-shift <boolean>
     --string-array-wrappers-count <number>
     --string-array-wrappers-chained-calls <boolean>
     --string-array-wrappers-type <string> [variable, function]
@@ -987,6 +989,13 @@ stringArrayEncoding: [
 ]
 ```
 
+### `stringArrayIndexShift`
+Type: `boolean` Default: `true`
+
+##### :warning: `stringArray` option must be enabled
+
+Enables additional index shift for all string array calls
+
 ### `stringArrayWrappersCount`
 Type: `number` Default: `1`
 
@@ -1236,6 +1245,7 @@ Performance will 50-100% slower than without obfuscation
     splitStringsChunkLength: 5,
     stringArray: true,
     stringArrayEncoding: ['rc4'],
+    stringArrayIndexShift: true,
     stringArrayWrappersCount: 5,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersType: 'function',
@@ -1271,6 +1281,7 @@ Performance will 30-35% slower than without obfuscation
     splitStringsChunkLength: 10,
     stringArray: true,
     stringArrayEncoding: ['base64'],
+    stringArrayIndexShift: true,
     stringArrayWrappersCount: 2,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersType: 'variable',
@@ -1303,6 +1314,7 @@ Performance will slightly slower than without obfuscation
     splitStrings: false,
     stringArray: true,
     stringArrayEncoding: [],
+    stringArrayIndexShift: true,
     stringArrayWrappersCount: 1,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersType: 'variable',
@@ -1332,6 +1344,7 @@ Performance will slightly slower than without obfuscation
     splitStrings: false,
     stringArray: true,
     stringArrayEncoding: [],
+    stringArrayIndexShift: true,
     stringArrayWrappersCount: 1,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersType: 'variable',

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/index.browser.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/index.cli.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/index.js


+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "2.8.1",
+  "version": "2.9.0",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -56,7 +56,7 @@
     "@types/js-string-escape": "1.0.0",
     "@types/md5": "2.2.1",
     "@types/mkdirp": "1.0.1",
-    "@types/mocha": "8.0.3",
+    "@types/mocha": "8.0.4",
     "@types/multimatch": "4.0.0",
     "@types/node": "14.14.7",
     "@types/rimraf": "3.0.0",

+ 5 - 0
src/cli/JavaScriptObfuscatorCLI.ts

@@ -350,6 +350,11 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 `Default: ${StringArrayEncoding.None}`,
                 ArraySanitizer
             )
+            .option(
+                '--string-array-index-shift <boolean>',
+                'Enables additional index shift for all string array calls',
+                BooleanSanitizer
+            )
             .option(
                 '--string-array-wrappers-count <number>',
                 'Sets the count of wrappers for the string array inside each root or function scope',

+ 12 - 2
src/custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper.ts

@@ -20,6 +20,12 @@ import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
 export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper {
+    /**
+     * @type {number}
+     */
+    @initializable()
+    protected indexShiftAmount!: number;
+
     /**
      * @type {string}
      */
@@ -68,13 +74,16 @@ export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper
     /**
      * @param {string} stringArrayName
      * @param {string} stringArrayCallsWrapperName
+     * @param {number} indexShiftAmount
      */
     public initialize (
         stringArrayName: string,
-        stringArrayCallsWrapperName: string
+        stringArrayCallsWrapperName: string,
+        indexShiftAmount: number
     ): void {
         this.stringArrayName = stringArrayName;
         this.stringArrayCallsWrapperName = stringArrayCallsWrapperName;
+        this.indexShiftAmount = indexShiftAmount;
     }
 
     /**
@@ -97,7 +106,8 @@ export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper
             this.customCodeHelperFormatter.formatTemplate(StringArrayCallsWrapperTemplate(), {
                 decodeCodeHelperTemplate,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
-                stringArrayName: this.stringArrayName
+                stringArrayName: this.stringArrayName,
+                indexShiftAmount: this.indexShiftAmount
             }),
             {
                 reservedNames: preservedNames

+ 6 - 3
src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts

@@ -142,7 +142,8 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
 
             stringArrayCallsWrapperCodeHelper.initialize(
                 stringArrayName,
-                stringArrayCallsWrapperName
+                stringArrayCallsWrapperName,
+                this.stringArrayStorage.getIndexShiftAmount()
             );
 
             this.customCodeHelpers.set(stringArrayCallsWrapperCodeHelperName, stringArrayCallsWrapperCodeHelper);
@@ -151,9 +152,11 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
         // stringArrayRotateFunction helper initialize
         const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
             this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
-        const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
 
-        stringArrayRotateFunctionCodeHelper.initialize(stringArrayName, stringArrayRotationAmount);
+        stringArrayRotateFunctionCodeHelper.initialize(
+            stringArrayName,
+            this.stringArrayStorage.getRotationAmount()
+        );
 
         if (this.options.rotateStringArray) {
             this.customCodeHelpers.set(CustomCodeHelper.StringArrayRotateFunction, stringArrayRotateFunctionCodeHelper);

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

@@ -4,7 +4,7 @@
 export function StringArrayCallsWrapperTemplate (): string {
     return `
         const {stringArrayCallsWrapperName} = function (index, key) {
-            index = index - 0;
+            index = index - {indexShiftAmount};
             
             let value = {stringArrayName}[index];
             

+ 10 - 1
src/custom-nodes/string-array-nodes/StringArrayCallNode.ts

@@ -30,6 +30,12 @@ export class StringArrayCallNode extends AbstractStringArrayCallNode {
     @initializable()
     private index!: number;
 
+    /**
+     * @type {number}
+     */
+    @initializable()
+    private indexShiftAmount!: number;
+
     /**
      * @type {string}
      */
@@ -60,15 +66,18 @@ export class StringArrayCallNode extends AbstractStringArrayCallNode {
     /**
      * @param {string} stringArrayCallsWrapperName
      * @param {number} index
+     * @param {number} indexShiftAmount
      * @param {string | null} decodeKey
      */
     public initialize (
         stringArrayCallsWrapperName: string,
         index: number,
+        indexShiftAmount: number,
         decodeKey: string | null
     ): void {
         this.stringArrayCallsWrapperName = stringArrayCallsWrapperName;
         this.index = index;
+        this.indexShiftAmount = indexShiftAmount;
         this.decodeKey = decodeKey;
     }
 
@@ -77,7 +86,7 @@ export class StringArrayCallNode extends AbstractStringArrayCallNode {
      */
     protected getNodeStructure (): TStatement[] {
         const callExpressionArgs: ESTree.Expression[] = [
-            this.getHexadecimalNode(this.index)
+            this.getHexadecimalNode(this.indexShiftAmount + this.index)
         ];
 
         if (this.decodeKey) {

+ 1 - 0
src/interfaces/options/IOptions.ts

@@ -43,6 +43,7 @@ export interface IOptions {
     readonly splitStringsChunkLength: number;
     readonly stringArray: boolean;
     readonly stringArrayEncoding: TStringArrayEncoding[];
+    readonly stringArrayIndexShift: boolean;
     readonly stringArrayWrappersChainedCalls: boolean;
     readonly stringArrayWrappersCount: number;
     readonly stringArrayWrappersType: TStringArrayWrappersType;

+ 5 - 0
src/interfaces/storages/string-array-transformers/IStringArrayStorage.ts

@@ -4,6 +4,11 @@ import { IMapStorage } from '../IMapStorage';
 import { IStringArrayStorageItemData } from './IStringArrayStorageItem';
 
 export interface IStringArrayStorage extends IMapStorage <string, IStringArrayStorageItemData> {
+    /**
+     * @returns {number}
+     */
+    getIndexShiftAmount (): number;
+
     /**
      * @returns {number}
      */

+ 8 - 3
src/node-transformers/string-array-transformers/StringArrayTransformer.ts

@@ -204,16 +204,21 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
 
     /**
      * @param {IStringArrayStorageItemData} stringArrayStorageItemData
-     * @returns {Node}
+     * @returns {Expression}
      */
-    private getStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Node {
+    private getStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Expression {
         const [stringArrayCallsWrapperName, index] = this.getStringArrayCallsWrapperData(stringArrayStorageItemData);
         const {decodeKey } = stringArrayStorageItemData;
 
         const stringArrayCallCustomNode: ICustomNode<TInitialData<StringArrayCallNode>> =
             this.stringArrayTransformerCustomNodeFactory(StringArrayCustomNode.StringArrayCallNode);
 
-        stringArrayCallCustomNode.initialize(stringArrayCallsWrapperName, index, decodeKey);
+        stringArrayCallCustomNode.initialize(
+            stringArrayCallsWrapperName,
+            index,
+            this.stringArrayStorage.getIndexShiftAmount(),
+            decodeKey
+        );
 
         const statementNode: TStatement = stringArrayCallCustomNode.getNode()[0];
 

+ 6 - 0
src/options/Options.ts

@@ -314,6 +314,12 @@ export class Options implements IOptions {
     @IsIn([StringArrayEncoding.None, StringArrayEncoding.Base64, StringArrayEncoding.Rc4], { each: true })
     public readonly stringArrayEncoding!: TStringArrayEncoding[];
 
+    /**
+     * @type {boolean}
+     */
+    @IsBoolean()
+    public readonly stringArrayIndexShift!: boolean;
+
     /**
      * @type {boolean}
      */

+ 1 - 0
src/options/normalizer-rules/StringArrayRule.ts

@@ -18,6 +18,7 @@ export const StringArrayRule: TOptionsNormalizerRule = (options: IOptions): IOpt
             stringArrayEncoding: [
                 StringArrayEncoding.None
             ],
+            stringArrayIndexShift: false,
             stringArrayWrappersChainedCalls: false,
             stringArrayWrappersCount: 0,
             stringArrayThreshold: 0

+ 1 - 0
src/options/presets/Default.ts

@@ -47,6 +47,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
     stringArrayEncoding: [
         StringArrayEncoding.None
     ],
+    stringArrayIndexShift: true,
     stringArrayWrappersChainedCalls: true,
     stringArrayWrappersCount: 1,
     stringArrayWrappersType: StringArrayWrappersType.Variable,

+ 1 - 0
src/options/presets/NoCustomNodes.ts

@@ -44,6 +44,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
     stringArrayEncoding: [
         StringArrayEncoding.None
     ],
+    stringArrayIndexShift: false,
     stringArrayWrappersChainedCalls: false,
     stringArrayWrappersCount: 0,
     stringArrayWrappersType: StringArrayWrappersType.Variable,

+ 28 - 0
src/storages/string-array-transformers/StringArrayStorage.ts

@@ -29,6 +29,16 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
      */
     private static readonly maximumRotationAmount: number = 500;
 
+    /**
+     * @type {number}
+     */
+    private static readonly minimumIndexShiftAmount: number = 100;
+
+    /**
+     * @type {number}
+     */
+    private static readonly maximumIndexShiftAmount: number = 500;
+
     /**
      * @type {number}
      */
@@ -69,6 +79,11 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
      */
     private readonly rc4EncodedValuesSourcesCache: Map<string, string[]> = new Map();
 
+    /**
+     * @type {number}
+     */
+    private indexShiftAmount: number = 0;
+
     /**
      * @type {number}
      */
@@ -118,6 +133,12 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
     public initialize (): void {
         super.initialize();
 
+        this.indexShiftAmount = this.options.stringArrayIndexShift
+            ? this.randomGenerator.getRandomInteger(
+                StringArrayStorage.minimumIndexShiftAmount,
+                StringArrayStorage.maximumIndexShiftAmount
+            )
+            : 0;
         this.rotationAmount = this.options.rotateStringArray
             ? this.randomGenerator.getRandomInteger(
                 StringArrayStorage.minimumRotationAmount,
@@ -133,6 +154,13 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
         return this.getOrSetIfDoesNotExist(value);
     }
 
+    /**
+     * @returns {number}
+     */
+    public getIndexShiftAmount (): number {
+        return this.indexShiftAmount;
+    }
+
     /**
      * @returns {number}
      */

+ 28 - 10
test/dev/dev.ts

@@ -7,20 +7,38 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
-            const foo = { 
-                baz: 1
-            };
-            const bar = {
-                baz: 2,
-                bark: 3,
-                ...foo,
-            };
-            console.log(bar);
+            const foo = 'foo';
+            const bar = 'bar';
+            
+            function test1 () {
+                const baz = 'baz';
+                
+                function test2() {
+                    const bark = 'bark';
+                    
+                    console.log(bark);
+                }
+                
+                console.log(baz);
+                
+                test2();
+            }
+            
+            console.log(foo, bar);
+            
+            test1();
         `,
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             compact: false,
-            transformObjectKeys: true
+            rotateStringArray: true,
+            shuffleStringArray: true,
+            stringArray: true,
+            stringArrayIndexShift: true,
+            stringArrayThreshold: 1,
+            stringArrayWrappersCount: 2,
+            stringArrayWrappersChainedCalls: true,
+            stringArrayWrappersType: 'function'
         }
     ).getObfuscatedCode();
 

+ 160 - 58
test/functional-tests/custom-code-helpers/string-array/templates/string-array-calls-wrapper-node-template/StringArrayCallsWrapperTemplate.spec.ts

@@ -42,84 +42,186 @@ describe('StringArrayCallsWrapperTemplate', () => {
     });
 
     describe('Variant #1: `base64` encoding', () => {
-        const index: string = '0x0';
-        const expectedDecodedValue: string = 'test1';
-
-        let decodedValue: string;
-
-        before(() => {
-            const atobPolyfill = format(AtobTemplate(), {
-                atobFunctionName
-            });
-            const atobDecodeTemplate: string = format(
-                StringArrayBase64DecodeTemplate(randomGenerator),
-                {
-                    atobPolyfill,
-                    atobFunctionName,
-                    selfDefendingCode: '',
-                    stringArrayCallsWrapperName
-                }
-            );
-            const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
-                decodeCodeHelperTemplate: atobDecodeTemplate,
-                stringArrayCallsWrapperName,
-                stringArrayName
-            });
-
-            decodedValue = Function(`
+        describe('Variant #1: index shift amount is `0`', () => {
+            const index: string = '0x0';
+
+            const indexShiftAmount: number = 0;
+
+            const expectedDecodedValue: string = 'test1';
+
+            let decodedValue: string;
+
+            before(() => {
+                const atobPolyfill = format(AtobTemplate(), {
+                    atobFunctionName
+                });
+                const atobDecodeTemplate: string = format(
+                    StringArrayBase64DecodeTemplate(randomGenerator),
+                    {
+                        atobPolyfill,
+                        atobFunctionName,
+                        selfDefendingCode: '',
+                        stringArrayCallsWrapperName
+                    }
+                );
+                const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
+                    decodeCodeHelperTemplate: atobDecodeTemplate,
+                    indexShiftAmount,
+                    stringArrayCallsWrapperName,
+                    stringArrayName
+                });
+
+                decodedValue = Function(`
                 var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa('test1')}'];
             
                 ${stringArrayCallsWrapperTemplate}
                 
                 return ${stringArrayCallsWrapperName}(${index});
             `)();
+            });
+
+            it('should correctly return decoded value', () => {
+                assert.deepEqual(decodedValue, expectedDecodedValue);
+            });
         });
 
-        it('should correctly return decoded value', () => {
-            assert.deepEqual(decodedValue, expectedDecodedValue);
+        describe('Variant #2: index shift amount is `5`', () => {
+            const index: string = '0x5';
+
+            const indexShiftAmount: number = 5;
+
+            const expectedDecodedValue: string = 'test1';
+
+            let decodedValue: string;
+
+            before(() => {
+                const atobPolyfill = format(AtobTemplate(), {
+                    atobFunctionName
+                });
+                const atobDecodeTemplate: string = format(
+                    StringArrayBase64DecodeTemplate(randomGenerator),
+                    {
+                        atobPolyfill,
+                        atobFunctionName,
+                        selfDefendingCode: '',
+                        stringArrayCallsWrapperName
+                    }
+                );
+                const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
+                    decodeCodeHelperTemplate: atobDecodeTemplate,
+                    indexShiftAmount,
+                    stringArrayCallsWrapperName,
+                    stringArrayName
+                });
+
+                decodedValue = Function(`
+                var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa('test1')}'];
+            
+                ${stringArrayCallsWrapperTemplate}
+                
+                return ${stringArrayCallsWrapperName}(${index});
+            `)();
+            });
+
+            it('should correctly return decoded value', () => {
+                assert.deepEqual(decodedValue, expectedDecodedValue);
+            });
         });
     });
 
     describe('Variant #2: `rc4` encoding', () => {
-        const index: string = '0x0';
-        const key: string = 'key';
-        const expectedDecodedValue: string = 'test1';
-
-        let decodedValue: string;
-
-        before(() => {
-            const atobPolyfill = format(AtobTemplate(), {
-                atobFunctionName
-            });
-            const rc4Polyfill = format(Rc4Template(), {
-                atobFunctionName
-            });
-            const rc4decodeCodeHelperTemplate: string = format(
-                StringArrayRC4DecodeTemplate(randomGenerator),
-                {
-                    atobPolyfill,
-                    rc4Polyfill,
-                    selfDefendingCode: '',
-                    stringArrayCallsWrapperName
-                }
-            );
-            const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
-                decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
-                stringArrayCallsWrapperName,
-                stringArrayName
-            });
-
-            decodedValue = Function(`
+        describe('Variant #1: index shift amount is `0`', () => {
+            const index: string = '0x0';
+            const key: string = 'key';
+
+            const indexShiftAmount: number = 0;
+
+            const expectedDecodedValue: string = 'test1';
+
+            let decodedValue: string;
+
+            before(() => {
+                const atobPolyfill = format(AtobTemplate(), {
+                    atobFunctionName
+                });
+                const rc4Polyfill = format(Rc4Template(), {
+                    atobFunctionName
+                });
+                const rc4decodeCodeHelperTemplate: string = format(
+                    StringArrayRC4DecodeTemplate(randomGenerator),
+                    {
+                        atobPolyfill,
+                        rc4Polyfill,
+                        selfDefendingCode: '',
+                        stringArrayCallsWrapperName
+                    }
+                );
+                const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
+                    decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
+                    indexShiftAmount,
+                    stringArrayCallsWrapperName,
+                    stringArrayName
+                });
+
+                decodedValue = Function(`
                 var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'];
             
                 ${stringArrayCallsWrapperTemplate}
                 
                 return ${stringArrayCallsWrapperName}('${index}', '${key}');
             `)();
+            });
+
+            it('should correctly return decoded value', () => {
+                assert.deepEqual(decodedValue, expectedDecodedValue);
+            });
         });
 
-        it('should correctly return decoded value', () => {
-            assert.deepEqual(decodedValue, expectedDecodedValue);
+        describe('Variant #2: index shift amount is `5`', () => {
+            const index: string = '0x5';
+            const key: string = 'key';
+
+            const indexShiftAmount: number = 5;
+
+            const expectedDecodedValue: string = 'test1';
+
+            let decodedValue: string;
+
+            before(() => {
+                const atobPolyfill = format(AtobTemplate(), {
+                    atobFunctionName
+                });
+                const rc4Polyfill = format(Rc4Template(), {
+                    atobFunctionName
+                });
+                const rc4decodeCodeHelperTemplate: string = format(
+                    StringArrayRC4DecodeTemplate(randomGenerator),
+                    {
+                        atobPolyfill,
+                        rc4Polyfill,
+                        selfDefendingCode: '',
+                        stringArrayCallsWrapperName
+                    }
+                );
+                const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
+                    decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
+                    indexShiftAmount,
+                    stringArrayCallsWrapperName,
+                    stringArrayName
+                });
+
+                decodedValue = Function(`
+                var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'];
+            
+                ${stringArrayCallsWrapperTemplate}
+                
+                return ${stringArrayCallsWrapperName}('${index}', '${key}');
+            `)();
+            });
+
+            it('should correctly return decoded value', () => {
+                assert.deepEqual(decodedValue, expectedDecodedValue);
+            });
         });
     });
 

+ 2 - 0
test/functional-tests/options/OptionsNormalizer.spec.ts

@@ -544,6 +544,7 @@ describe('OptionsNormalizer', () => {
                     shuffleStringArray: true,
                     stringArray: false,
                     stringArrayEncoding: [StringArrayEncoding.Rc4],
+                    stringArrayIndexShift: true,
                     stringArrayWrappersChainedCalls: true,
                     stringArrayWrappersCount: 5,
                     stringArrayThreshold: 0.5,
@@ -555,6 +556,7 @@ describe('OptionsNormalizer', () => {
                     shuffleStringArray: false,
                     stringArray: false,
                     stringArrayEncoding: [StringArrayEncoding.None],
+                    stringArrayIndexShift: false,
                     stringArrayWrappersChainedCalls: false,
                     stringArrayWrappersCount: 0,
                     stringArrayThreshold: 0,

+ 1 - 0
test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

@@ -40,6 +40,7 @@ describe('JavaScriptObfuscator runtime eval', function () {
             StringArrayEncoding.Base64,
             StringArrayEncoding.Rc4
         ],
+        stringArrayIndexShift: true,
         stringArrayWrappersChainedCalls: true,
         stringArrayWrappersCount: 5,
         stringArrayWrappersType: StringArrayWrappersType.Function,

+ 1 - 1
test/unit-tests/analyzers/string-array-storage-analyzer/StringArrayStorageAnalyzer.spec.ts

@@ -434,7 +434,7 @@ describe('StringArrayStorageAnalyzer', () => {
                 before(() => {
                     stringArrayStorageAnalyzer = getStringArrayStorageAnalyzer({
                         stringArrayThreshold: 0.5,
-                        seed: 1
+                        seed: 3
                     });
 
                     const astTree: ESTree.Program = NodeFactory.programNode([

+ 4 - 4
yarn.lock

@@ -513,10 +513,10 @@
   dependencies:
     "@types/node" "*"
 
-"@types/[email protected].3":
-  version "8.0.3"
-  resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.3.tgz#51b21b6acb6d1b923bbdc7725c38f9f455166402"
-  integrity sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==
+"@types/[email protected].4":
+  version "8.0.4"
+  resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.4.tgz#b840c2dce46bacf286e237bfb59a29e843399148"
+  integrity sha512-M4BwiTJjHmLq6kjON7ZoI2JMlBvpY3BYSdiP6s/qCT3jb1s9/DeJF0JELpAxiVSIxXDzfNKe+r7yedMIoLbknQ==
 
 "@types/[email protected]":
   version "4.0.0"

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor