Forráskód Böngészése

* `stringArrayWrappersType: 'function'` now appends `FunctionDeclaration` functions instead of `FunctionExpression` functions. This allows to append these wrappers at random positions inside each scope

sanex 3 éve
szülő
commit
3a71c78304

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 
+v2.16.0
+---
+* `stringArrayWrappersType: 'function'` now appends `FunctionDeclaration` functions instead of `FunctionExpression` functions. This allows to append these wrappers at random positions inside each scope
+
 v2.15.6
 ---
 * To increase performance and prevent possible runtime errors `transformObjectKeys` option now completely ignores objects with `CallExpression` or `NewExpression` nodes. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/948

+ 11 - 11
README.md

@@ -1281,8 +1281,8 @@ Type: `string` Default: `variable`
 Allows to select a type of the wrappers that are appending by the `stringArrayWrappersCount` option.
 
 Available values:
-* `'variable'`: appends variable wrappers. Fast performance.
-* `'function'`: appends function wrappers. Slower performance than with `variable` but provides more strict obfuscation
+* `'variable'`: appends variable wrappers at the top of each scope. Fast performance.
+* `'function'`: appends function wrappers at random positions inside each scope. Slower performance than with `variable` but provides more strict obfuscation.
 
 Highly recommended to use `function` wrappers for higher obfuscation when a performance loss doesn't have a high impact on an obfuscated application.
 
@@ -1304,9 +1304,6 @@ const a = [
     'bar',
     'foo'
 ];
-const d = function (c, g) {
-    return b(g - 0x3e1, c);
-};
 const foo = d(0x567, 0x568);
 function b(c, d) {
     b = function (e, f) {
@@ -1317,14 +1314,17 @@ function b(c, d) {
     return b(c, d);
 }
 function test() {
-    const e = function (c, g) {
-        return b(c - 0x396, g);
-    };
-    const f = function (c, g) {
-        return b(c - 0x396, g);
-    };
     const c = e(0x51c, 0x51b);
+    function e (c, g) {
+        return b(c - 0x396, g);
+    }
     console[f(0x51b, 0x51d)](foo, c);
+    function f (c, g) {
+        return b(c - 0x396, g);
+    }
+}
+function d (c, g) {
+    return b(g - 0x3e1, c);
 }
 test();
 ```

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/index.browser.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/index.cli.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "2.15.6",
+  "version": "2.16.0",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",

+ 5 - 12
src/custom-nodes/string-array-nodes/StringArrayScopeCallsWrapperFunctionNode.ts

@@ -165,8 +165,9 @@ export class StringArrayScopeCallsWrapperFunctionNode extends AbstractStringArra
             decodeKeyIdentifierNode
         );
 
-        // stage 3: function expression node
-        const functionExpressionNode: ESTree.FunctionExpression =  NodeFactory.functionExpressionNode(
+        // stage 3: function declaration node
+        const functionDeclarationNode: ESTree.FunctionDeclaration =  NodeFactory.functionDeclarationNode(
+            this.stringArrayScopeCallsWrapperName,
             parameters,
             NodeFactory.blockStatementNode([
                 NodeFactory.returnStatementNode(
@@ -178,22 +179,14 @@ export class StringArrayScopeCallsWrapperFunctionNode extends AbstractStringArra
             ])
         );
 
-        const structure: TStatement = NodeFactory.variableDeclarationNode(
-            [
-                NodeFactory.variableDeclaratorNode(
-                    NodeFactory.identifierNode(this.stringArrayScopeCallsWrapperName),
-                    functionExpressionNode
-                )
-            ],
-            'const',
-        );
+        const structure: TStatement = functionDeclarationNode;
 
         NodeUtils.parentizeAst(structure);
 
         // stage 4: rename
         // have to generate names for both parameter and call identifiers
         for (const parameter of parameters) {
-            parameter.name = this.identifierNamesGenerator.generateForLexicalScope(functionExpressionNode);
+            parameter.name = this.identifierNamesGenerator.generateForLexicalScope(functionDeclarationNode);
         }
 
         return [structure];

+ 33 - 14
src/node-transformers/string-array-transformers/StringArrayScopeCallsWrapperTransformer.ts

@@ -172,17 +172,13 @@ export class StringArrayScopeCallsWrapperTransformer extends AbstractNodeTransfo
                     stringArrayScopeCallsWrapperLexicalScopeData,
                 );
 
-                const stringArrayScopeCallsWrapperNode: TStatement[] = this.getStringArrayScopeCallsWrapperNode(
+                this.getAndAppendStringArrayScopeCallsWrapperNode(
+                    lexicalScopeBodyNode,
                     stringArrayScopeCallsWrapperName,
                     stringArrayScopeCallsWrapperParameterIndexes,
                     upperStringArrayCallsWrapperName,
                     upperStringArrayCallsWrapperParameterIndexes,
-                    upperStringArrayCallsWrapperShiftedIndex
-                );
-
-                NodeAppender.prepend(
-                    lexicalScopeBodyNode,
-                    stringArrayScopeCallsWrapperNode
+                    upperStringArrayCallsWrapperShiftedIndex,
                 );
             }
         }
@@ -263,23 +259,31 @@ export class StringArrayScopeCallsWrapperTransformer extends AbstractNodeTransfo
     }
 
     /**
+     * @param {TNodeWithLexicalScopeStatements} lexicalScopeBodyNode
      * @param {string} stringArrayScopeCallsWrapperName
      * @param {IStringArrayScopeCallsWrapperParameterIndexesData | null} stringArrayScopeCallsWrapperParameterIndexes
      * @param {string} upperStringArrayCallsWrapperName
      * @param {IStringArrayScopeCallsWrapperParameterIndexesData | null} upperStringArrayCallsWrapperParameterIndexes
      * @param {number} stringArrayScopeCallsWrapperShiftedIndex
-     * @returns {TStatement[]}
      */
-    private getStringArrayScopeCallsWrapperNode (
+    private getAndAppendStringArrayScopeCallsWrapperNode (
+        lexicalScopeBodyNode: TNodeWithLexicalScopeStatements,
         stringArrayScopeCallsWrapperName: string,
         stringArrayScopeCallsWrapperParameterIndexes: IStringArrayScopeCallsWrapperParameterIndexesData | null,
         upperStringArrayCallsWrapperName: string,
         upperStringArrayCallsWrapperParameterIndexes: IStringArrayScopeCallsWrapperParameterIndexesData | null,
         stringArrayScopeCallsWrapperShiftedIndex: number
-    ): TStatement[] {
+    ): void {
+        let stringArrayScopeCallsWrapperNode: TStatement[];
+
         switch (this.options.stringArrayWrappersType) {
-            case StringArrayWrappersType.Function:
-                return this.getStringArrayScopeCallsWrapperFunctionNode(
+            case StringArrayWrappersType.Function: {
+                const randomIndex: number = this.randomGenerator.getRandomInteger(
+                    0,
+                    lexicalScopeBodyNode.body.length - 1
+                );
+
+                stringArrayScopeCallsWrapperNode = this.getStringArrayScopeCallsWrapperFunctionNode(
                     stringArrayScopeCallsWrapperName,
                     stringArrayScopeCallsWrapperParameterIndexes,
                     upperStringArrayCallsWrapperName,
@@ -287,12 +291,27 @@ export class StringArrayScopeCallsWrapperTransformer extends AbstractNodeTransfo
                     stringArrayScopeCallsWrapperShiftedIndex
                 );
 
+                NodeAppender.insertAtIndex(
+                    lexicalScopeBodyNode,
+                    stringArrayScopeCallsWrapperNode,
+                    randomIndex
+                );
+
+                break;
+            }
+
             case StringArrayWrappersType.Variable:
-            default:
-                return this.getStringArrayScopeCallsWrapperVariableNode(
+            default: {
+                stringArrayScopeCallsWrapperNode = this.getStringArrayScopeCallsWrapperVariableNode(
                     stringArrayScopeCallsWrapperName,
                     upperStringArrayCallsWrapperName
                 );
+
+                NodeAppender.prepend(
+                    lexicalScopeBodyNode,
+                    stringArrayScopeCallsWrapperNode
+                );
+            }
         }
     }
 

+ 15 - 4
test/dev/dev.ts

@@ -7,9 +7,18 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
 
     let obfuscationResult = JavaScriptObfuscator.obfuscate(
         `
-            console.log('foo');
-            console.log('bar');
-            console.log('bar');
+             (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);
+            })();
         `,
         {
             ...NO_ADDITIONAL_NODES_PRESET,
@@ -17,7 +26,9 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
             simplify: false,
             stringArray: true,
             stringArrayThreshold: 1,
-            stringArrayEncoding: ['base64'],
+            stringArrayChainedCalls: true,
+            stringArrayWrappersCount: 2,
+            stringArrayWrappersType: 'function',
             identifierNamesGenerator: 'mangled'
         }
     );

+ 171 - 76
test/functional-tests/node-transformers/string-array-transformers/string-array-scope-calls-wrapper-transformer/StringArrayScopeCallsWrapperTransformer.spec.ts

@@ -644,20 +644,29 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #1: base', () => {
                 describe('Variant #1: `hexadecimal-number` indexes type', () => {
-                    const stringArrayCallRegExp: RegExp = new RegExp(
-                        'const f *= *function *\\(c, *d\\) *{' +
+                    const getStringArrayCallsWrapperMatch = (stringArrayCallsWrapperName: string) =>
+                        `function *${stringArrayCallsWrapperName} *\\(c, *d\\) *{` +
                             `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                        '};.*' +
+                        '}';
+
+                    const stringArrayScopeCallsWrapperRegExp1: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        getStringArrayCallsWrapperMatch('f')
+                    );
+                    const stringArrayScopeCallsWrapperRegExp2: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function test *\\( *\\) *{.*' +
+                            `${getStringArrayCallsWrapperMatch('g')}.*?` +
+                        '}'
+                    );
+                    const stringArrayCallsWrapperCallsRegExp: RegExp = new RegExp(
                         `const foo *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
                         `const bar *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
                         `const baz *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
-                        'function test *\\( *\\) *{' +
-                            'const g *= *function *\\(c, *d\\) *{' +
-                                `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                            '};' +
-                            `const c *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
-                            `const d *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
-                            `const e *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
+                        'function test *\\( *\\) *{.*' +
+                            `const c *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
+                            `const d *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
+                            `const e *= *g\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
                         '}'
                     );
 
@@ -689,8 +698,16 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                         ).areSuccessEvaluations;
                     });
 
-                    it('should add correct scope calls wrappers', () => {
-                        assert.match(obfuscatedCode, stringArrayCallRegExp);
+                    it('Match #1: should add correct scope calls wrapper 1', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp1);
+                    });
+
+                    it('Match #2: should add correct scope calls wrapper 2', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp2);
+                    });
+
+                    it('Match #3: should add correct scope calls wrappers calls', () => {
+                        assert.match(obfuscatedCode, stringArrayCallsWrapperCallsRegExp);
                     });
 
                     it('should evaluate code without errors', () => {
@@ -699,20 +716,29 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                 });
 
                 describe('Variant #2: `hexadecimal-numeric-string` indexes type', () => {
-                    const stringArrayCallRegExp: RegExp = new RegExp(
-                        'const f *= *function *\\(c, *d\\) *{' +
+                    const getStringArrayCallsWrapperMatch = (stringArrayCallsWrapperName: string) =>
+                        `function *${stringArrayCallsWrapperName} *\\(c, *d\\) *{` +
                             `return b\\([cd] *-(?: -)?'${hexadecimalIndexMatch}', *[cd]\\);` +
-                        '};.*' +
+                        '}';
+
+                    const stringArrayScopeCallsWrapperRegExp1: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        getStringArrayCallsWrapperMatch('f')
+                    );
+                    const stringArrayScopeCallsWrapperRegExp2: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function test *\\( *\\) *{.*' +
+                            `${getStringArrayCallsWrapperMatch('g')}.*?` +
+                        '}'
+                    );
+                    const stringArrayCallsWrapperCallRegExp: RegExp = new RegExp(
                         `const foo *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
                         `const bar *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
                         `const baz *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
-                        'function test *\\( *\\) *{' +
-                            'const g *= *function *\\(c, *d\\) *{' +
-                                `return b\\([cd] *-(?: -)?'${hexadecimalIndexMatch}', *[cd]\\);` +
-                            '};' +
-                            `const c *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
-                            `const d *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
-                            `const e *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
+                        'function test *\\( *\\) *{.*' +
+                            `const c *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
+                            `const d *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
+                            `const e *= *g\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
                         '}'
                     );
 
@@ -744,8 +770,16 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                         ).areSuccessEvaluations;
                     });
 
-                    it('should add correct scope calls wrappers', () => {
-                        assert.match(obfuscatedCode, stringArrayCallRegExp);
+                    it('Match #1: should add correct scope calls wrapper 1', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp1);
+                    });
+
+                    it('Match #2: should add correct scope calls wrapper 2', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp2);
+                    });
+
+                    it('Match #3: should add correct scope calls wrappers', () => {
+                        assert.match(obfuscatedCode, stringArrayCallsWrapperCallRegExp);
                     });
 
                     it('should evaluate code without errors', () => {
@@ -755,24 +789,32 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
             });
 
             describe('Variant #2: correct chained calls', () => {
-                const stringArrayCallRegExp: RegExp = new RegExp(
-                    'const f *= *function *\\(c, *d\\) *{' +
+                const stringArrayScopeCallsWrapperRegExp1: RegExp = new RegExp(
+                    'const a *= *\\[.*?];.*?' +
+                    'function *f *\\(c, *d\\) *{' +
                         `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                    '};.*' +
-                    `const foo *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
-                    `const bar *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
-                    `const baz *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
-                    'function test *\\( *\\) *{' +
-                        'const g *= *function *\\(c, *d\\) *{' +
+                    '}.*'
+                );
+                const stringArrayScopeCallsWrapperRegExp2: RegExp = new RegExp(
+                    'const a *= *\\[.*?];.*?' +
+                    'function test *\\( *\\) *{.*' +
+                        'function *g *\\(c, *d\\) *{' +
                             `return f\\(` +
                                 // order of arguments depends on the parent wrapper parameters order
                                 `[cd](?: *-(?: -)?${hexadecimalIndexMatch})?, *` +
                                 `[cd](?: *-(?: -)?${hexadecimalIndexMatch})?` +
                             `\\);` +
-                        '};' +
-                        `const c *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const d *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const e *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
+                        '}.*' +
+                    '}'
+                );
+                const stringArrayCallsWrapperCallRegExp: RegExp = new RegExp(
+                    `const foo *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                    `const bar *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                    `const baz *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                    'function test *\\( *\\) *{.*' +
+                        `const c *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const d *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const e *= *g\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
                     '}'
                 );
 
@@ -801,8 +843,16 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     ).areSuccessEvaluations;
                 });
 
-                it('should add correct scope calls wrappers', () => {
-                    assert.match(obfuscatedCode, stringArrayCallRegExp);
+                it('Match #1: should add correct scope calls wrapper 1', () => {
+                    assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp1);
+                });
+
+                it('Match #2: should add correct scope calls wrapper 2', () => {
+                    assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp2);
+                });
+
+                it('Match #3: should add correct scope calls wrappers', () => {
+                    assert.match(obfuscatedCode, stringArrayCallsWrapperCallRegExp);
                 });
 
                 it('should evaluate code without errors', () => {
@@ -811,15 +861,20 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
             });
 
             describe('Variant #3: no wrappers on a root scope', () => {
-                const stringArrayCallRegExp: RegExp = new RegExp(
-                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
-                    'function test *\\( *\\) *{' +
-                        'const f *= *function *\\(c, *d\\) *{' +
+                const stringArrayScopeCallsWrapperRegExp: RegExp = new RegExp(
+                    'const a *= *\\[.*?];.*' +
+                    'function test *\\( *\\) *{.*' +
+                        'function *f*\\(c, *d\\) *{' +
                             `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                        '};' +
-                        `const c *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const d *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const e *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
+                        '}.*' +
+                    '}'
+                );
+                const stringArrayCallsWrapperCallRegExp: RegExp = new RegExp(
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    'function test *\\( *\\) *{.*' +
+                        `const c *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const d *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const e *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
                     '}'
                 );
 
@@ -848,8 +903,12 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     ).areSuccessEvaluations;
                 });
 
-                it('should add correct scope calls wrappers', () => {
-                    assert.match(obfuscatedCode, stringArrayCallRegExp);
+                it('Match #1: should add correct scope calls wrapper', () => {
+                    assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp);
+                });
+
+                it('Match #2: should add correct scope calls wrappers', () => {
+                    assert.match(obfuscatedCode, stringArrayCallsWrapperCallRegExp);
                 });
 
                 it('should evaluate code without errors', () => {
@@ -1026,15 +1085,17 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayWrapperArgumentsRegExpString: string = Array(5)
                         .fill(`-? *${hexadecimalIndexMatch}`)
                         .join(', *');
-                    const stringArrayCallRegExp: RegExp = new RegExp(
-                        'const f *= *function *\\(c, *d, *e, *h, *i\\) *{' +
+
+                    const stringArrayScopeCallsWrapperRegExp1: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function *f *\\(c, *d, *e, *h, *i\\) *{' +
                             `return b\\([cdehi] *-(?: -)?${hexadecimalIndexMatch}, *[cdehi]\\);` +
-                        '};.*' +
-                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        'function test *\\( *\\) *{' +
-                            'const g *= *function *\\(c, *d, *e, *h, *i\\) *{' +
+                        '}.*'
+                    );
+                    const stringArrayScopeCallsWrapperRegExp2: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function test *\\( *\\) *{.*' +
+                            'function *g *\\(c, *d, *e, *h, *i\\) *{' +
                                 `return f\\(` +
                                     // order of arguments depends on the parent wrapper parameters order
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?, *` +
@@ -1043,10 +1104,18 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?, *` +
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?` +
                                 `\\);` +
-                            '};' +
-                            `const c *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                            `const d *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                            `const e *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
+                            '}.*' +
+                        '}'
+                    );
+
+                    const stringArrayCallsWrapperCallRegExp: RegExp = new RegExp(
+                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        'function test *\\( *\\) *{.*' +
+                            `const c *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                            `const d *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                            `const e *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
                         '}'
                     );
 
@@ -1076,8 +1145,16 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                         ).areSuccessEvaluations;
                     });
 
-                    it('should add correct scope calls wrappers', () => {
-                        assert.match(obfuscatedCode, stringArrayCallRegExp);
+                    it('Match #1: should add correct scope calls wrapper 1', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp1);
+                    });
+
+                    it('Match #2: should add correct scope calls wrapper 2', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp2);
+                    });
+
+                    it('Match #3: should add correct scope calls wrappers', () => {
+                        assert.match(obfuscatedCode, stringArrayCallsWrapperCallRegExp);
                     });
 
                     it('should evaluate code without errors', () => {
@@ -1089,15 +1166,17 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayWrapperArgumentsRegExpString: string = Array(5)
                         .fill(`(?:-? *${hexadecimalIndexMatch}|(?:'.{4}'))`)
                         .join(', *');
-                    const stringArrayCallRegExp: RegExp = new RegExp(
-                        'const f *= *function *\\(c, *d, *e, *h, *i\\) *{' +
+
+                    const stringArrayScopeCallsWrapperRegExp1: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function *f *\\(c, *d, *e, *h, *i\\) *{' +
                             `return b\\([cdehi] *-(?: -)?${hexadecimalIndexMatch}, *[cdehi]\\);` +
-                        '};.*' +
-                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
-                        'function test *\\( *\\) *{' +
-                            'const g *= *function *\\(c, *d, *e, *h, *i\\) *{' +
+                        '}.*'
+                    );
+                    const stringArrayScopeCallsWrapperRegExp2: RegExp = new RegExp(
+                        'const a *= *\\[.*?];.*?' +
+                        'function test *\\( *\\) *{.*' +
+                            'function *g *\\(c, *d, *e, *h, *i\\) *{' +
                                 `return f\\(` +
                                     // order of arguments depends on the parent wrapper parameters order
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?, *` +
@@ -1106,10 +1185,18 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?, *` +
                                     `[cdehi](?: *-(?: -)?${hexadecimalIndexMatch})?` +
                                 `\\);` +
-                            '};' +
-                            `const c *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                            `const d *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                            `const e *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
+                            '}.*' +
+                        '}'
+                    );
+
+                    const stringArrayCallsWrapperCallRegExp: RegExp = new RegExp(
+                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        'function test *\\( *\\) *{.*' +
+                            `const c *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                            `const d *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                            `const e *= *g\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
                         '}'
                     );
 
@@ -1142,8 +1229,16 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                         ).areSuccessEvaluations;
                     });
 
-                    it('should add correct scope calls wrappers', () => {
-                        assert.match(obfuscatedCode, stringArrayCallRegExp);
+                    it('Match #1: should add correct scope calls wrapper 1', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp1);
+                    });
+
+                    it('Match #2: should add correct scope calls wrapper 2', () => {
+                        assert.match(obfuscatedCode, stringArrayScopeCallsWrapperRegExp2);
+                    });
+
+                    it('Match #3: should add correct scope calls wrappers', () => {
+                        assert.match(obfuscatedCode, stringArrayCallsWrapperCallRegExp);
                     });
 
                     it('should evaluate code without errors', () => {

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott