Browse Source

Merge pull request #162 from javascript-obfuscator/improved-string-array-templates

Improved string array templates
Timofey Kachalov 7 years ago
parent
commit
5a57fb5df7

+ 1 - 0
CHANGELOG.md

@@ -4,6 +4,7 @@ v0.14.0
 ---
 * **Breaking change:** Now CLI obfuscating directory recursively. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/157
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/156
+* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/159
 
 v0.13.0
 ---

File diff suppressed because it is too large
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.14.0-beta.1",
+  "version": "0.14.0-beta.2",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",

+ 27 - 15
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts

@@ -118,29 +118,41 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
             selfDefendingCode: string = '';
 
         if (this.options.selfDefending) {
-            selfDefendingCode = format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
-                stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
-                stringArrayName: this.stringArrayName
-            });
+            selfDefendingCode = format(
+                SelfDefendingTemplate(
+                    this.randomGenerator,
+                    this.escapeSequenceEncoder
+                ),
+                {
+                    stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
+                    stringArrayName: this.stringArrayName
+                }
+            );
         }
 
         switch (this.options.stringArrayEncoding) {
             case StringArrayEncoding.Rc4:
-                decodeStringArrayTemplate = format(StringArrayRc4DecodeNodeTemplate(), {
-                    atobPolyfill,
-                    rc4Polyfill: Rc4Template(),
-                    selfDefendingCode,
-                    stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
-                });
+                decodeStringArrayTemplate = format(
+                    StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
+                    {
+                        atobPolyfill,
+                        rc4Polyfill: Rc4Template(),
+                        selfDefendingCode,
+                        stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
+                    }
+                );
 
                 break;
 
             case StringArrayEncoding.Base64:
-                decodeStringArrayTemplate = format(StringArrayBase64DecodeNodeTemplate(), {
-                    atobPolyfill,
-                    selfDefendingCode,
-                    stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
-                });
+                decodeStringArrayTemplate = format(
+                    StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
+                    {
+                        atobPolyfill,
+                        selfDefendingCode,
+                        stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
+                    }
+                );
 
                 break;
         }

+ 40 - 33
src/templates/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate.ts

@@ -1,59 +1,66 @@
 import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
-import { Utils } from '../../../utils/Utils';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 /**
+ * @param {IRandomGenerator} randomGenerator
  * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
  * @returns {string}
+ * @constructor
  */
-export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
-    const symTbl: { [key: string]: string } = {
-        'rc4Bytes': Utils.generateIden(),
-        'states': Utils.generateIden(),
-        'newState': Utils.generateIden(),
-        'firstState': Utils.generateIden(),
-        'secondState': Utils.generateIden(),
-        'checkState': Utils.generateIden(),
-        'runState': Utils.generateIden(),
-        'getState': Utils.generateIden(),
-        'stateResult': Utils.generateIden()
-    };
+export function SelfDefendingTemplate (
+    randomGenerator: IRandomGenerator,
+    escapeSequenceEncoder: IEscapeSequenceEncoder
+): string {
+    const identifierLength: number = 6;
+    const rc4BytesIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const statesIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const newStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const firstStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const secondStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const checkStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const runStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const getStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const stateResultIdentifier: string = randomGenerator.getRandomString(identifierLength);
     
     return `
-        var StatesClass = function (${symTbl.rc4Bytes}) {
-            this.${symTbl.rc4Bytes} = ${symTbl.rc4Bytes};
-            this.${symTbl.states} = [1, 0, 0];
-            this.${symTbl.newState} = function(){return 'newState';};
-            this.${symTbl.firstState} = '${
+        var StatesClass = function (${rc4BytesIdentifier}) {
+            this.${rc4BytesIdentifier} = ${rc4BytesIdentifier};
+            this.${statesIdentifier} = [1, 0, 0];
+            this.${newStateIdentifier} = function(){return 'newState';};
+            this.${firstStateIdentifier} = '${
                 escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *`, true)
             }';
-            this.${symTbl.secondState} = '${
+            this.${secondStateIdentifier} = '${
                 escapeSequenceEncoder.encode(`['|"].+['|"];? *}`, true)
             }';
         };
         
-        StatesClass.prototype.${symTbl.checkState} = function () {
-            var regExp = new RegExp(this.${symTbl.firstState} + this.${symTbl.secondState});
-
-            return this.${symTbl.runState}(regExp.test(this.${symTbl.newState}.toString()) ? --this.${symTbl.states}[1] : --this.${symTbl.states}[0]);
+        StatesClass.prototype.${checkStateIdentifier} = function () {
+            var regExp = new RegExp(this.${firstStateIdentifier} + this.${secondStateIdentifier});
+            var expression = regExp.test(this.${newStateIdentifier}.toString())
+                ? --this.${statesIdentifier}[1]
+                : --this.${statesIdentifier}[0];
+            
+            return this.${runStateIdentifier}(expression);
         };
         
-        StatesClass.prototype.${symTbl.runState} = function (${symTbl.stateResult}) {
-            if (!Boolean(~${symTbl.stateResult})) {
-                return ${symTbl.stateResult};
+        StatesClass.prototype.${runStateIdentifier} = function (${stateResultIdentifier}) {
+            if (!Boolean(~${stateResultIdentifier})) {
+                return ${stateResultIdentifier};
             }
             
-            return this.${symTbl.getState}(this.${symTbl.rc4Bytes});
+            return this.${getStateIdentifier}(this.${rc4BytesIdentifier});
         };
 
-        StatesClass.prototype.${symTbl.getState} = function (${symTbl.rc4Bytes}) {
-            for (var i = 0, len = this.${symTbl.states}.length; i < len; i++) {
-                this.${symTbl.states}.push(Math.round(Math.random()));
-                len = this.${symTbl.states}.length;
+        StatesClass.prototype.${getStateIdentifier} = function (${rc4BytesIdentifier}) {
+            for (var i = 0, len = this.${statesIdentifier}.length; i < len; i++) {
+                this.${statesIdentifier}.push(Math.round(Math.random()));
+                len = this.${statesIdentifier}.length;
             }
             
-            return ${symTbl.rc4Bytes}(this.${symTbl.states}[0]);
+            return ${rc4BytesIdentifier}(this.${statesIdentifier}[0]);
         };
 
-        new StatesClass({stringArrayCallsWrapperName}).${symTbl.checkState}();
+        new StatesClass({stringArrayCallsWrapperName}).${checkStateIdentifier}();
     `;
 }

+ 19 - 8
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate.ts

@@ -1,12 +1,23 @@
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+
 /**
+ * @param {IRandomGenerator} randomGenerator
  * @returns {string}
+ * @constructor
  */
-export function StringArrayBase64DecodeNodeTemplate (): string {
+export function StringArrayBase64DecodeNodeTemplate (
+    randomGenerator: IRandomGenerator
+): string {
+    const identifierLength: number = 6;
+    const initializedIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const base64DecodeFunctionIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const dataIdentifier: string = randomGenerator.getRandomString(identifierLength);
+
     return `
-        if ({stringArrayCallsWrapperName}.initialized === undefined) {
+        if ({stringArrayCallsWrapperName}.${initializedIdentifier} === undefined) {
             {atobPolyfill}
             
-            {stringArrayCallsWrapperName}.base64DecodeUnicode = function (str) {
+            {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier} = function (str) {
                 var string = atob(str);
                 var newStringChars = [];
                 
@@ -17,18 +28,18 @@ export function StringArrayBase64DecodeNodeTemplate (): string {
                 return decodeURIComponent(newStringChars);
             };
             
-            {stringArrayCallsWrapperName}.data = {};
+            {stringArrayCallsWrapperName}.${dataIdentifier} = {};
             
-            {stringArrayCallsWrapperName}.initialized = true;
+            {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
                   
-        var cachedValue = {stringArrayCallsWrapperName}.data[index];
+        var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
                         
         if (cachedValue === undefined) {
             {selfDefendingCode}
             
-            value = {stringArrayCallsWrapperName}.base64DecodeUnicode(value);
-            {stringArrayCallsWrapperName}.data[index] = value;
+            value = {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier}(value);
+            {stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
         } else {
             value = cachedValue;
         }

+ 20 - 17
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate.ts

@@ -1,39 +1,42 @@
-import { Utils } from '../../../utils/Utils';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 /**
+ * @param {IRandomGenerator} randomGenerator
  * @returns {string}
+ * @constructor
  */
-export function StringArrayRc4DecodeNodeTemplate (): string {
-    const symTbl: { [key: string]: string } = {
-        'initialized': Utils.generateIden(),
-        'rc4': Utils.generateIden(),
-        'data': Utils.generateIden(),
-        'once': Utils.generateIden()
-    };
+export function StringArrayRc4DecodeNodeTemplate (
+    randomGenerator: IRandomGenerator
+): string {
+    const identifierLength: number = 6;
+    const initializedIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const rc4Identifier: string = randomGenerator.getRandomString(identifierLength);
+    const dataIdentifier: string = randomGenerator.getRandomString(identifierLength);
+    const onceIdentifier: string = randomGenerator.getRandomString(identifierLength);
   
     return `
-        if ({stringArrayCallsWrapperName}.${symTbl.initialized} === undefined) {
+        if ({stringArrayCallsWrapperName}.${initializedIdentifier} === undefined) {
             {atobPolyfill}
             
             {rc4Polyfill}
-            {stringArrayCallsWrapperName}.${symTbl.rc4} = rc4;
+            {stringArrayCallsWrapperName}.${rc4Identifier} = rc4;
             
-            {stringArrayCallsWrapperName}.${symTbl.data} = {};
+            {stringArrayCallsWrapperName}.${dataIdentifier} = {};
             
-            {stringArrayCallsWrapperName}.${symTbl.initialized} = true;
+            {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
   
-        var cachedValue = {stringArrayCallsWrapperName}.${symTbl.data}[index];
+        var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
 
         if (cachedValue === undefined) {
-            if ({stringArrayCallsWrapperName}.${symTbl.once} === undefined) {
+            if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
                 {selfDefendingCode}
                 
-                {stringArrayCallsWrapperName}.${symTbl.once} = true;
+                {stringArrayCallsWrapperName}.${onceIdentifier} = true;
             }
             
-            value = {stringArrayCallsWrapperName}.${symTbl.rc4}(value, key);
-            {stringArrayCallsWrapperName}.${symTbl.data}[index] = value;
+            value = {stringArrayCallsWrapperName}.${rc4Identifier}(value, key);
+            {stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
         } else {
             value = cachedValue;
         }

+ 1 - 1
src/types/TObject.d.ts

@@ -1 +1 @@
-export type TObject = {[key: string]: any};
+export type TObject <T = any> = {[key: string]: T};

+ 0 - 20
src/utils/Utils.ts

@@ -71,24 +71,4 @@ export class Utils {
             })
             .join(' + ');
     }
-    
-    /**
-     * @returns {string}
-     */
-    public static generateIden (): string {
-        let validIden: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_';
-        let ret: string = '';
-        
-        const idenIdx: (() => number) = () => Math.floor(Math.random() * validIden.length) % validIden.length;
-
-        ret += validIden[idenIdx()];
-        validIden += '0123456789';
-        
-        const len: number = Math.floor((Math.random() * 10) + 3);
-        for (let i: number = 0; i < len; i++) {
-            ret += validIden[idenIdx()];
-        }
-        
-        return ret;
-    }
 }

+ 29 - 18
test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts

@@ -1,3 +1,5 @@
+import 'reflect-metadata';
+
 import * as format from 'string-template';
 
 import { assert } from 'chai';
@@ -6,6 +8,7 @@ import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifi
 
 import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils';
 import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade';
+import { IRandomGenerator } from '../../../../../src/interfaces/utils/IRandomGenerator';
 
 import { AtobTemplate } from '../../../../../src/templates/AtobTemplate';
 import { GlobalVariableTemplate1 } from '../../../../../src/templates/GlobalVariableTemplate1';
@@ -20,30 +23,35 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
     const stringArrayName: string = 'stringArrayName';
     const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
 
-    let cryptUtils: ICryptUtils;
+    let cryptUtils: ICryptUtils,
+        randomGenerator: IRandomGenerator;
 
     before(() => {
         const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
 
         inversifyContainerFacade.load('', {});
         cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
+        randomGenerator = inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
     });
 
     describe('variant #1: `base64` encoding', () => {
-        const atobPolyfill = format(AtobTemplate(), {
-            globalVariableTemplate: GlobalVariableTemplate1()
-        });
-        const atobDecodeNodeTemplate: string = format(StringArrayBase64DecodeNodeTemplate(), {
-            atobPolyfill,
-            selfDefendingCode: '',
-            stringArrayCallsWrapperName
-        });
         const index: string = '0x0';
         const expectedDecodedValue: string = 'test1';
 
         let decodedValue: string;
 
         before(() => {
+            const atobPolyfill = format(AtobTemplate(), {
+                globalVariableTemplate: GlobalVariableTemplate1()
+            });
+            const atobDecodeNodeTemplate: string = format(
+                StringArrayBase64DecodeNodeTemplate(randomGenerator),
+                {
+                    atobPolyfill,
+                    selfDefendingCode: '',
+                    stringArrayCallsWrapperName
+                }
+            );
             const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate: atobDecodeNodeTemplate,
                 stringArrayCallsWrapperName,
@@ -65,15 +73,6 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
     });
 
     describe('variant #2: `rc4` encoding', () => {
-        const atobPolyfill = format(AtobTemplate(), {
-            globalVariableTemplate: GlobalVariableTemplate1()
-        });
-        const rc4DecodeNodeTemplate: string = format(StringArrayRc4DecodeNodeTemplate(), {
-            atobPolyfill,
-            rc4Polyfill: Rc4Template(),
-            selfDefendingCode: '',
-            stringArrayCallsWrapperName
-        });
         const index: string = '0x0';
         const key: string = 'key';
         const expectedDecodedValue: string = 'test1';
@@ -81,6 +80,18 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
         let decodedValue: string;
 
         before(() => {
+            const atobPolyfill = format(AtobTemplate(), {
+                globalVariableTemplate: GlobalVariableTemplate1()
+            });
+            const rc4DecodeNodeTemplate: string = format(
+                StringArrayRc4DecodeNodeTemplate(randomGenerator),
+                {
+                    atobPolyfill,
+                    rc4Polyfill: Rc4Template(),
+                    selfDefendingCode: '',
+                    stringArrayCallsWrapperName
+                }
+            );
             const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate: rc4DecodeNodeTemplate,
                 stringArrayCallsWrapperName,

Some files were not shown because too many files changed in this diff