mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Added ability to add specific node guard to the black list of nodes.
This nodes wont obfuscated.
This commit is contained in:
@@ -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
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+4
-4
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
Vendored
+4
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+24
-8
@@ -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}
|
||||
@@ -214,6 +230,14 @@ export class Node {
|
||||
return node.type === NodeType.UnaryExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isUseStrictOperator (node: ESTree.Node): node is ESTree.ExpressionStatement {
|
||||
return node.type === NodeType.ExpressionStatement && node.directive === 'use strict';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
@@ -229,12 +253,4 @@ export class Node {
|
||||
public static isVariableDeclaratorNode (node: ESTree.Node): node is ESTree.VariableDeclarator {
|
||||
return node.type === NodeType.VariableDeclarator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isNodeHasBlockStatement (node: ESTree.Node): node is TNodeWithBlockStatement {
|
||||
return node.hasOwnProperty('body') && Array.isArray((<TNodeWithBlockStatement>node).body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,7 +15,5 @@ export class ControlFlowStorage extends MapStorage <ICustomNode> {
|
||||
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
|
||||
) {
|
||||
super(randomGenerator);
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+3
-1
@@ -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;
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import * as estraverse from 'estraverse';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
export type TVisitorResult = ESTree.Node | estraverse.VisitorOption | void;
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
export type TNodeGuard = (node: ESTree.Node) => boolean;
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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/;
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
var test = 'abc';
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -52,13 +52,13 @@
|
||||
version "2.2.41"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
|
||||
|
||||
"@types/node@*", "@types/node@8.0.13":
|
||||
version "8.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.13.tgz#530f0f9254209b0335bf5cc6387822594ef47093"
|
||||
"@types/node@*", "@types/node@8.0.14":
|
||||
version "8.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.14.tgz#4a19dc6bb61d16c01cbadc7b30ac23518fff176b"
|
||||
|
||||
"@types/sinon@2.3.2":
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.2.tgz#1e1e99e67162d78e2db17816892bf93bf5209885"
|
||||
"@types/sinon@2.3.3":
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.3.tgz#1f20b96f954b4997a09c1c0a20264aaba6b00147"
|
||||
|
||||
"@types/string-template@1.0.2":
|
||||
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"
|
||||
|
||||
typescript@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc"
|
||||
typescript@2.4.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"
|
||||
|
||||
Reference in New Issue
Block a user