Kaynağa Gözat

Added ability to add specific node guard to the black list of nodes.

This nodes wont obfuscated.
sanex3339 7 yıl önce
ebeveyn
işleme
a3dad6cf94

+ 1 - 0
CHANGELOG.md

@@ -11,6 +11,7 @@ v0.10.0
 * added support for async functions
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/65
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/60
+* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/59
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/54
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/57
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/58

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


+ 4 - 4
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.10.0-beta.8",
+  "version": "0.10.0-beta.9",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -46,8 +46,8 @@
     "@types/md5": "2.1.32",
     "@types/mkdirp": "0.5.0",
     "@types/mocha": "2.2.41",
-    "@types/node": "8.0.13",
-    "@types/sinon": "2.3.2",
+    "@types/node": "8.0.14",
+    "@types/sinon": "2.3.3",
     "@types/string-template": "1.0.2",
     "awesome-typescript-loader": "3.2.1",
     "babel-cli": "6.24.1",
@@ -64,7 +64,7 @@
     "tslint": "5.5.0",
     "tslint-eslint-rules": "4.1.1",
     "tslint-loader": "3.5.3",
-    "typescript": "2.4.1",
+    "typescript": "2.4.2",
     "webpack": "3.3.0",
     "webpack-node-externals": "1.6.0"
   },

+ 35 - 2
src/Obfuscator.ts

@@ -4,9 +4,11 @@ import { ServiceIdentifiers } from './container/ServiceIdentifiers';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
+import { TNodeGuard } from './types/node/TNodeGuard';
 import { TNodeTransformerFactory } from './types/container/node-transformers/TNodeTransformerFactory';
 import { TVisitorDirection } from './types/TVisitorDirection';
 import { TVisitorFunction } from './types/TVisitorFunction';
+import { TVisitorResult } from './types/TVisitorResult';
 
 import { ICustomNodeGroup } from './interfaces/custom-nodes/ICustomNodeGroup';
 import { IObfuscationEventEmitter } from './interfaces/event-emitters/IObfuscationEventEmitter';
@@ -26,6 +28,13 @@ import { NodeUtils } from './node/NodeUtils';
 
 @injectable()
 export class Obfuscator implements IObfuscator {
+    /**
+     * @type {((node: Node) => boolean)[]}
+     */
+    private static readonly blackListGuards: TNodeGuard[] = [
+        Node.isUseStrictOperator
+    ];
+
     /**
      * @type {NodeTransformer[]}
      */
@@ -109,6 +118,26 @@ export class Obfuscator implements IObfuscator {
         this.options = options;
     }
 
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    private static isBlackListNode (node: ESTree.Node): boolean {
+        const guardsLength: number = Obfuscator.blackListGuards.length;
+
+        let guard: TNodeGuard;
+
+        for (let i: number = 0; i < guardsLength; i++) {
+            guard = Obfuscator.blackListGuards[i];
+
+            if (guard(node)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * @param {Program} astTree
      * @returns {Program}
@@ -211,6 +240,10 @@ export class Obfuscator implements IObfuscator {
         let visitor: IVisitor;
 
         return (node: ESTree.Node, parentNode: ESTree.Node) => {
+            if (Obfuscator.isBlackListNode(node)) {
+                return estraverse.VisitorOption.Skip;
+            }
+
             for (let i: number = 0; i < visitorsLength; i++) {
                 visitor = visitors[i];
 
@@ -220,9 +253,9 @@ export class Obfuscator implements IObfuscator {
                     continue;
                 }
 
-                const visitorResult: ESTree.Node | void = visitorFunction(node, parentNode);
+                const visitorResult: TVisitorResult = visitorFunction(node, parentNode);
 
-                if (!visitorResult) {
+                if (!visitorResult || !Node.isNode(visitorResult)) {
                     continue;
                 }
 

+ 5 - 1
src/container/modules/storages/StoragesModule.ts

@@ -33,7 +33,11 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
                 const randomGenerator: IRandomGenerator = context.container
                     .get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
 
-                return new constructor(randomGenerator);
+                const storage: TControlFlowStorage = new constructor(randomGenerator);
+
+                storage.initialize();
+
+                return storage;
             };
         });
 });

+ 4 - 0
src/declarations/ESTree.d.ts

@@ -8,6 +8,10 @@ declare module 'estree' {
         parentNode?: ESTree.Node;
     }
 
+    interface ExpressionStatement extends ESTree.BaseStatement {
+        directive?: 'use strict';
+    }
+
     interface SimpleLiteral extends ESTree.BaseNode, ESTree.BaseExpression {
         'x-verbatim-property'?: any;
     }

+ 6 - 2
src/node-transformers/AbstractNodeTransformer.ts

@@ -1,15 +1,16 @@
-import { injectable, inject } from 'inversify';
+import { injectable, inject, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
+import { IInitializable } from '../interfaces/IInitializable';
 import { INodeTransformer } from '../interfaces/node-transformers/INodeTransformer';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../interfaces/IVisitor';
 
 @injectable()
-export abstract class AbstractNodeTransformer implements INodeTransformer {
+export abstract class AbstractNodeTransformer implements INodeTransformer, IInitializable {
     /**
      * @type {number}
      */
@@ -35,7 +36,10 @@ export abstract class AbstractNodeTransformer implements INodeTransformer {
     ) {
         this.randomGenerator = randomGenerator;
         this.options = options;
+    }
 
+    @postConstruct()
+    public initialize (): void {
         this.nodeIdentifier = this.randomGenerator.getRandomInteger(0, 10000);
     }
 

+ 22 - 6
src/node/Node.ts

@@ -146,6 +146,22 @@ export class Node {
         return node.type === NodeType.MethodDefinition;
     }
 
+    /**
+     * @param {Object} object
+     * @returns {boolean}
+     */
+    public static isNode (object: Object & { type?: string }): object is ESTree.Node {
+        return object && !object.type !== undefined;
+    }
+
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isNodeHasBlockStatement (node: ESTree.Node): node is TNodeWithBlockStatement {
+        return Array.isArray((<TNodeWithBlockStatement>node).body);
+    }
+
     /**
      * @param {Node} node
      * @returns {boolean}
@@ -218,23 +234,23 @@ export class Node {
      * @param {Node} node
      * @returns {boolean}
      */
-    public static isVariableDeclarationNode (node: ESTree.Node): node is ESTree.VariableDeclaration {
-        return node.type === NodeType.VariableDeclaration;
+    public static isUseStrictOperator (node: ESTree.Node): node is ESTree.ExpressionStatement {
+        return node.type === NodeType.ExpressionStatement && node.directive === 'use strict';
     }
 
     /**
      * @param {Node} node
      * @returns {boolean}
      */
-    public static isVariableDeclaratorNode (node: ESTree.Node): node is ESTree.VariableDeclarator {
-        return node.type === NodeType.VariableDeclarator;
+    public static isVariableDeclarationNode (node: ESTree.Node): node is ESTree.VariableDeclaration {
+        return node.type === NodeType.VariableDeclaration;
     }
 
     /**
      * @param {Node} node
      * @returns {boolean}
      */
-    public static isNodeHasBlockStatement (node: ESTree.Node): node is TNodeWithBlockStatement {
-        return node.hasOwnProperty('body') && Array.isArray((<TNodeWithBlockStatement>node).body);
+    public static isVariableDeclaratorNode (node: ESTree.Node): node is ESTree.VariableDeclarator {
+        return node.type === NodeType.VariableDeclarator;
     }
 }

+ 7 - 9
src/storages/ArrayStorage.ts

@@ -1,4 +1,4 @@
-import { injectable, inject } from 'inversify';
+import { injectable, inject, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
@@ -39,6 +39,12 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
         this.randomGenerator = randomGenerator;
     }
 
+    @postConstruct()
+    public initialize (): void {
+        this.storage = [];
+        this.storageId = this.randomGenerator.getRandomString(6);
+    }
+
     /**
      * @param {number} key
      * @returns {T}
@@ -84,14 +90,6 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
         return this.storageId;
     }
 
-    /**
-     * @param {any[]} args
-     */
-    public initialize (...args: any[]): void {
-        this.storage = [];
-        this.storageId = this.randomGenerator.getRandomString(6);
-    }
-
     /**
      * @param {this} storage
      * @param {boolean} mergeId

+ 7 - 9
src/storages/MapStorage.ts

@@ -1,4 +1,4 @@
-import { injectable, inject } from 'inversify';
+import { injectable, inject, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
@@ -34,6 +34,12 @@ export abstract class MapStorage <T> implements IStorage <T> {
         this.randomGenerator = randomGenerator;
     }
 
+    @postConstruct()
+    public initialize (): void {
+        this.storage = new Map <string | number, T>();
+        this.storageId = this.randomGenerator.getRandomString(6);
+    }
+
     /**
      * @param {string | number} key
      * @returns {T}
@@ -83,14 +89,6 @@ export abstract class MapStorage <T> implements IStorage <T> {
         return this.storageId;
     }
 
-    /**
-     * @param {any[]} args
-     */
-    public initialize (...args: any[]): void {
-        this.storage = new Map <string | number, T>();
-        this.storageId = this.randomGenerator.getRandomString(6);
-    }
-
     /**
      * @param {this} storage
      * @param {boolean} mergeId

+ 0 - 2
src/storages/control-flow/ControlFlowStorage.ts

@@ -15,7 +15,5 @@ export class ControlFlowStorage extends MapStorage <ICustomNode> {
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
     ) {
         super(randomGenerator);
-
-        this.initialize();
     }
 }

+ 2 - 3
src/storages/custom-node-group/CustomNodeGroupStorage.ts

@@ -1,4 +1,4 @@
-import { injectable, inject } from 'inversify';
+import { injectable, inject, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import { TCustomNodeGroupFactory } from '../../types/container/custom-nodes/TCustomNodeGroupFactory';
@@ -48,10 +48,9 @@ export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
 
         this.customNodeGroupFactory = customNodeGroupFactory;
         this.options = options;
-
-        this.initialize();
     }
 
+    @postConstruct()
     public initialize (): void {
         this.storage = new Map <string, ICustomNodeGroup>();
         this.storageId = this.randomGenerator.getRandomString(6);

+ 4 - 8
src/storages/string-array/StringArrayStorage.ts

@@ -1,4 +1,4 @@
-import { injectable, inject } from 'inversify';
+import { injectable, inject, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
@@ -25,15 +25,11 @@ export class StringArrayStorage extends ArrayStorage <string> {
         super(randomGenerator);
 
         this.arrayUtils = arrayUtils;
-
-        this.initialize();
     }
 
-    /**
-     * @param {any[]} args
-     */
-    public initialize (...args: any[]): void {
-        super.initialize(args);
+    @postConstruct()
+    public initialize (): void {
+        super.initialize();
 
         this.storageId = this.randomGenerator.getRandomString(4, RandomGenerator.randomGeneratorPoolHexadecimal);
     }

+ 3 - 1
src/types/TVisitorFunction.d.ts

@@ -1,3 +1,5 @@
 import * as ESTree from 'estree';
 
-export type TVisitorFunction = (node: ESTree.Node, parentNode: ESTree.Node | null) => ESTree.Node | void;
+import { TVisitorResult } from './TVisitorResult';
+
+export type TVisitorFunction = (node: ESTree.Node, parentNode: ESTree.Node | null) => TVisitorResult;

+ 4 - 0
src/types/TVisitorResult.d.ts

@@ -0,0 +1,4 @@
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+export type TVisitorResult = ESTree.Node | estraverse.VisitorOption | void;

+ 3 - 0
src/types/node/TNodeGuard.d.ts

@@ -0,0 +1,3 @@
+import * as ESTree from 'estree';
+
+export type TNodeGuard = (node: ESTree.Node) => boolean;

+ 8 - 4
src/utils/RandomGenerator.ts

@@ -1,9 +1,10 @@
-import { inject, injectable } from 'inversify';
+import { inject, injectable, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
 import * as md5 from 'md5';
 import { Chance } from 'chance';
 
+import { IInitializable } from '../interfaces/IInitializable';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 
@@ -11,7 +12,7 @@ import { Utils } from './Utils';
 import { ISourceCode } from '../interfaces/ISourceCode';
 
 @injectable()
-export class RandomGenerator implements IRandomGenerator {
+export class RandomGenerator implements IRandomGenerator, IInitializable {
     /**
      * @type {string}
      */
@@ -40,7 +41,7 @@ export class RandomGenerator implements IRandomGenerator {
     /**
      * @type {Chance.Chance | Chance.SeededChance}
      */
-    private readonly randomGenerator: Chance.Chance | Chance.SeededChance;
+    private randomGenerator: Chance.Chance | Chance.SeededChance;
 
     /**
      * @type {ISourceCode}
@@ -57,8 +58,11 @@ export class RandomGenerator implements IRandomGenerator {
     ) {
         this.sourceCode = sourceCode;
         this.options = options;
+    }
 
-        this.randomGenerator = options.seed === 0
+    @postConstruct()
+    public initialize (): void {
+        this.randomGenerator = this.options.seed === 0
             ? new Chance()
             : new Chance(this.getSeed());
     }

+ 34 - 0
test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts

@@ -439,6 +439,40 @@ describe('JavaScriptObfuscator', () => {
             });
         });
 
+        describe('`\'use strict\';` operator', () => {
+            const useStrictOperatorRegExp: RegExp = /'use *strict';/;
+            const stringArrayLatinRegExp: RegExp = /var _0x(\w){4} *= *\['abc'\];/;
+            const stringArrayCallRegExp: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/;
+
+            let obfuscatedCode: string;
+
+            beforeEach(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/use-strict-operator.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_CUSTOM_NODES_PRESET,
+                        stringArray: true,
+                        stringArrayThreshold: 1
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('match #1: shouldn\'t obfuscate `use strict` operator', () => {
+                assert.match(obfuscatedCode, useStrictOperatorRegExp);
+            });
+
+            it('match #2: should return correct obfuscated code', () => {
+                assert.match(obfuscatedCode, stringArrayLatinRegExp);
+            });
+
+            it('match #3: should return correct obfuscated code', () => {
+                assert.match(obfuscatedCode, stringArrayCallRegExp);
+            });
+        });
+
         describe('mangle', () => {
             const regExp: RegExp = /var *a *= *0x1/;
 

+ 3 - 0
test/functional-tests/javascript-obfuscator/fixtures/use-strict-operator.js

@@ -0,0 +1,3 @@
+'use strict';
+
+var test = 'abc';

+ 1 - 1
tslint.json

@@ -171,7 +171,7 @@
     "typeof-compare": true,
     "unified-signatures": true,
     "use-isnan": true,
-    "valid-jsdoc": [true, {
+    "valid-jsdoc": [false, {
       "requireReturn": false,
       "requireParamDescription": false,
       "requireReturnDescription": false

+ 9 - 9
yarn.lock

@@ -52,13 +52,13 @@
   version "2.2.41"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
 
-"@types/node@*", "@types/[email protected]3":
-  version "8.0.13"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.13.tgz#530f0f9254209b0335bf5cc6387822594ef47093"
+"@types/node@*", "@types/[email protected]4":
+  version "8.0.14"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.14.tgz#4a19dc6bb61d16c01cbadc7b30ac23518fff176b"
 
-"@types/[email protected].2":
-  version "2.3.2"
-  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.2.tgz#1e1e99e67162d78e2db17816892bf93bf5209885"
+"@types/[email protected].3":
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.3.tgz#1f20b96f954b4997a09c1c0a20264aaba6b00147"
 
 "@types/[email protected]":
   version "1.0.2"
@@ -3807,9 +3807,9 @@ typedarray@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
 
[email protected].1:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc"
[email protected].2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844"
 
 uglify-js@^2.6, uglify-js@^2.8.29:
   version "2.8.29"

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