Merge remote-tracking branch 'origin/dev' into dev

Conflicts:
	package.json
This commit is contained in:
sanex3339
2016-11-24 10:23:26 +03:00
107 changed files with 2846 additions and 1488 deletions
+5
View File
@@ -1,5 +1,10 @@
Change Log
===
v0.8.2
---
* New option `seed` sets seed for random generator. This is useful for creating repeatable results.
* IE8 runtime error fix.
v0.8.1
---
* `disableConsoleOutput` option now replaces `console.xxx` functions on empty function instead of infinity loop.
+9 -1
View File
@@ -123,6 +123,7 @@ Following options available for the JS Obfuscator:
disableConsoleOutput: true,
reservedNames: [],
rotateStringArray: true,
seed: 0,
selfDefending: true,
sourceMap: false,
sourceMapBaseUrl: '',
@@ -131,7 +132,7 @@ Following options available for the JS Obfuscator:
stringArray: true,
stringArrayEncoding: false,
stringArrayThreshold: 0.8,
unicdeEscapeSequence: true
unicodeEscapeSequence: true
}
```
@@ -148,6 +149,7 @@ Following options available for the JS Obfuscator:
--disableConsoleOutput <boolean>
--reservedNames <list> (comma separated)
--rotateStringArray <boolean>
--seed <number>
--selfDefending <boolean>
--sourceMap <boolean>
--sourceMapBaseUrl <string>
@@ -218,6 +220,12 @@ Shift the `stringArray` array by a fixed and random (generated at the code obfus
This option is recommended if your original source code isn't small, as the helper function can attract attention.
### `seed`
Type: `number` Default: `0`
This option sets seed for random generator. This is useful for creating repeatable results.
If seed is `0` - random generator will work without seed.
### `selfDefending`
Type: `boolean` Default: `true`
+1399 -715
View File
File diff suppressed because it is too large Load Diff
+11 -10
View File
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.8.1",
"version": "0.8.2",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
@@ -27,27 +27,28 @@
"escodegen": "1.8.1",
"esprima": "3.1.1",
"estraverse": "4.2.0",
"format-unicorn": "1.1.0",
"is-equal": "^1.5.3",
"mkdirp": "0.5.1",
"source-map-support": "0.4.6"
"source-map-support": "0.4.6",
"string-template": "^1.0.0"
},
"devDependencies": {
"@types/chai": "3.4.34",
"@types/chance": "0.7.31",
"@types/commander": "2.3.30",
"@types/commander": "2.3.31",
"@types/escodegen": "0.0.6",
"@types/esprima": "2.1.33",
"@types/estraverse": "0.0.6",
"@types/estree": "0.0.34",
"@types/format-unicorn": "0.0.29",
"@types/joi": "9.0.33",
"@types/mkdirp": "0.3.29",
"@types/mocha": "2.2.33",
"@types/node": "6.0.47",
"@types/sinon": "1.16.31",
"@types/node": "6.0.49",
"@types/sinon": "1.16.32",
"@types/string-template": "^1.0.2",
"awesome-typescript-loader": "2.2.4",
"babel-cli": "6.18.0",
"babel-loader": "6.2.7",
"babel-loader": "6.2.8",
"babel-preset-es2015": "6.18.0",
"chai": "3.5.0",
"coveralls": "2.11.15",
@@ -55,9 +56,9 @@
"mocha": "3.1.2",
"sinon": "2.0.0-pre.3",
"ts-node": "1.7.0",
"tslint": "3.15.1",
"tslint": "4.0.1",
"typescript": "2.0.10",
"webpack": "2.1.0-beta.25",
"webpack": "2.1.0-beta.27",
"webpack-node-externals": "1.5.4"
},
"repository": {
+4 -6
View File
@@ -3,6 +3,7 @@ import { IObfuscatorOptions } from './interfaces/IObfuscatorOptions';
import { JavaScriptObfuscatorCLI } from './cli/JavaScriptObfuscatorCLI';
import { JavaScriptObfuscatorInternal } from './JavaScriptObfuscatorInternal';
import { Options } from './options/Options';
export class JavaScriptObfuscator {
/**
@@ -11,14 +12,11 @@ export class JavaScriptObfuscator {
* @returns {string}
*/
public static obfuscate (sourceCode: string, obfuscatorOptions: IObfuscatorOptions = {}): IObfuscationResult {
let javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal(
sourceCode,
obfuscatorOptions
const javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal(
new Options(obfuscatorOptions)
);
javaScriptObfuscator.obfuscate();
return javaScriptObfuscator.getObfuscationResult();
return javaScriptObfuscator.obfuscate(sourceCode);
}
/**
+33 -26
View File
@@ -2,47 +2,43 @@ import * as esprima from 'esprima';
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
import { IObfuscatorOptions } from './interfaces/IObfuscatorOptions';
import { Chance } from 'chance';
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
import { IObfuscationResult } from './interfaces/IObfuscationResult';
import { IOptions } from './interfaces/IOptions';
import { ObfuscationResult } from './ObfuscationResult';
import { Obfuscator } from './Obfuscator';
import { Options } from './options/Options';
import { SourceMapCorrector } from './SourceMapCorrector';
import { Utils } from './Utils';
export class JavaScriptObfuscatorInternal {
/**
* @type {GenerateOptions}
*/
private static escodegenParams: escodegen.GenerateOptions = {
private static readonly escodegenParams: escodegen.GenerateOptions = {
verbatim: 'x-verbatim-property',
sourceMapWithCode: true
};
/**
* @type {IGeneratorOutput}
* @type {esprima.Options}
*/
private generatorOutput: IGeneratorOutput;
private static readonly esprimaParams: esprima.Options = {
loc: true
};
/**
* @type {IOptions}
*/
private options: IOptions;
private readonly options: IOptions;
/**
* @type {string}
* @param options
*/
private sourceCode: string;
/**
* @param sourceCode
* @param obfuscatorOptions
*/
constructor (sourceCode: string, obfuscatorOptions: IObfuscatorOptions = {}) {
this.sourceCode = sourceCode;
this.options = new Options(obfuscatorOptions);
constructor (options: IOptions) {
this.options = options;
}
/**
@@ -50,7 +46,7 @@ export class JavaScriptObfuscatorInternal {
* @param astTree
* @param options
*/
private static generateCode (sourceCode: string, astTree: ESTree.Node, options: IOptions): IGeneratorOutput {
private static generateCode (sourceCode: string, astTree: ESTree.Program, options: IOptions): IGeneratorOutput {
const escodegenParams: escodegen.GenerateOptions = Object.assign(
{},
JavaScriptObfuscatorInternal.escodegenParams
@@ -73,26 +69,37 @@ export class JavaScriptObfuscatorInternal {
}
/**
* @param generatorOutput
* @returns {IObfuscationResult}
*/
public getObfuscationResult (): IObfuscationResult {
public getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
return new SourceMapCorrector(
new ObfuscationResult(
this.generatorOutput.code,
this.generatorOutput.map
generatorOutput.code,
generatorOutput.map
),
this.options.sourceMapBaseUrl + this.options.sourceMapFileName,
this.options.sourceMapMode
).correct();
}
public obfuscate (): void {
let astTree: ESTree.Node = esprima.parse(this.sourceCode, {
loc: true
});
/**
* @param sourceCode
* @returns {IObfuscationResult}
*/
public obfuscate (sourceCode: string): IObfuscationResult {
if (this.options.seed !== 0) {
Utils.setRandomGenerator(new Chance(this.options.seed));
}
astTree = new Obfuscator(this.options).obfuscateNode(astTree);
const astTree: ESTree.Program = esprima.parse(sourceCode, JavaScriptObfuscatorInternal.esprimaParams);
const obfuscatedAstTree: ESTree.Program = new Obfuscator(this.options).obfuscateAstTree(astTree);
const generatorOutput: IGeneratorOutput = JavaScriptObfuscatorInternal.generateCode(
sourceCode,
obfuscatedAstTree,
this.options
);
this.generatorOutput = JavaScriptObfuscatorInternal.generateCode(this.sourceCode, astTree, this.options);
return this.getObfuscationResult(generatorOutput);
}
}
+57 -76
View File
@@ -2,39 +2,34 @@ import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TNodeGroup } from './types/TNodeGroup';
import { TNodeObfuscator } from './types/TNodeObfuscator';
import { TVisitorDirection } from './types/TVisitorDirection';
import { ICustomNode } from './interfaces/custom-nodes/ICustomNode';
import { IObfuscator } from './interfaces/IObfuscator';
import { IOptions } from './interfaces/IOptions';
import { INodeTransformer } from './interfaces/INodeTransformer';
import { INodeTransformersFactory } from './interfaces/INodeTransformersFactory';
import { IStackTraceData } from './interfaces/stack-trace-analyzer/IStackTraceData';
import { AppendState } from './enums/AppendState';
import { NodeType } from './enums/NodeType';
import { VisitorDirection } from './enums/VisitorDirection';
import { CatchClauseObfuscator } from './node-obfuscators/CatchClauseObfuscator';
import { ConsoleOutputNodesGroup } from './node-groups/ConsoleOutputNodesGroup';
import { DebugProtectionNodesGroup } from './node-groups/DebugProtectionNodesGroup';
import { DomainLockNodesGroup } from './node-groups/DomainLockNodesGroup';
import { FunctionDeclarationObfuscator } from './node-obfuscators/FunctionDeclarationObfuscator';
import { FunctionObfuscator } from './node-obfuscators/FunctionObfuscator';
import { LabeledStatementObfuscator } from './node-obfuscators/LabeledStatementObfuscator';
import { LiteralObfuscator } from './node-obfuscators/LiteralObfuscator';
import { MemberExpressionObfuscator } from './node-obfuscators/MemberExpressionObfuscator';
import { MethodDefinitionObfuscator } from './node-obfuscators/MethodDefinitionObfuscator';
import { Node } from './node/Node';
import { NodeControlFlowTransformersFactory } from './node-transformers/node-control-flow-transformers/factory/NodeControlFlowTransformersFactory';
import { NodeObfuscatorsFactory } from './node-transformers/node-obfuscators/factory/NodeObfuscatorsFactory';
import { NodeUtils } from './node/NodeUtils';
import { ObjectExpressionObfuscator } from './node-obfuscators/ObjectExpressionObfuscator';
import { SelfDefendingNodesGroup } from './node-groups/SelfDefendingNodesGroup';
import { StackTraceAnalyzer } from './stack-trace-analyzer/StackTraceAnalyzer';
import { StringArrayNodesGroup } from './node-groups/StringArrayNodesGroup';
import { VariableDeclarationObfuscator } from './node-obfuscators/VariableDeclarationObfuscator';
export class Obfuscator implements IObfuscator {
/**
* @type {TNodeGroup[]}
*/
private static nodeGroups: TNodeGroup[] = [
private static readonly nodeGroups: TNodeGroup[] = [
DomainLockNodesGroup,
SelfDefendingNodesGroup,
ConsoleOutputNodesGroup,
@@ -42,35 +37,15 @@ export class Obfuscator implements IObfuscator {
StringArrayNodesGroup
];
/**
* @type {Map<string, TNodeObfuscator[]>}
*/
private static nodeObfuscators: Map <string, TNodeObfuscator[]> = new Map <string, TNodeObfuscator[]> ([
[NodeType.ArrowFunctionExpression, [FunctionObfuscator]],
[NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]],
[NodeType.CatchClause, [CatchClauseObfuscator]],
[NodeType.FunctionDeclaration, [
FunctionDeclarationObfuscator,
FunctionObfuscator
]],
[NodeType.FunctionExpression, [FunctionObfuscator]],
[NodeType.MemberExpression, [MemberExpressionObfuscator]],
[NodeType.MethodDefinition, [MethodDefinitionObfuscator]],
[NodeType.ObjectExpression, [ObjectExpressionObfuscator]],
[NodeType.VariableDeclaration, [VariableDeclarationObfuscator]],
[NodeType.LabeledStatement, [LabeledStatementObfuscator]],
[NodeType.Literal, [LiteralObfuscator]]
]);
/**
* @type {Map<string, AbstractCustomNode>}
*/
private customNodes: Map <string, ICustomNode> = new Map <string, ICustomNode> ();
private customNodes: Map <string, ICustomNode>;
/**
* @type {IOptions}
*/
private options: IOptions;
private readonly options: IOptions;
/**
* @param options
@@ -80,34 +55,47 @@ export class Obfuscator implements IObfuscator {
}
/**
* @param node
* @returns {ESTree.Node}
* @param astTree
* @returns {ESTree.Program}
*/
public obfuscateNode (node: ESTree.Program): ESTree.Node {
if (Node.isProgramNode(node) && !node.body.length) {
return node;
public obfuscateAstTree (astTree: ESTree.Program): ESTree.Program {
if (Node.isProgramNode(astTree) && !astTree.body.length) {
return astTree;
}
NodeUtils.parentize(node);
NodeUtils.parentize(astTree);
this.initializeCustomNodes(new StackTraceAnalyzer().analyze(astTree.body));
const stackTraceData: IStackTraceData[] = new StackTraceAnalyzer(node.body).analyze();
// tasks before nodes transformation
this.beforeTransform(astTree);
this.initializeCustomNodes(stackTraceData);
// first pass: control flow flattening
if (this.options.controlFlowFlattening) {
this.transformAstTree(astTree, VisitorDirection.leave, new NodeControlFlowTransformersFactory(
this.customNodes,
this.options
));
}
this.beforeObfuscation(node);
this.obfuscate(node);
this.afterObfuscation(node);
// second pass: nodes obfuscation
this.transformAstTree(astTree, VisitorDirection.enter, new NodeObfuscatorsFactory(
this.customNodes,
this.options
));
return node;
// tasks after nodes transformation
this.afterTransform(astTree);
return astTree;
}
/**
* @param astTree
*/
private afterObfuscation (astTree: ESTree.Node): void {
this.customNodes.forEach((node: ICustomNode) => {
if (node.getAppendState() === AppendState.AfterObfuscation) {
node.appendNode(astTree);
private afterTransform (astTree: ESTree.Program): void {
this.customNodes.forEach((customNode: ICustomNode) => {
if (customNode.getAppendState() === AppendState.AfterObfuscation) {
customNode.appendNode(astTree);
}
});
}
@@ -115,10 +103,10 @@ export class Obfuscator implements IObfuscator {
/**
* @param astTree
*/
private beforeObfuscation (astTree: ESTree.Node): void {
this.customNodes.forEach((node: ICustomNode) => {
if (node.getAppendState() === AppendState.BeforeObfuscation) {
node.appendNode(astTree);
private beforeTransform (astTree: ESTree.Program): void {
this.customNodes.forEach((customNode: ICustomNode) => {
if (customNode.getAppendState() === AppendState.BeforeObfuscation) {
customNode.appendNode(astTree);
}
});
};
@@ -127,7 +115,7 @@ export class Obfuscator implements IObfuscator {
* @param stackTraceData
*/
private initializeCustomNodes (stackTraceData: IStackTraceData[]): void {
let customNodes: [string, ICustomNode][] = [];
const customNodes: [string, ICustomNode][] = [];
Obfuscator.nodeGroups.forEach((nodeGroupConstructor: TNodeGroup) => {
const nodeGroupNodes: Map <string, ICustomNode> | undefined = new nodeGroupConstructor(
@@ -144,30 +132,23 @@ export class Obfuscator implements IObfuscator {
this.customNodes = new Map <string, ICustomNode> (customNodes);
}
/**
* @param node
* @param parentNode
* @param astTree
* @param direction
* @param nodeTransformersFactory
*/
private initializeNodeObfuscators (node: ESTree.Node, parentNode: ESTree.Node): void {
let nodeObfuscators: TNodeObfuscator[] | undefined = Obfuscator.nodeObfuscators.get(node.type);
private transformAstTree (
astTree: ESTree.Program,
direction: TVisitorDirection,
nodeTransformersFactory: INodeTransformersFactory
): void {
estraverse.traverse(astTree, {
[direction]: (node: ESTree.Node, parentNode: ESTree.Node): void => {
const nodeTransformers: INodeTransformer[] = nodeTransformersFactory.initializeNodeTransformers(node.type);
if (!nodeObfuscators) {
return;
}
nodeObfuscators.forEach((obfuscator: TNodeObfuscator) => {
new obfuscator(this.customNodes, this.options).obfuscateNode(node, parentNode);
});
}
/**
* @param node
*/
private obfuscate (node: ESTree.Node): void {
estraverse.traverse(node, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): void => {
this.initializeNodeObfuscators(node, parentNode);
nodeTransformers.forEach((nodeTransformer: INodeTransformer) => {
nodeTransformer.transformNode(node, parentNode);
});
}
});
}
+4 -4
View File
@@ -12,22 +12,22 @@ export class SourceMapCorrector implements ISourceMapCorrector {
/**
* @type {string}
*/
private obfuscatedCode: string;
private readonly obfuscatedCode: string;
/**
* @type {string}
*/
private sourceMap: string;
private readonly sourceMap: string;
/**
* @type {TSourceMapMode}
*/
private sourceMapMode: TSourceMapMode;
private readonly sourceMapMode: TSourceMapMode;
/**
* @type {string}
*/
private sourceMapUrl: string;
private readonly sourceMapUrl: string;
/**
* @param obfuscationResult
-53
View File
@@ -1,53 +0,0 @@
import { Utils } from './Utils';
export class StringArray {
/**
* @type {string[]}
*/
private array: string[] = [];
/**
* @param value
*/
public addToArray (value: string): void {
this.array.push(value);
}
/**
* @returns {string[]}
*/
public getArray (): string[] {
return this.array;
}
/**
* @param value
* @returns {number}
*/
public getIndexOf(value: string): number {
return this.array.indexOf(value);
}
/**
* @returns {number}
*/
public getLength (): number {
return this.array.length;
}
/**
* @param rotationValue
*/
public rotateArray (rotationValue: number): void {
this.array = Utils.arrayRotate(this.array, rotationValue);
}
/**
* @returns {string}
*/
public toString (): string {
return this.array.map((value: string) => {
return `'${value}'`;
}).toString()
}
}
+73 -13
View File
@@ -2,11 +2,18 @@ import { Chance } from 'chance';
import { JSFuck } from './enums/JSFuck';
const isEqual = require('is-equal');
export class Utils {
/**
* @type {Chance.Chance}
* @type {string}
*/
private static randomGenerator: Chance.Chance = new Chance();
public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
/**
* @type {Chance.Chance | Chance.SeededChance}
*/
private static randomGenerator: Chance.Chance | Chance.SeededChance = new Chance();
/**
* @param array
@@ -99,13 +106,44 @@ export class Utils {
return domain;
}
/**
* @param min
* @param max
* @returns {number}
*/
public static getRandomFloat (min: number, max: number): number {
return Utils.getRandomGenerator().floating({
min: min,
max: max,
fixed: 7
});
}
/**
* @returns {Chance.Chance}
*/
public static getRandomGenerator (): Chance.Chance {
const randomGenerator: Chance.Chance = Utils.randomGenerator;
if (!randomGenerator) {
throw new Error(`\`randomGenerator\` static property is undefined`);
}
return Utils.randomGenerator;
}
/**
* @param min
* @param max
* @returns {number}
*/
public static getRandomInteger (min: number, max: number): number {
return Utils.getRandomGenerator().integer({
min: min,
max: max
});
}
/**
* @param length
* @returns {string}
@@ -117,10 +155,7 @@ export class Utils {
return `${prefix}${(
Utils.decToHex(
Utils.getRandomGenerator().integer({
min: rangeMinInteger,
max: rangeMaxInteger
})
Utils.getRandomInteger(rangeMinInteger, rangeMaxInteger)
)
).substr(0, length)}`;
}
@@ -140,7 +175,7 @@ export class Utils {
result: string = '';
while (i1 < s1.length || i2 < s2.length) {
if (Math.random() < 0.5 && i2 < s2.length) {
if (Utils.getRandomFloat(0, 1) < 0.5 && i2 < s2.length) {
result += s2.charAt(++i2);
} else {
result += s1.charAt(++i1);
@@ -150,13 +185,16 @@ export class Utils {
return result;
};
const customPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const randomString: string = Utils.randomGenerator.string({
length: length,
pool: Utils.randomGeneratorPool
});
let randomString: string = Utils.randomGenerator.string({length: length, pool: customPool}),
randomStringDiff: string = randomString.replace(
new RegExp('[' + escapeRegExp(str) + ']', 'g'),
''),
randomStringDiffArray: string[] = randomStringDiff.split('');
let randomStringDiff: string = randomString.replace(
new RegExp('[' + escapeRegExp(str) + ']', 'g'),
'');
const randomStringDiffArray: string[] = randomStringDiff.split('');
Utils.randomGenerator.shuffle(randomStringDiffArray);
randomStringDiff = randomStringDiffArray.join('');
@@ -173,6 +211,21 @@ export class Utils {
return number % 1 === 0;
}
/**
* @param map
* @param value
* @returns {any}
*/
public static mapGetFirstKeyOf(map: Map <any, any>, value: any): any {
for (var [key, storageValue] of map) {
if (isEqual(value, storageValue)) {
return key;
}
}
return null;
}
/**
* RC4 symmetric cipher encryption/decryption
* https://gist.github.com/farhadi/2185197
@@ -213,6 +266,13 @@ export class Utils {
return result;
}
/**
* @param randomGenerator
*/
public static setRandomGenerator (randomGenerator: Chance.Chance | Chance.SeededChance): void {
Utils.randomGenerator = randomGenerator;
}
/**
* @param obj
* @returns {T}
+2 -2
View File
@@ -10,14 +10,14 @@ export class CLIUtils {
/**
* @type {string[]}
*/
private static availableInputExtensions: string[] = [
private static readonly availableInputExtensions: string[] = [
'.js'
];
/**
* @type {BufferEncoding}
*/
private static encoding: BufferEncoding = 'utf8';
private static readonly encoding: BufferEncoding = 'utf8';
/**
* @param outputPath
+10 -8
View File
@@ -19,7 +19,7 @@ export class JavaScriptObfuscatorCLI {
/**
* @type {string[]}
*/
private arguments: string[];
private readonly arguments: string[];
/**
* @type {commander.ICommand}
@@ -69,7 +69,7 @@ export class JavaScriptObfuscatorCLI {
* @returns {string}
*/
private static parseSourceMapMode (value: string): string {
let availableMode: boolean = Object
const availableMode: boolean = Object
.keys(SourceMapMode)
.some((key: string): boolean => {
return SourceMapMode[key] === value;
@@ -121,8 +121,8 @@ export class JavaScriptObfuscatorCLI {
* @returns {IObfuscatorOptions}
*/
private buildOptions (): IObfuscatorOptions {
let obfuscatorOptions: IObfuscatorOptions = {},
availableOptions: string[] = Object.keys(DEFAULT_PRESET);
const obfuscatorOptions: IObfuscatorOptions = {};
const availableOptions: string[] = Object.keys(DEFAULT_PRESET);
for (const option in this.commands) {
if (!this.commands.hasOwnProperty(option)) {
@@ -145,12 +145,14 @@ export class JavaScriptObfuscatorCLI {
.usage('<inputPath> [options]')
.option('-o, --output <path>', 'Output path for obfuscated code')
.option('--compact <boolean>', 'Disable one line output code compacting', JavaScriptObfuscatorCLI.parseBoolean)
.option('--controlFlowFlattening <boolean>', 'Enables control flow flattening', JavaScriptObfuscatorCLI.parseBoolean)
.option('--debugProtection <boolean>', 'Disable browser Debug panel (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean)
.option('--debugProtectionInterval <boolean>', 'Disable browser Debug panel even after page was loaded (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean)
.option('--disableConsoleOutput <boolean>', 'Allow console.log, console.info, console.error and console.warn messages output into browser console', JavaScriptObfuscatorCLI.parseBoolean)
.option('--domainLock <list>', 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)', (val: string) => val.split(','))
.option('--reservedNames <list>', 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)', (val: string) => val.split(','))
.option('--rotateStringArray <boolean>', 'Disable rotation of unicode array values during obfuscation', JavaScriptObfuscatorCLI.parseBoolean)
.option('--seed <number>', 'Sets seed for random generator. This is useful for creating repeatable results.', parseFloat)
.option('--selfDefending <boolean>', 'Disables self-defending for obfuscated code', JavaScriptObfuscatorCLI.parseBoolean)
.option('--sourceMap <boolean>', 'Enables source map generation', JavaScriptObfuscatorCLI.parseBoolean)
.option('--sourceMapBaseUrl <string>', 'Sets base url to the source map import url when `--sourceMapMode=separate`')
@@ -179,8 +181,8 @@ export class JavaScriptObfuscatorCLI {
}
private processData (): void {
let options: IObfuscatorOptions = this.buildOptions(),
outputCodePath: string = CLIUtils.getOutputCodePath((<any>this.commands).output, this.inputPath);
const options: IObfuscatorOptions = this.buildOptions();
const outputCodePath: string = CLIUtils.getOutputCodePath((<any>this.commands).output, this.inputPath);
if (options.sourceMap) {
this.processDataWithSourceMap(outputCodePath, options);
@@ -194,7 +196,7 @@ export class JavaScriptObfuscatorCLI {
* @param options
*/
private processDataWithoutSourceMap (outputCodePath: string, options: IObfuscatorOptions): void {
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.data, options).getObfuscatedCode();
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.data, options).getObfuscatedCode();
CLIUtils.writeFile(outputCodePath, obfuscatedCode);
}
@@ -204,7 +206,7 @@ export class JavaScriptObfuscatorCLI {
* @param options
*/
private processDataWithSourceMap (outputCodePath: string, options: IObfuscatorOptions): void {
let outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
outputCodePath,
options.sourceMapFileName || ''
);
+10 -2
View File
@@ -5,6 +5,7 @@ import { IOptions } from '../interfaces/IOptions';
import { TStatement } from '../types/TStatement';
import { AppendState } from '../enums/AppendState';
import { NodeUtils } from '../node/NodeUtils';
export abstract class AbstractCustomNode implements ICustomNode {
/**
@@ -15,7 +16,7 @@ export abstract class AbstractCustomNode implements ICustomNode {
/**
* @type {IOptions}
*/
protected options: IOptions;
protected readonly options: IOptions;
/**
* @param options
@@ -36,6 +37,11 @@ export abstract class AbstractCustomNode implements ICustomNode {
return this.appendState;
}
/**
* @returns {string}
*/
public abstract getCode (): string;
/**
* @returns {TStatement[]}
*/
@@ -53,5 +59,7 @@ export abstract class AbstractCustomNode implements ICustomNode {
/**
* @returns {TStatement[]}
*/
protected abstract getNodeStructure (): TStatement[];
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(this.getCode());
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
import { IStackTraceData } from '../../interfaces/stack-trace-analyzer/IStackTraceData';
@@ -12,7 +11,6 @@ import { ConsoleOutputDisableExpressionTemplate } from '../../templates/custom-n
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { Utils } from '../../Utils';
export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
@@ -68,27 +66,12 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
}
/**
* JSCrush version of following code
*
* (function () {
* var _console = []["filter"]["constructor"]("return this")().console;
* var _function = function () {};
*
* _console.log = _function;
* _console.info = _function;
* _console.warn = _function;
* _console.error = _function;
* _console
* })();
*
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
ConsoleOutputDisableExpressionTemplate().formatUnicorn({
consoleLogDisableFunctionName: Utils.getRandomVariableName(),
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
})
);
public getCode (): string {
return format(ConsoleOutputDisableExpressionTemplate(), {
consoleLogDisableFunctionName: Utils.getRandomVariableName(),
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
});
}
}
@@ -0,0 +1,49 @@
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../../types/TNodeWithBlockStatement';
import { IOptions } from '../../../interfaces/IOptions';
import { AppendState } from '../../../enums/AppendState';
import { BinaryExpressionFunctionTemplate } from '../../../templates/custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionTemplate';
import { AbstractCustomNode } from '../../AbstractCustomNode';
import { Utils } from '../../../Utils';
export class BinaryExpressionFunctionNode extends AbstractCustomNode {
/**
* @type {AppendState}
*/
protected appendState: AppendState = AppendState.BeforeObfuscation;
/**
* @type {string}
*/
private operator: string;
/**
* @param operator
* @param options
*/
constructor (operator: string, options: IOptions) {
super(options);
this.operator = operator;
}
/**
* @param blockScopeNode
*/
public appendNode (blockScopeNode: TNodeWithBlockStatement): void {}
/**
* @returns {string}
*/
public getCode (): string {
return format(BinaryExpressionFunctionTemplate(), {
functionName: Utils.getRandomVariableName(1),
operator: this.operator
});
}
}
@@ -0,0 +1,80 @@
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../../types/TNodeWithBlockStatement';
import { IOptions } from '../../../interfaces/IOptions';
import { AppendState } from '../../../enums/AppendState';
import { ControlFlowStorageCallTemplate } from '../../../templates/custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/ControlFlowStorageCallTemplate';
import { AbstractCustomNode } from '../../AbstractCustomNode';
import { NodeAppender } from '../../../node/NodeAppender';
export class ControlFlowStorageCallNode extends AbstractCustomNode {
/**
* @type {AppendState}
*/
protected appendState: AppendState = AppendState.AfterObfuscation;
/**
* @type {string}
*/
private controlFlowStorageKey: string;
/**
* @type {string}
*/
private controlFlowStorageName: string;
/**
* @type {string}
*/
private leftValue: string;
/**
* @type {string}
*/
private rightValue: string;
/**
* @param controlFlowStorageName
* @param controlFlowStorageKey
* @param leftValue
* @param rightValue
* @param options
*/
constructor (
controlFlowStorageName: string,
controlFlowStorageKey: string,
leftValue: string,
rightValue: string,
options: IOptions
) {
super(options);
this.controlFlowStorageName = controlFlowStorageName;
this.controlFlowStorageKey = controlFlowStorageKey;
this.leftValue = leftValue;
this.rightValue = rightValue;
}
/**
* @param blockScopeNode
*/
public appendNode (blockScopeNode: TNodeWithBlockStatement): void {
NodeAppender.prependNode(blockScopeNode, this.getNode());
}
/**
* @returns {string}
*/
public getCode (): string {
return format(ControlFlowStorageCallTemplate(), {
controlFlowStorageKey: this.controlFlowStorageKey,
controlFlowStorageName: this.controlFlowStorageName,
leftValue: this.leftValue,
rightValue: this.rightValue
});
}
}
@@ -0,0 +1,64 @@
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { IStorage } from '../../interfaces/IStorage';
import { AppendState } from '../../enums/AppendState';
import { ControlFlowStorageTemplate } from '../../templates/custom-nodes/control-flow-storage-nodes/ControlFlowStorageTemplate';
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
export class ControlFlowStorageNode extends AbstractCustomNode {
/**
* @type {AppendState}
*/
protected appendState: AppendState = AppendState.AfterObfuscation;
/**
* @type {IStorage <ICustomNode>}
*/
private controlFlowStorage: IStorage <ICustomNode>;
/**
* @type {string}
*/
private controlFlowStorageName: string;
/**
* @param controlFlowStorage
* @param controlFlowStorageName
* @param options
*/
constructor (
controlFlowStorage: IStorage <ICustomNode>,
controlFlowStorageName: string,
options: IOptions
) {
super(options);
this.controlFlowStorage = controlFlowStorage;
this.controlFlowStorageName = controlFlowStorageName;
}
/**
* @param blockScopeNode
*/
public appendNode (blockScopeNode: TNodeWithBlockStatement): void {
NodeAppender.prependNode(blockScopeNode, this.getNode());
}
/**
* @returns {string}
*/
public getCode (): string {
return format(ControlFlowStorageTemplate(), {
controlFlowStorage: this.controlFlowStorage.toString(),
controlFlowStorageName: this.controlFlowStorageName
});
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
@@ -11,7 +10,6 @@ import { DebugProtectionFunctionCallTemplate } from '../../templates/custom-node
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
/**
@@ -42,13 +40,11 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
DebugProtectionFunctionCallTemplate().formatUnicorn({
debugProtectionFunctionName: this.debugProtectionFunctionName
})
);
public getCode (): string {
return format(DebugProtectionFunctionCallTemplate(), {
debugProtectionFunctionName: this.debugProtectionFunctionName
});
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
@@ -11,7 +10,6 @@ import { DebugProtectionFunctionIntervalTemplate } from '../../templates/custom-
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
/**
@@ -42,13 +40,11 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
DebugProtectionFunctionIntervalTemplate().formatUnicorn({
debugProtectionFunctionName: this.debugProtectionFunctionName
})
);
public getCode (): string {
return format(DebugProtectionFunctionIntervalTemplate(), {
debugProtectionFunctionName: this.debugProtectionFunctionName
});
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
@@ -11,7 +10,6 @@ import { DebugProtectionFunctionTemplate } from '../../templates/custom-nodes/de
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { Utils } from '../../Utils';
export class DebugProtectionFunctionNode extends AbstractCustomNode {
@@ -40,10 +38,7 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
*/
public appendNode (blockScopeNode: TNodeWithBlockStatement): void {
let programBodyLength: number = blockScopeNode.body.length,
randomIndex: number = Utils.getRandomGenerator().integer({
min: 0,
max: programBodyLength
});
randomIndex: number = Utils.getRandomInteger(0, programBodyLength);
NodeAppender.insertNodeAtIndex(blockScopeNode, this.getNode(), randomIndex);
}
@@ -51,20 +46,9 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
/**
* @returns {string}
*/
public getNodeIdentifier (): string {
return this.debugProtectionFunctionName;
}
/**
* Found this trick in JScrambler
*
* @returns {TStatement[]}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
DebugProtectionFunctionTemplate().formatUnicorn({
debugProtectionFunctionName: this.debugProtectionFunctionName
})
);
public getCode (): string {
return format(DebugProtectionFunctionTemplate(), {
debugProtectionFunctionName: this.debugProtectionFunctionName
});
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
import { IStackTraceData } from '../../interfaces/stack-trace-analyzer/IStackTraceData';
@@ -12,7 +11,6 @@ import { DomainLockNodeTemplate } from '../../templates/custom-nodes/domain-lock
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { Utils } from '../../Utils';
export class DomainLockNode extends AbstractCustomNode {
@@ -68,19 +66,17 @@ export class DomainLockNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
public getCode (): string {
let domainsString: string = this.options.domainLock.join(';'),
[hiddenDomainsString, diff]: string[] = Utils.hideString(domainsString, domainsString.length * 3);
return NodeUtils.convertCodeToStructure(
DomainLockNodeTemplate().formatUnicorn({
domainLockFunctionName: Utils.getRandomVariableName(),
diff: diff,
domains: hiddenDomainsString,
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
})
);
return format(DomainLockNodeTemplate(), {
domainLockFunctionName: Utils.getRandomVariableName(),
diff: diff,
domains: hiddenDomainsString,
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
});
}
}
@@ -1,7 +1,6 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
import { IStackTraceData } from '../../interfaces/stack-trace-analyzer/IStackTraceData';
@@ -15,7 +14,6 @@ import { NO_CUSTOM_NODES_PRESET } from '../../preset-options/NoCustomNodesPreset
import { AbstractCustomNode } from '../AbstractCustomNode';
import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
/**
@@ -74,21 +72,22 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
public getCode (): string {
if (this.appendState === AppendState.AfterObfuscation) {
return NodeUtils.convertCodeToStructure(
JavaScriptObfuscator.obfuscate(SingleNodeCallControllerTemplate().formatUnicorn({
return JavaScriptObfuscator.obfuscate(
format(SingleNodeCallControllerTemplate(), {
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
}), NO_CUSTOM_NODES_PRESET).getObfuscatedCode()
);
}),
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
seed: this.options.seed
})
).getObfuscatedCode();
}
return NodeUtils.convertCodeToStructure(
SingleNodeCallControllerTemplate().formatUnicorn({
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
})
);
return format(SingleNodeCallControllerTemplate(), {
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
});
}
}
@@ -1,5 +1,6 @@
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
import { IStackTraceData } from '../../interfaces/stack-trace-analyzer/IStackTraceData';
@@ -13,7 +14,6 @@ import { SelfDefendingTemplate } from '../../templates/custom-nodes/self-defendi
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
import { NodeUtils } from '../../node/NodeUtils';
import { Utils } from '../../Utils';
export class SelfDefendingUnicodeNode extends AbstractCustomNode {
@@ -69,17 +69,17 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
JavaScriptObfuscator.obfuscate(
SelfDefendingTemplate().formatUnicorn({
selfDefendingFunctionName: Utils.getRandomVariableName(),
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
}),
NO_CUSTOM_NODES_PRESET
).getObfuscatedCode()
);
public getCode (): string {
return JavaScriptObfuscator.obfuscate(
format(SelfDefendingTemplate(), {
selfDefendingFunctionName: Utils.getRandomVariableName(),
singleNodeCallControllerFunctionName: this.callsControllerFunctionName
}),
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
seed: this.options.seed
})
).getObfuscatedCode();
}
}
@@ -1,9 +1,11 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
import { IOptions } from '../../interfaces/IOptions';
import { IStorage } from '../../interfaces/IStorage';
import { AppendState } from '../../enums/AppendState';
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
@@ -20,19 +22,17 @@ import { StringArrayRc4DecodeNodeTemplate } from '../../templates/custom-nodes/s
import { AbstractCustomNode } from '../AbstractCustomNode';
import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { StringArray } from '../../StringArray';
export class StringArrayCallsWrapper extends AbstractCustomNode {
export class StringArrayCallsWrapper extends AbstractCustomNode implements ICustomNodeWithIdentifier {
/**
* @type {AppendState}
*/
protected appendState: AppendState = AppendState.AfterObfuscation;
/**
* @type {StringArray}
* @type {IStorage <string>}
*/
private stringArray: StringArray;
private stringArray: IStorage <string>;
/**
* @type {string}
@@ -53,7 +53,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
constructor (
stringArrayCallsWrapperName: string,
stringArrayName: string,
stringArray: StringArray,
stringArray: IStorage <string>,
options: IOptions
) {
super(options);
@@ -74,6 +74,24 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
NodeAppender.insertNodeAtIndex(blockScopeNode, this.getNode(), 1);
}
/**
* @returns {string}
*/
public getCode (): string {
const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
return JavaScriptObfuscator.obfuscate(
format(StringArrayCallsWrapperTemplate(), {
decodeNodeTemplate,
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
stringArrayName: this.stringArrayName
}),
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
seed: this.options.seed
})
).getObfuscatedCode();
}
/**
* @returns {string}
*/
@@ -96,7 +114,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
selfDefendingCode: string = '';
if (this.options.selfDefending) {
selfDefendingCode = SelfDefendingTemplate().formatUnicorn({
selfDefendingCode = format(SelfDefendingTemplate(), {
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
stringArrayName: this.stringArrayName
});
@@ -104,7 +122,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
switch (this.options.stringArrayEncoding) {
case StringArrayEncoding.base64:
decodeStringArrayTemplate = StringArrayBase64DecodeNodeTemplate().formatUnicorn({
decodeStringArrayTemplate = format(StringArrayBase64DecodeNodeTemplate(), {
atobPolyfill: AtobTemplate(),
selfDefendingCode,
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
@@ -113,7 +131,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
break;
case StringArrayEncoding.rc4:
decodeStringArrayTemplate = StringArrayRc4DecodeNodeTemplate().formatUnicorn({
decodeStringArrayTemplate = format(StringArrayRc4DecodeNodeTemplate(), {
atobPolyfill: AtobTemplate(),
rc4Polyfill: Rc4Template(),
selfDefendingCode,
@@ -125,22 +143,4 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
return decodeStringArrayTemplate;
}
/**
* @returns {TStatement[]}
*/
protected getNodeStructure (): TStatement[] {
const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
return NodeUtils.convertCodeToStructure(
JavaScriptObfuscator.obfuscate(
StringArrayCallsWrapperTemplate().formatUnicorn({
decodeNodeTemplate,
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
stringArrayName: this.stringArrayName
}),
NO_CUSTOM_NODES_PRESET
).getObfuscatedCode()
);
}
}
@@ -1,21 +1,21 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { ICustomNodeWithData } from '../../interfaces/custom-nodes/ICustomNodeWithData';
import { IOptions } from '../../interfaces/IOptions';
import { IStorage } from '../../interfaces/IStorage';
import { AppendState } from '../../enums/AppendState';
import { StringArray } from '../../StringArray';
import { StringArrayTemplate } from '../../templates/custom-nodes/string-array-nodes/string-array-node/StringArrayTemplate';
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { StringArrayStorage } from '../../storages/string-array/StringArrayStorage';
export class StringArrayNode extends AbstractCustomNode {
export class StringArrayNode extends AbstractCustomNode implements ICustomNodeWithData {
/**
* @type {number}
*/
@@ -27,9 +27,9 @@ export class StringArrayNode extends AbstractCustomNode {
protected appendState: AppendState = AppendState.AfterObfuscation;
/**
* @type {StringArray}
* @type {IStorage <string>}
*/
private stringArray: StringArray;
private stringArray: IStorage <string>;
/**
* @type {string}
@@ -48,7 +48,7 @@ export class StringArrayNode extends AbstractCustomNode {
* @param options
*/
constructor (
stringArray: StringArray,
stringArray: IStorage <string>,
stringArrayName: string,
stringArrayRotateValue: number = 0,
options: IOptions
@@ -74,14 +74,17 @@ export class StringArrayNode extends AbstractCustomNode {
/**
* @returns {string}
*/
public getNodeIdentifier (): string {
return this.stringArrayName;
public getCode (): string {
return format(StringArrayTemplate(), {
stringArrayName: this.stringArrayName,
stringArray: this.stringArray.toString()
});
}
/**
* @returns {StringArray}
* @returns {IStorage <string>}
*/
public getNodeData (): StringArray {
public getNodeData (): IStorage <string> {
return this.stringArray;
}
@@ -89,27 +92,8 @@ export class StringArrayNode extends AbstractCustomNode {
* @returns {TStatement[]}
*/
public getNode (): TStatement[] {
this.stringArray.rotateArray(this.stringArrayRotateValue);
(<StringArrayStorage>this.stringArray).rotateArray(this.stringArrayRotateValue);
return super.getNode();
}
/**
* @param data
*/
public updateNodeData (data: string): void {
this.stringArray.addToArray(data);
}
/**
* @returns {TStatement[]}
*/
protected getNodeStructure (): TStatement[] {
return NodeUtils.convertCodeToStructure(
StringArrayTemplate().formatUnicorn({
stringArrayName: this.stringArrayName,
stringArray: this.stringArray.toString()
})
);
}
}
@@ -1,9 +1,9 @@
import 'format-unicorn';
import * as format from 'string-template';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { TStatement } from '../../types/TStatement';
import { IOptions } from '../../interfaces/IOptions';
import { IStorage } from '../../interfaces/IStorage';
import { AppendState } from '../../enums/AppendState';
@@ -15,8 +15,6 @@ import { StringArrayRotateFunctionTemplate } from '../../templates/custom-nodes/
import { AbstractCustomNode } from '../AbstractCustomNode';
import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeUtils } from '../../node/NodeUtils';
import { StringArray } from '../../StringArray';
import { Utils } from '../../Utils';
export class StringArrayRotateFunctionNode extends AbstractCustomNode {
@@ -26,9 +24,9 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
protected appendState: AppendState = AppendState.AfterObfuscation;
/**
* @type {StringArray}
* @type {IStorage <string>}
*/
private stringArray: StringArray;
private stringArray: IStorage <string>;
/**
* @type {string}
@@ -48,7 +46,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
*/
constructor (
stringArrayName: string,
stringArray: StringArray,
stringArray: IStorage <string>,
stringArrayRotateValue: number,
options: IOptions
) {
@@ -71,22 +69,15 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
}
/**
* @returns {TStatement[]}
* @returns {string}
*/
public getNode (): TStatement[] {
return super.getNode();
}
/**
* @returns {TStatement[]}
*/
protected getNodeStructure (): TStatement[] {
public getCode (): string {
let code: string = '',
timesName: string = Utils.getRandomVariableName(),
whileFunctionName: string = Utils.getRandomVariableName();
if (this.options.selfDefending) {
code = SelfDefendingTemplate().formatUnicorn({
code = format(SelfDefendingTemplate(), {
timesName,
whileFunctionName
});
@@ -94,17 +85,17 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
code = `${whileFunctionName}(++${timesName})`;
}
return NodeUtils.convertCodeToStructure(
JavaScriptObfuscator.obfuscate(
StringArrayRotateFunctionTemplate().formatUnicorn({
code,
timesName,
stringArrayName: this.stringArrayName,
stringArrayRotateValue: Utils.decToHex(this.stringArrayRotateValue),
whileFunctionName
}),
NO_CUSTOM_NODES_PRESET
).getObfuscatedCode()
);
return JavaScriptObfuscator.obfuscate(
format(StringArrayRotateFunctionTemplate(), {
code,
timesName,
stringArrayName: this.stringArrayName,
stringArrayRotateValue: Utils.decToHex(this.stringArrayRotateValue),
whileFunctionName
}),
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
seed: this.options.seed
})
).getObfuscatedCode();
}
}
-2
View File
@@ -1,6 +1,4 @@
export const JSFuck: any = {
Window: '[]["filter"]["constructor"]("return this")()',
False: '![]',
True: '!![]',
+6
View File
@@ -0,0 +1,6 @@
import { Utils } from '../Utils';
export const VisitorDirection: any = Utils.strEnumify({
enter: 'enter',
leave: 'leave'
});
+13
View File
@@ -0,0 +1,13 @@
import * as ESTree from 'estree';
import { ICustomNode } from './custom-nodes/ICustomNode';
import { IStorage } from './IStorage';
export interface IControlFlowReplacer {
replace (
node: ESTree.Node,
parentNode: ESTree.Node,
controlFlowStorage: IStorage <ICustomNode>,
controlFlowStorageCustomNodeName: string
): ICustomNode | undefined;
}
-9
View File
@@ -1,9 +0,0 @@
import * as ESTree from 'estree';
export interface INodeObfuscator {
/**
* @param node
* @param parentNode
*/
obfuscateNode (node: ESTree.Node, parentNode?: ESTree.Node): void;
}
+5
View File
@@ -0,0 +1,5 @@
import * as ESTree from 'estree';
export interface INodeTransformer {
transformNode (node: ESTree.Node, parentNode?: ESTree.Node): void;
}
+5
View File
@@ -0,0 +1,5 @@
import { INodeTransformer } from './INodeTransformer';
export interface INodeTransformersFactory {
initializeNodeTransformers (nodeType: string): INodeTransformer[];
}
+1 -1
View File
@@ -1,5 +1,5 @@
import * as ESTree from 'estree';
export interface IObfuscator {
obfuscateNode (node: ESTree.Node): ESTree.Node;
obfuscateAstTree (node: ESTree.Program): ESTree.Program;
}
+2
View File
@@ -3,12 +3,14 @@ import { TStringArrayEncoding } from '../types/TStringArrayEncoding';
export interface IObfuscatorOptions {
compact?: boolean;
controlFlowFlattening?: boolean;
debugProtection?: boolean;
debugProtectionInterval?: boolean;
disableConsoleOutput?: boolean;
domainLock?: string[];
reservedNames?: string[];
rotateStringArray?: boolean;
seed?: number;
selfDefending?: boolean;
sourceMap?: boolean;
sourceMapBaseUrl?: string;
+2
View File
@@ -3,12 +3,14 @@ import { TStringArrayEncoding } from '../types/TStringArrayEncoding';
export interface IOptions {
readonly compact: boolean;
readonly controlFlowFlattening: boolean;
readonly debugProtection: boolean;
readonly debugProtectionInterval: boolean;
readonly disableConsoleOutput: boolean;
readonly domainLock: string[];
readonly reservedNames: string[];
readonly rotateStringArray: boolean;
readonly seed: number;
readonly selfDefending: boolean;
readonly sourceMap: boolean;
readonly sourceMapBaseUrl: string;
+8
View File
@@ -0,0 +1,8 @@
export interface IStorage <T> {
get (key: string | number): T;
getKeyOf (value: T): string | number | null;
getLength (): number;
getStorage (): any;
set (key: string | number | null, value: T): void;
toString (): string;
}
+5
View File
@@ -15,6 +15,11 @@ export interface ICustomNode {
*/
getAppendState (): AppendState;
/**
* @returns {string}
*/
getCode (): string;
/**
* @returns ESTree.Node[]
*/
-5
View File
@@ -5,9 +5,4 @@ export interface ICustomNodeWithData extends ICustomNode {
* @returns any
*/
getNodeData (): any;
/**
* @param data
*/
updateNodeData (data: any): void;
}
@@ -1,5 +1,7 @@
import * as ESTree from 'estree';
import { IStackTraceData } from './IStackTraceData';
export interface IStackTraceAnalyzer {
analyze (): IStackTraceData[];
analyze (blockScopeBody: ESTree.Node[]): IStackTraceData[];
}
+3 -3
View File
@@ -9,17 +9,17 @@ export abstract class AbstractNodesGroup implements INodesGroup {
/**
* @type {AppendState}
*/
protected appendState: AppendState = AppendState.BeforeObfuscation;
protected readonly appendState: AppendState = AppendState.BeforeObfuscation;
/**
* @type {IStackTraceData[]}
*/
protected stackTraceData: IStackTraceData[];
protected readonly stackTraceData: IStackTraceData[];
/**
* @type {IOptions}
*/
protected options: IOptions;
protected readonly options: IOptions;
/**
* @param stackTraceData
+4 -6
View File
@@ -7,8 +7,9 @@ import { StringArrayNode } from '../custom-nodes/string-array-nodes/StringArrayN
import { StringArrayRotateFunctionNode } from '../custom-nodes/string-array-nodes/StringArrayRotateFunctionNode';
import { AbstractNodesGroup } from './AbstractNodesGroup';
import { StringArray } from '../StringArray';
import { StringArrayStorage } from '../storages/string-array/StringArrayStorage';
import { Utils } from '../Utils';
import { IStorage } from '../interfaces/IStorage';
export class StringArrayNodesGroup extends AbstractNodesGroup {
/**
@@ -40,15 +41,12 @@ export class StringArrayNodesGroup extends AbstractNodesGroup {
}
if (this.options.rotateStringArray) {
this.stringArrayRotateValue = Utils.getRandomGenerator().integer({
min: 100,
max: 500
});
this.stringArrayRotateValue = Utils.getRandomInteger(100, 500);
} else {
this.stringArrayRotateValue = 0;
}
const stringArray: StringArray = new StringArray();
const stringArray: IStorage <string> = new StringArrayStorage();
const stringArrayNode: ICustomNode = new StringArrayNode(
stringArray,
this.stringArrayName,
@@ -1,25 +1,25 @@
import * as ESTree from 'estree';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { INodeObfuscator } from '../interfaces/INodeObfuscator';
import { INodeTransformer } from '../interfaces/INodeTransformer';
import { IOptions } from '../interfaces/IOptions';
export abstract class AbstractNodeObfuscator implements INodeObfuscator {
export abstract class AbstractNodeTransformer implements INodeTransformer {
/**
* @type Map <string, AbstractCustomNode>
*/
protected nodes: Map <string, ICustomNode>;
protected readonly nodes: Map <string, ICustomNode>;
/**
* @type {IOptions}
*/
protected options: IOptions;
protected readonly options: IOptions;
/**
* @param nodes
* @param options
*/
constructor(nodes: Map <string, ICustomNode>, options: IOptions) {
constructor (nodes: Map <string, ICustomNode>, options: IOptions) {
this.nodes = nodes;
this.options = options;
}
@@ -28,5 +28,5 @@ export abstract class AbstractNodeObfuscator implements INodeObfuscator {
* @param node
* @param parentNode
*/
public abstract obfuscateNode (node: ESTree.Node, parentNode?: ESTree.Node): void;
public abstract transformNode (node: ESTree.Node, parentNode?: ESTree.Node): void;
}
@@ -0,0 +1,49 @@
import { TNodeTransformer } from '../types/TNodeTransformer';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { INodeTransformer } from '../interfaces/INodeTransformer';
import { INodeTransformersFactory } from '../interfaces/INodeTransformersFactory';
import { IOptions } from '../interfaces/IOptions';
export abstract class AbstractNodeTransformersFactory implements INodeTransformersFactory {
/**
* @type {Map<string, TNodeTransformer[]>}
*/
protected abstract readonly nodeTransformers: Map <string, TNodeTransformer[]>;
/**
* @type Map <string, AbstractCustomNode>
*/
protected readonly customNodes: Map <string, ICustomNode>;
/**
* @type {IOptions}
*/
protected readonly options: IOptions;
/**
* @param customNodes
* @param options
*/
constructor (customNodes: Map <string, ICustomNode>, options: IOptions) {
this.customNodes = customNodes;
this.options = options;
}
/**
* @param nodeType
* @returns {INodeTransformer[]}
*/
public initializeNodeTransformers (nodeType: string): INodeTransformer[] {
const nodeTransformers: TNodeTransformer[] = this.nodeTransformers.get(nodeType) || [];
const instancesArray: INodeTransformer[] = [];
nodeTransformers.forEach((transformer: TNodeTransformer) => {
instancesArray.push(
new transformer(this.customNodes, this.options)
);
});
return instancesArray;
}
}
@@ -0,0 +1,98 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TControlFlowReplacer } from '../../types/TControlFlowReplacer';
import { TStatement } from '../../types/TStatement';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { IStorage } from '../../interfaces/IStorage';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { BinaryExpressionControlFlowReplacer } from './control-flow-replacers/BinaryExpressionControlFlowReplacer';
import { ControlFlowStorage } from '../../storages/control-flow/ControlFlowStorage';
import { ControlFlowStorageNode } from '../../custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
import { Node } from '../../node/Node';
import { NodeAppender } from '../../node/NodeAppender';
import { Utils } from '../../Utils';
import { NodeUtils } from '../../node/NodeUtils';
export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
/**
* @type {Map <string, IReplacer>}
*/
private static readonly controlFlowReplacers: Map <string, TControlFlowReplacer> = new Map <string, TControlFlowReplacer> ([
[NodeType.BinaryExpression, BinaryExpressionControlFlowReplacer]
]);
/**
* @param nodes
* @param options
*/
constructor (nodes: Map <string, ICustomNode>, options: IOptions) {
super(nodes, options);
}
/**
* @param functionNode
*/
public transformNode (functionNode: ESTree.Function): void {
this.changeFunctionBodyControlFlow(functionNode);
}
/**
* @param functionNode
*/
private changeFunctionBodyControlFlow (functionNode: ESTree.Function): void {
if (Node.isArrowFunctionExpressionNode(functionNode)) {
return;
}
const controlFlowStorage: IStorage <ICustomNode> = new ControlFlowStorage();
const controlFlowStorageCustomNodeName: string = Utils.getRandomVariableName(6);
console.log(NodeUtils.getNodeBlockScopeDepth(functionNode.body));
estraverse.replace(functionNode.body, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
const controlFlowReplacer: TControlFlowReplacer | undefined = FunctionControlFlowTransformer
.controlFlowReplacers.get(node.type);
if (!controlFlowReplacer) {
return;
}
const controlFlowStorageCallCustomNode: ICustomNode | undefined = new controlFlowReplacer(
this.nodes,
this.options
).replace(node, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName);
if (!controlFlowStorageCallCustomNode) {
return;
}
// controlFlowStorageCallCustomNode will always have only one TStatement node,
// so we can get it by index `0`
// also we need to return `expression` property of `ExpressionStatement` node because bug:
// https://github.com/estools/escodegen/issues/289
const statementNode: TStatement | undefined = controlFlowStorageCallCustomNode.getNode()[0];
if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
throw new Error(`\`controlFlowStorageCallCustomNode.getNode()\` should returns array with \`ExpressionStatement\` node`);
}
return statementNode.expression;
}
});
const controlFlowStorageCustomNode: ICustomNode = new ControlFlowStorageNode(
controlFlowStorage,
controlFlowStorageCustomNodeName,
this.options
);
NodeAppender.prependNode(functionNode.body, controlFlowStorageCustomNode.getNode());
}
}
@@ -0,0 +1,53 @@
import * as ESTree from 'estree';
import { IControlFlowReplacer } from '../../../interfaces/IControlFlowReplacer';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../../interfaces/IOptions';
import { IStorage } from '../../../interfaces/IStorage';
import { Utils } from '../../../Utils';
export abstract class AbstractControlFlowReplacer implements IControlFlowReplacer {
/**
* @type Map <string, AbstractCustomNode>
*/
protected readonly nodes: Map <string, ICustomNode>;
/**
* @type {IOptions}
*/
protected readonly options : IOptions;
/**
* @param nodes
* @param options
*/
constructor (nodes: Map <string, ICustomNode>, options: IOptions) {
this.nodes = nodes;
this.options = options;
}
/**
* @returns {string}
*/
protected static getStorageKey (): string {
return Utils.getRandomGenerator().string({
length: 3,
pool: Utils.randomGeneratorPool
});
}
/**
* @param node
* @param parentNode
* @param controlFlowStorage
* @param controlFlowStorageCustomNodeName
* @returns {ICustomNode | undefined}
*/
public abstract replace (
node: ESTree.Node,
parentNode: ESTree.Node,
controlFlowStorage: IStorage <ICustomNode>,
controlFlowStorageCustomNodeName: string
): ICustomNode | undefined;
}
@@ -0,0 +1,47 @@
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IStorage } from '../../../interfaces/IStorage';
import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode';
import { ControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/ControlFlowStorageCallNode';
export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
/**
* @param expressionNode
* @returns {string}
*/
private static getExpressionValue (expressionNode: ESTree.Expression): string {
return escodegen.generate(expressionNode, {
sourceMapWithCode: true
}).code;
}
/**
* @param binaryExpressionNode
* @param parentNode
* @param controlFlowStorage
* @param controlFlowStorageCustomNodeName
* @returns {ICustomNode | undefined}
*/
public replace (
binaryExpressionNode: ESTree.BinaryExpression,
parentNode: ESTree.Node,
controlFlowStorage: IStorage <ICustomNode>,
controlFlowStorageCustomNodeName: string
): ICustomNode | undefined {
const key: string = AbstractControlFlowReplacer.getStorageKey();
controlFlowStorage.set(key, new BinaryExpressionFunctionNode(binaryExpressionNode.operator, this.options));
return new ControlFlowStorageCallNode(
controlFlowStorageCustomNodeName,
key,
BinaryExpressionControlFlowReplacer.getExpressionValue(binaryExpressionNode.left),
BinaryExpressionControlFlowReplacer.getExpressionValue(binaryExpressionNode.right),
this.options
);
}
}
@@ -0,0 +1,16 @@
import { TNodeTransformer } from '../../../types/TNodeTransformer';
import { NodeType } from '../../../enums/NodeType';
import { FunctionControlFlowTransformer } from '../FunctionControlFlowTransformer';
import { AbstractNodeTransformersFactory } from '../../AbstractNodeTransformersFactory';
export class NodeControlFlowTransformersFactory extends AbstractNodeTransformersFactory {
/**
* @type {Map<string, TNodeTransformer[]>}
*/
protected readonly nodeTransformers: Map <string, TNodeTransformer[]> = new Map <string, TNodeTransformer[]> ([
[NodeType.FunctionDeclaration, [FunctionControlFlowTransformer]],
[NodeType.FunctionExpression, [FunctionControlFlowTransformer]]
]);
}
@@ -1,15 +1,15 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierReplacer } from './replacers/IdentifierReplacer';
import { Node } from '../node/Node';
import { NodeUtils } from '../node/NodeUtils';
import { Node } from '../../node/Node';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -19,11 +19,11 @@ import { NodeUtils } from '../node/NodeUtils';
* try {} catch (_0x12d45f) { console.log(_0x12d45f); };
*
*/
export class CatchClauseObfuscator extends AbstractNodeObfuscator {
export class CatchClauseObfuscator extends AbstractNodeTransformer {
/**
* @type {IdentifierReplacer}
*/
private identifierReplacer: IdentifierReplacer;
private readonly identifierReplacer: IdentifierReplacer;
/**
* @param nodes
@@ -38,7 +38,7 @@ export class CatchClauseObfuscator extends AbstractNodeObfuscator {
/**
* @param catchClauseNode
*/
public obfuscateNode (catchClauseNode: ESTree.CatchClause): void {
public transformNode (catchClauseNode: ESTree.CatchClause): void {
this.storeCatchClauseParam(catchClauseNode);
this.replaceCatchClauseParam(catchClauseNode);
}
@@ -47,7 +47,7 @@ export class CatchClauseObfuscator extends AbstractNodeObfuscator {
* @param catchClauseNode
*/
private storeCatchClauseParam (catchClauseNode: ESTree.CatchClause): void {
NodeUtils.typedReplace(catchClauseNode.param, NodeType.Identifier, {
NodeUtils.typedTraverse(catchClauseNode.param, NodeType.Identifier, {
enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
});
}
@@ -1,17 +1,17 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TNodeWithBlockStatement } from '../types/TNodeWithBlockStatement';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierReplacer } from './replacers/IdentifierReplacer';
import { Node } from '../node/Node';
import { NodeUtils } from '../node/NodeUtils';
import { Node } from '../../node/Node';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -22,11 +22,11 @@ import { NodeUtils } from '../node/NodeUtils';
* function _0x12d45f () { //... };
* _0x12d45f();
*/
export class FunctionDeclarationObfuscator extends AbstractNodeObfuscator {
export class FunctionDeclarationObfuscator extends AbstractNodeTransformer {
/**
* @type {IdentifierReplacer}
*/
private identifierReplacer: IdentifierReplacer;
private readonly identifierReplacer: IdentifierReplacer;
/**
* @param nodes
@@ -42,7 +42,7 @@ export class FunctionDeclarationObfuscator extends AbstractNodeObfuscator {
* @param functionDeclarationNode
* @param parentNode
*/
public obfuscateNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): void {
public transformNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): void {
const blockScopeOfFunctionDeclarationNode: TNodeWithBlockStatement = NodeUtils
.getBlockScopeOfNode(functionDeclarationNode);
@@ -58,7 +58,7 @@ export class FunctionDeclarationObfuscator extends AbstractNodeObfuscator {
* @param functionDeclarationNode
*/
private storeFunctionName (functionDeclarationNode: ESTree.FunctionDeclaration): void {
NodeUtils.typedReplace(functionDeclarationNode.id, NodeType.Identifier, {
NodeUtils.typedTraverse(functionDeclarationNode.id, NodeType.Identifier, {
enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
});
}
@@ -1,15 +1,15 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierReplacer } from './replacers/IdentifierReplacer';
import { Node } from '../node/Node';
import { NodeUtils } from '../node/NodeUtils';
import { Node } from '../../node/Node';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -19,11 +19,11 @@ import { NodeUtils } from '../node/NodeUtils';
* function foo (_0x12d45f) { return _0x12d45f; };
*
*/
export class FunctionObfuscator extends AbstractNodeObfuscator {
export class FunctionObfuscator extends AbstractNodeTransformer {
/**
* @type {IdentifierReplacer}
*/
private identifierReplacer: IdentifierReplacer;
private readonly identifierReplacer: IdentifierReplacer;
/**
* @param nodes
@@ -38,7 +38,7 @@ export class FunctionObfuscator extends AbstractNodeObfuscator {
/**
* @param functionNode
*/
public obfuscateNode (functionNode: ESTree.Function): void {
public transformNode (functionNode: ESTree.Function): void {
this.storeFunctionParams(functionNode);
this.replaceFunctionParams(functionNode);
}
@@ -49,7 +49,7 @@ export class FunctionObfuscator extends AbstractNodeObfuscator {
private storeFunctionParams (functionNode: ESTree.Function): void {
functionNode.params
.forEach((paramsNode: ESTree.Node) => {
NodeUtils.typedReplace(paramsNode, NodeType.Identifier, {
NodeUtils.typedTraverse(paramsNode, NodeType.Identifier, {
enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
});
});
@@ -59,7 +59,7 @@ export class FunctionObfuscator extends AbstractNodeObfuscator {
* @param functionNode
*/
private replaceFunctionParams (functionNode: ESTree.Function): void {
let replaceVisitor: estraverse.Visitor = {
let traverseVisitor: estraverse.Visitor = {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
if (Node.isReplaceableIdentifierNode(node, parentNode)) {
const newNodeName: string = this.identifierReplacer.replace(node.name);
@@ -72,11 +72,8 @@ export class FunctionObfuscator extends AbstractNodeObfuscator {
}
};
functionNode.params
.forEach((paramsNode: ESTree.Node) => {
estraverse.replace(paramsNode, replaceVisitor);
});
functionNode.params.forEach((paramsNode: ESTree.Node) => estraverse.replace(paramsNode, traverseVisitor));
estraverse.replace(functionNode.body, replaceVisitor);
estraverse.replace(functionNode.body, traverseVisitor);
}
}
@@ -1,15 +1,15 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierReplacer } from './replacers/IdentifierReplacer';
import { Node } from '../node/Node';
import { NodeUtils } from '../node/NodeUtils';
import { Node } from '../../node/Node';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -27,11 +27,11 @@ import { NodeUtils } from '../node/NodeUtils';
* }
*
*/
export class LabeledStatementObfuscator extends AbstractNodeObfuscator {
export class LabeledStatementObfuscator extends AbstractNodeTransformer {
/**
* @type {IdentifierReplacer}
*/
private identifierReplacer: IdentifierReplacer;
private readonly identifierReplacer: IdentifierReplacer;
/**
* @param nodes
@@ -46,7 +46,7 @@ export class LabeledStatementObfuscator extends AbstractNodeObfuscator {
/**
* @param labeledStatementNode
*/
public obfuscateNode (labeledStatementNode: ESTree.LabeledStatement): void {
public transformNode (labeledStatementNode: ESTree.LabeledStatement): void {
this.storeLabeledStatementName(labeledStatementNode);
this.replaceLabeledStatementName(labeledStatementNode);
}
@@ -55,7 +55,7 @@ export class LabeledStatementObfuscator extends AbstractNodeObfuscator {
* @param labeledStatementNode
*/
private storeLabeledStatementName (labeledStatementNode: ESTree.LabeledStatement): void {
NodeUtils.typedReplace(labeledStatementNode.label, NodeType.Identifier, {
NodeUtils.typedTraverse(labeledStatementNode.label, NodeType.Identifier, {
enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
});
}
@@ -1,18 +1,18 @@
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { BooleanLiteralReplacer } from './replacers/BooleanLiteralReplacer';
import { Node } from '../node/Node';
import { Node } from '../../node/Node';
import { NumberLiteralReplacer } from './replacers/NumberLiteralReplacer';
import { StringLiteralReplacer } from './replacers/StringLiteralReplacer';
export class LiteralObfuscator extends AbstractNodeObfuscator {
export class LiteralObfuscator extends AbstractNodeTransformer {
/**
* @param literalNode
* @param parentNode
*/
public obfuscateNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
public transformNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
if (Node.isPropertyNode(parentNode) && parentNode.key === literalNode) {
return;
}
@@ -34,7 +34,7 @@ export class LiteralObfuscator extends AbstractNodeObfuscator {
case 'string':
content = new StringLiteralReplacer(this.nodes, this.options)
.replace(<string>literalNode.value);
.replace(<string>literalNode.value);
break;
@@ -2,18 +2,18 @@ import * as escodegen from 'escodegen';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { Node } from '../node/Node';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { Node } from '../../node/Node';
import { StringLiteralReplacer } from './replacers/StringLiteralReplacer';
export class MemberExpressionObfuscator extends AbstractNodeObfuscator {
export class MemberExpressionObfuscator extends AbstractNodeTransformer {
/**
* @param memberExpressionNode
*/
public obfuscateNode (memberExpressionNode: ESTree.MemberExpression): void {
estraverse.replace(memberExpressionNode.property, {
public transformNode (memberExpressionNode: ESTree.MemberExpression): void {
estraverse.traverse(memberExpressionNode.property, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
if (Node.isLiteralNode(node)) {
this.obfuscateLiteralProperty(node);
@@ -46,16 +46,16 @@ export class MemberExpressionObfuscator extends AbstractNodeObfuscator {
* @param node
*/
private obfuscateIdentifierProperty (node: ESTree.Identifier): void {
let nodeValue: string = node.name,
literalNode: ESTree.Literal = {
raw: `'${nodeValue}'`,
'x-verbatim-property': {
content : new StringLiteralReplacer(this.nodes, this.options).replace(nodeValue),
precedence: escodegen.Precedence.Primary
},
type: NodeType.Literal,
value: nodeValue
};
const nodeValue: string = node.name;
const literalNode: ESTree.Literal = {
raw: `'${nodeValue}'`,
'x-verbatim-property': {
content : new StringLiteralReplacer(this.nodes, this.options).replace(nodeValue),
precedence: escodegen.Precedence.Primary
},
type: NodeType.Literal,
value: nodeValue
};
delete node.name;
@@ -1,9 +1,9 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { Node } from '../node/Node';
import { Utils } from '../Utils';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { Node } from '../../node/Node';
import { Utils } from '../../Utils';
import { StringLiteralReplacer } from './replacers/StringLiteralReplacer';
/**
@@ -13,17 +13,17 @@ import { StringLiteralReplacer } from './replacers/StringLiteralReplacer';
* on:
* [_0x9a4e('0x0')] { //... };
*/
export class MethodDefinitionObfuscator extends AbstractNodeObfuscator {
export class MethodDefinitionObfuscator extends AbstractNodeTransformer {
/**
* @type {string[]}
*/
private static ignoredNames: string[] = ['constructor'];
private static readonly ignoredNames: string[] = ['constructor'];
/**
* @param methodDefinitionNode
* @param parentNode
*/
public obfuscateNode (methodDefinitionNode: ESTree.MethodDefinition, parentNode: ESTree.Node): void {
public transformNode (methodDefinitionNode: ESTree.MethodDefinition, parentNode: ESTree.Node): void {
this.replaceMethodName(methodDefinitionNode);
}
@@ -2,11 +2,11 @@ import * as escodegen from 'escodegen';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { Node } from '../node/Node';
import { Utils } from '../Utils';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { Node } from '../../node/Node';
import { Utils } from '../../Utils';
/**
* replaces:
@@ -18,18 +18,18 @@ import { Utils } from '../Utils';
* on:
* var object = { '\u0050\u0053\u0045\u0055\u0044\u004f': 1 };
*/
export class ObjectExpressionObfuscator extends AbstractNodeObfuscator {
export class ObjectExpressionObfuscator extends AbstractNodeTransformer {
/**
* @param objectExpressionNode
*/
public obfuscateNode (objectExpressionNode: ESTree.ObjectExpression): void {
public transformNode (objectExpressionNode: ESTree.ObjectExpression): void {
objectExpressionNode.properties
.forEach((property: ESTree.Property) => {
if (property.shorthand) {
property.shorthand = false;
}
estraverse.replace(property.key, {
estraverse.traverse(property.key, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
if (Node.isLiteralNode(node)) {
this.obfuscateLiteralPropertyKey(node);
@@ -61,16 +61,16 @@ export class ObjectExpressionObfuscator extends AbstractNodeObfuscator {
* @param node
*/
private obfuscateIdentifierPropertyKey (node: ESTree.Identifier): void {
let nodeValue: string = node.name,
literalNode: ESTree.Literal = {
raw: `'${nodeValue}'`,
'x-verbatim-property': {
content : `'${Utils.stringToUnicodeEscapeSequence(nodeValue)}'`,
precedence: escodegen.Precedence.Primary
},
type: NodeType.Literal,
value: nodeValue
};
const nodeValue: string = node.name;
const literalNode: ESTree.Literal = {
raw: `'${nodeValue}'`,
'x-verbatim-property': {
content : `'${Utils.stringToUnicodeEscapeSequence(nodeValue)}'`,
precedence: escodegen.Precedence.Primary
},
type: NodeType.Literal,
value: nodeValue
};
delete node.name;
@@ -1,17 +1,17 @@
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TNodeWithBlockStatement } from '../types/TNodeWithBlockStatement';
import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { NodeType } from '../enums/NodeType';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeObfuscator } from './AbstractNodeObfuscator';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierReplacer } from './replacers/IdentifierReplacer';
import { Node } from '../node/Node';
import { NodeUtils } from '../node/NodeUtils';
import { Node } from '../../node/Node';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -23,11 +23,11 @@ import { NodeUtils } from '../node/NodeUtils';
* _0x12d45f++;
*
*/
export class VariableDeclarationObfuscator extends AbstractNodeObfuscator {
export class VariableDeclarationObfuscator extends AbstractNodeTransformer {
/**
* @type {IdentifierReplacer}
*/
private identifierReplacer: IdentifierReplacer;
private readonly identifierReplacer: IdentifierReplacer;
/**
* @param nodes
@@ -43,7 +43,7 @@ export class VariableDeclarationObfuscator extends AbstractNodeObfuscator {
* @param variableDeclarationNode
* @param parentNode
*/
public obfuscateNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): void {
public transformNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): void {
const blockScopeOfVariableDeclarationNode: TNodeWithBlockStatement = NodeUtils
.getBlockScopeOfNode(variableDeclarationNode);
@@ -65,7 +65,7 @@ export class VariableDeclarationObfuscator extends AbstractNodeObfuscator {
private storeVariableNames (variableDeclarationNode: ESTree.VariableDeclaration): void {
variableDeclarationNode.declarations
.forEach((declarationNode: ESTree.VariableDeclarator) => {
NodeUtils.typedReplace(declarationNode.id, NodeType.Identifier, {
NodeUtils.typedTraverse(declarationNode.id, NodeType.Identifier, {
enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
});
});
@@ -0,0 +1,36 @@
import { TNodeTransformer } from '../../../types/TNodeTransformer';
import { NodeType } from '../../../enums/NodeType';
import { CatchClauseObfuscator } from '../CatchClauseObfuscator';
import { FunctionDeclarationObfuscator } from '../FunctionDeclarationObfuscator';
import { FunctionObfuscator } from '../FunctionObfuscator';
import { LabeledStatementObfuscator } from '../LabeledStatementObfuscator';
import { LiteralObfuscator } from '../LiteralObfuscator';
import { MemberExpressionObfuscator } from '../MemberExpressionObfuscator';
import { MethodDefinitionObfuscator } from '../MethodDefinitionObfuscator';
import { ObjectExpressionObfuscator } from '../ObjectExpressionObfuscator';
import { VariableDeclarationObfuscator } from '../VariableDeclarationObfuscator';
import { AbstractNodeTransformersFactory } from '../../AbstractNodeTransformersFactory';
export class NodeObfuscatorsFactory extends AbstractNodeTransformersFactory {
/**
* @type {Map<string, TNodeTransformer[]>}
*/
protected readonly nodeTransformers: Map <string, TNodeTransformer[]> = new Map <string, TNodeTransformer[]> ([
[NodeType.ArrowFunctionExpression, [FunctionObfuscator]],
[NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]],
[NodeType.CatchClause, [CatchClauseObfuscator]],
[NodeType.FunctionDeclaration, [
FunctionDeclarationObfuscator,
FunctionObfuscator
]],
[NodeType.FunctionExpression, [FunctionObfuscator]],
[NodeType.MemberExpression, [MemberExpressionObfuscator]],
[NodeType.MethodDefinition, [MethodDefinitionObfuscator]],
[NodeType.ObjectExpression, [ObjectExpressionObfuscator]],
[NodeType.VariableDeclaration, [VariableDeclarationObfuscator]],
[NodeType.LabeledStatement, [LabeledStatementObfuscator]],
[NodeType.Literal, [LiteralObfuscator]]
]);
}
@@ -1,17 +1,17 @@
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/IOptions';
import { IReplacer } from '../../interfaces/IReplacer';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../../interfaces/IOptions';
import { IReplacer } from '../../../interfaces/IReplacer';
export abstract class AbstractReplacer implements IReplacer {
/**
* @type Map <string, AbstractCustomNode>
*/
protected nodes: Map <string, ICustomNode>;
protected readonly nodes: Map <string, ICustomNode>;
/**
* @type {IOptions}
*/
protected options : IOptions;
protected readonly options : IOptions;
/**
* @param nodes
@@ -1,4 +1,4 @@
import { JSFuck } from '../../enums/JSFuck';
import { JSFuck } from '../../../enums/JSFuck';
import { AbstractReplacer } from './AbstractReplacer';
@@ -1,11 +1,11 @@
import { AbstractReplacer } from './AbstractReplacer';
import { Utils } from '../../Utils';
import { Utils } from '../../../Utils';
export class IdentifierReplacer extends AbstractReplacer {
/**
* @type {Map<string, string>}
*/
private namesMap: Map<string, string> = new Map<string, string>();
private readonly namesMap: Map<string, string> = new Map<string, string>();
/**
* @param nodeValue
@@ -1,5 +1,5 @@
import { AbstractReplacer } from './AbstractReplacer';
import { Utils } from '../../Utils';
import { Utils } from '../../../Utils';
export class NumberLiteralReplacer extends AbstractReplacer {
/**
@@ -1,23 +1,23 @@
import { TStringArrayCallsWrapper } from '../../types/custom-nodes/TStringArrayCallsWrapper';
import { TStringArrayNode } from '../../types/custom-nodes/TStringArrayNode';
import { ICustomNodeWithData } from '../../../interfaces/custom-nodes/ICustomNodeWithData';
import { IStorage } from '../../../interfaces/IStorage';
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
import { StringArrayEncoding } from '../../../enums/StringArrayEncoding';
import { AbstractReplacer } from './AbstractReplacer';
import { NumberLiteralReplacer } from './NumberLiteralReplacer';
import { StringArray } from '../../StringArray';
import { Utils } from '../../Utils';
import { Utils } from '../../../Utils';
import { ICustomNodeWithIdentifier } from '../../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
export class StringLiteralReplacer extends AbstractReplacer {
/**
* @type {number}
*/
private static minimumLengthForStringArray: number = 3;
private static readonly minimumLengthForStringArray: number = 3;
/**
* @type {string[]}
*/
private static rc4Keys: string[] = Utils.getRandomGenerator()
private static readonly rc4Keys: string[] = Utils.getRandomGenerator()
.n(() => Utils.getRandomGenerator().string({length: 4}), 50);
/**
@@ -27,7 +27,7 @@ export class StringLiteralReplacer extends AbstractReplacer {
public replace (nodeValue: string): string {
const replaceWithStringArrayFlag: boolean = (
nodeValue.length >= StringLiteralReplacer.minimumLengthForStringArray
&& Math.random() <= this.options.stringArrayThreshold
&& Utils.getRandomFloat(0, 1) <= this.options.stringArrayThreshold
);
if (this.options.stringArray && replaceWithStringArrayFlag) {
@@ -42,10 +42,10 @@ export class StringLiteralReplacer extends AbstractReplacer {
* @returns {string}
*/
private replaceStringLiteralWithStringArrayCall (value: string): string {
const stringArrayNode: TStringArrayNode = <TStringArrayNode>this.nodes.get('stringArrayNode');
const stringArrayNode: ICustomNodeWithData = <ICustomNodeWithData>this.nodes.get('stringArrayNode');
if (!stringArrayNode) {
throw new ReferenceError('`stringArrayNode` node is not found in Map with custom node.');
throw new ReferenceError('`stringArrayNode` node is not found in Map with custom nodes.');
}
let rc4Key: string = '';
@@ -67,22 +67,20 @@ export class StringLiteralReplacer extends AbstractReplacer {
value = Utils.stringToUnicodeEscapeSequence(value);
}
let stringArray: StringArray = stringArrayNode.getNodeData(),
indexOfExistingValue: number = stringArray.getIndexOf(value),
indexOfValue: number,
hexadecimalIndex: string;
const stringArray: IStorage <string> = stringArrayNode.getNodeData();
const indexOfExistingValue: number = <number>stringArray.getKeyOf(value);
let indexOfValue: number;
if (indexOfExistingValue >= 0) {
indexOfValue = indexOfExistingValue;
} else {
indexOfValue = stringArray.getLength();
stringArrayNode.updateNodeData(value);
stringArray.set(null, value);
}
hexadecimalIndex = new NumberLiteralReplacer(this.nodes, this.options)
.replace(indexOfValue);
const stringArrayCallsWrapper: TStringArrayCallsWrapper = <TStringArrayCallsWrapper>this.nodes.get('stringArrayCallsWrapper');
const stringArrayCallsWrapper: ICustomNodeWithIdentifier = <ICustomNodeWithIdentifier>this.nodes.get('stringArrayCallsWrapper');
const hexadecimalIndex: string = new NumberLiteralReplacer(this.nodes, this.options).replace(indexOfValue);
if (!stringArrayCallsWrapper) {
throw new ReferenceError('`stringArrayCallsWrapper` node is not found in Map with custom node.');
+1 -4
View File
@@ -101,10 +101,7 @@ export class NodeAppender {
* @param stackTraceRootLength
*/
public static getRandomStackTraceIndex (stackTraceRootLength: number): number {
return Utils.getRandomGenerator().integer({
min: 0,
max: Math.max(0, Math.round(stackTraceRootLength - 1))
});
return Utils.getRandomInteger(0, Math.max(0, Math.round(stackTraceRootLength - 1)));
}
/**
+26 -3
View File
@@ -15,7 +15,7 @@ export class NodeUtils {
/**
* @type {string[]}
*/
private static nodesWithBlockScope: string[] = [
private static readonly nodesWithBlockScope: string[] = [
NodeType.ArrowFunctionExpression,
NodeType.FunctionDeclaration,
NodeType.FunctionExpression,
@@ -42,7 +42,7 @@ export class NodeUtils {
* @returns {TStatement[]}
*/
public static convertCodeToStructure (code: string): TStatement[] {
let structure: ESTree.Program = esprima.parse(code);
const structure: ESTree.Program = esprima.parse(code);
NodeUtils.addXVerbatimPropertyToLiterals(structure);
NodeUtils.parentize(structure);
@@ -73,7 +73,7 @@ export class NodeUtils {
* @returns {ESTree.Node}
*/
public static getBlockScopeOfNode (node: ESTree.Node, depth: number = 0): TNodeWithBlockStatement {
let parentNode: ESTree.Node | undefined = node.parentNode;
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
@@ -100,6 +100,29 @@ export class NodeUtils {
return NodeUtils.getBlockScopeOfNode(parentNode);
}
/**
* @param node
* @param depth
* @returns {number}
*/
public static getNodeBlockScopeDepth (node: ESTree.Node, depth: number = 0): number {
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
if (Node.isProgramNode(parentNode)) {
return depth;
}
if (Node.isBlockStatementNode(node)) {
return NodeUtils.getNodeBlockScopeDepth(parentNode, ++depth);
}
return NodeUtils.getNodeBlockScopeDepth(parentNode, depth);
}
/**
* @param node
*/
+13 -1
View File
@@ -41,6 +41,12 @@ export class Options implements IOptions {
@IsBoolean()
public readonly compact: boolean;
/**
* @type {boolean}
*/
@IsBoolean()
public readonly controlFlowFlattening: boolean;
/**
* @type {boolean}
*/
@@ -85,6 +91,12 @@ export class Options implements IOptions {
@IsBoolean()
public readonly rotateStringArray: boolean;
/**
* @type {number}
*/
@IsNumber()
public readonly seed: number;
/**
* @type {boolean}
*/
@@ -152,7 +164,7 @@ export class Options implements IOptions {
constructor (obfuscatorOptions: IObfuscatorOptions) {
Object.assign(this, DEFAULT_PRESET, obfuscatorOptions);
let errors: ValidationError[] = validateSync(this, Options.validatorOptions);
const errors: ValidationError[] = validateSync(this, Options.validatorOptions);
if (errors.length) {
throw new ReferenceError(`Validation failed. errors:\n${ValidationErrorsFormatter.format(errors)}`);
+6 -6
View File
@@ -9,7 +9,7 @@ export class OptionsNormalizer {
/**
* @type {IObfuscatorOptions}
*/
private static DISABLED_UNICODE_ARRAY_OPTIONS: IObfuscatorOptions = {
private static readonly DISABLED_UNICODE_ARRAY_OPTIONS: IObfuscatorOptions = {
rotateStringArray: false,
stringArray: false,
stringArrayEncoding: false,
@@ -19,7 +19,7 @@ export class OptionsNormalizer {
/**
* @type {IObfuscatorOptions}
*/
private static SELF_DEFENDING_OPTIONS: IObfuscatorOptions = {
private static readonly SELF_DEFENDING_OPTIONS: IObfuscatorOptions = {
compact: true,
selfDefending: true
};
@@ -27,14 +27,14 @@ export class OptionsNormalizer {
/**
* @type {IObfuscatorOptions}
*/
private static UNICODE_ARRAY_ENCODING_OPTIONS: IObfuscatorOptions = {
private static readonly UNICODE_ARRAY_ENCODING_OPTIONS: IObfuscatorOptions = {
stringArrayEncoding: 'base64'
};
/**
* @type {TOptionsNormalizerRule[]}
*/
private static normalizerRules: TOptionsNormalizerRule[] = [
private static readonly normalizerRules: TOptionsNormalizerRule[] = [
OptionsNormalizer.domainLockRule,
OptionsNormalizer.selfDefendingRule,
OptionsNormalizer.sourceMapBaseUrlRule,
@@ -64,7 +64,7 @@ export class OptionsNormalizer {
*/
private static domainLockRule (options: IOptions): IOptions {
if (options.domainLock.length) {
let normalizedDomains: string[] = [];
const normalizedDomains: string[] = [];
for (const domain of options.domainLock) {
normalizedDomains.push(Utils.extractDomainFromUrl(domain));
@@ -95,7 +95,7 @@ export class OptionsNormalizer {
* @returns {IOptions}
*/
private static sourceMapBaseUrlRule (options: IOptions): IOptions {
let sourceMapBaseUrl: string = options.sourceMapBaseUrl;
const sourceMapBaseUrl: string = options.sourceMapBaseUrl;
if (!options.sourceMapFileName) {
Object.assign(options, {
+4 -3
View File
@@ -6,7 +6,7 @@ export class ValidationErrorsFormatter {
* @returns {string}
*/
public static format (validationErrors: ValidationError[]): string {
let errorsArray: string[] = [];
const errorsArray: string[] = [];
for (const error of validationErrors) {
errorsArray.push(ValidationErrorsFormatter.formatError(error));
@@ -20,8 +20,9 @@ export class ValidationErrorsFormatter {
* @returns {string}
*/
private static formatError (validationError: ValidationError): string {
let errorString: string = `\`${validationError.property}\` errors:\n`,
constraints: {[type: string]: string} = validationError.constraints;
const constraints: {[type: string]: string} = validationError.constraints;
let errorString: string = `\`${validationError.property}\` errors:\n`;
for (const constraint in constraints) {
if (!constraints.hasOwnProperty(constraint)) {
+2
View File
@@ -4,12 +4,14 @@ import { SourceMapMode } from '../enums/SourceMapMode';
export const DEFAULT_PRESET: IObfuscatorOptions = Object.freeze({
compact: true,
controlFlowFlattening: false,
debugProtection: false,
debugProtectionInterval: false,
disableConsoleOutput: true,
domainLock: [],
reservedNames: [],
rotateStringArray: true,
seed: 0,
selfDefending: true,
sourceMap: false,
sourceMapBaseUrl: '',
@@ -4,12 +4,14 @@ import { SourceMapMode } from '../enums/SourceMapMode';
export const NO_CUSTOM_NODES_PRESET: IObfuscatorOptions = Object.freeze({
compact: true,
controlFlowFlattening: false,
debugProtection: false,
debugProtectionInterval: false,
disableConsoleOutput: false,
domainLock: [],
reservedNames: [],
rotateStringArray: false,
seed: 0,
selfDefending: false,
sourceMap: false,
sourceMapBaseUrl: '',
+7 -18
View File
@@ -51,34 +51,22 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer {
/**
* @type {number}
*/
private static limitThresholdActivationLength: number = 25;
private static readonly limitThresholdActivationLength: number = 25;
/**
* @type {number}
*/
private static limitThreshold: number = 0.002;
/**
* @type {ESTree.Node[]}
*/
private blockScopeBody: ESTree.Node[];
private static readonly limitThreshold: number = 0.002;
/**
* @type {Map<string, TCalleeDataExtractor>}
*/
private calleeDataExtractors: Map <string, TCalleeDataExtractor> = new Map <string, TCalleeDataExtractor> ([
private readonly calleeDataExtractors: Map <string, TCalleeDataExtractor> = new Map <string, TCalleeDataExtractor> ([
[NodeType.FunctionDeclaration, FunctionDeclarationCalleeDataExtractor],
[NodeType.FunctionExpression, FunctionExpressionCalleeDataExtractor],
[NodeType.ObjectExpression, ObjectExpressionCalleeDataExtractor]
]);
/**
* @param blockScopeBody
*/
constructor (blockScopeBody: ESTree.Node[]) {
this.blockScopeBody = blockScopeBody;
}
/**
* @param blockScopeBodyLength
* @returns {number}
@@ -103,10 +91,11 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer {
}
/**
* @param blockScopeBody
* @returns {IStackTraceData[]}
*/
public analyze (): IStackTraceData[] {
return this.analyzeRecursive(this.blockScopeBody);
public analyze (blockScopeBody: ESTree.Node[]): IStackTraceData[] {
return this.analyzeRecursive(blockScopeBody);
}
/**
@@ -122,7 +111,7 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer {
index < blockScopeBodyLength;
index++
) {
let rootNode: ESTree.Node = blockScopeBody[index];
const rootNode: ESTree.Node = blockScopeBody[index];
if (index > limitIndex) {
break;
+52
View File
@@ -0,0 +1,52 @@
import { IStorage } from '../interfaces/IStorage';
export abstract class ArrayStorage <T> implements IStorage <T> {
/**
* @type {T[]}
*/
protected storage: T[] = [];
/**
* @param key
* @returns {T}
*/
public get (key: number): T {
const value: T | undefined = this.storage[key];
if (!value) {
throw new Error(`No value found in array storage with key \`${key}\``);
}
return value;
}
/**
* @param value
* @returns {string | number}
*/
public getKeyOf (value: T): string | number {
return this.storage.indexOf(value);
}
/**
* @returns {number}
*/
public getLength (): number {
return this.storage.length;
}
/**
* @returns {T[]}
*/
public getStorage (): T[] {
return this.storage;
}
/**
* @param key
* @param value
*/
public set (key: string | null, value: T): void {
this.storage.push(value);
}
}
+54
View File
@@ -0,0 +1,54 @@
import { IStorage } from '../interfaces/IStorage';
import { Utils } from '../Utils';
export abstract class MapStorage <T> implements IStorage <T> {
/**
* @type {Map <string | number, T>}
*/
protected storage: Map <string | number, T> = new Map <string | number, T> ();
/**
* @param key
* @returns {T}
*/
public get (key: string | number): T {
const value: T | undefined = this.storage.get(key);
if (!value) {
throw new Error(`No value found in map storage with key \`${key}\``);
}
return value;
}
/**
* @param value
* @returns {string | number | null}
*/
public getKeyOf (value: T): string | number | null {
return Utils.mapGetFirstKeyOf(this.storage, value);
}
/**
* @returns {number}
*/
public getLength (): number {
return Array.from(this.storage).length;
}
/**
* @returns {Map <string | number, T>}
*/
public getStorage (): Map <string | number, T> {
return this.storage;
}
/**
* @param key
* @param value
*/
public set (key: string | number, value: T): void {
this.storage.set(key, value);
}
}
@@ -0,0 +1,19 @@
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { MapStorage } from '../MapStorage';
export class ControlFlowStorage extends MapStorage <ICustomNode> {
/**
* @returns {string}
*/
public toString (): string {
return Array
.from(this.storage)
.reduce((controlFlowStorageItems: string[], [key, value]: [string, ICustomNode]) => {
controlFlowStorageItems.push(`${key}: ${value.getCode()}`);
return controlFlowStorageItems;
}, [])
.join(',');
}
}
@@ -0,0 +1,20 @@
import { ArrayStorage } from '../ArrayStorage';
import { Utils } from '../../Utils';
export class StringArrayStorage extends ArrayStorage <string> {
/**
* @param rotationValue
*/
public rotateArray (rotationValue: number): void {
this.storage = Utils.arrayRotate(this.storage, rotationValue);
}
/**
* @returns {string}
*/
public toString (): string {
return this.storage.map((value: string) => {
return `'${value}'`;
}).toString();
}
}
@@ -0,0 +1,10 @@
/**
* @returns {string}
*/
export function BinaryExpressionFunctionTemplate (): string {
return `
function {functionName} (x, y) {
return x {operator} y;
}
`;
}
@@ -0,0 +1,6 @@
/**
* @returns {string}
*/
export function ControlFlowStorageCallTemplate (): string {
return '{controlFlowStorageName}.{controlFlowStorageKey}({leftValue}, {rightValue})';
}
@@ -0,0 +1,8 @@
/**
* @returns {string}
*/
export function ControlFlowStorageTemplate (): string {
return `
var {controlFlowStorageName} = { {controlFlowStorage} };
`;
}
@@ -1,5 +1,3 @@
import { Utils } from '../../../../Utils';
/**
* @returns {string}
*/
@@ -10,7 +8,7 @@ export function DebugProtectionFunctionTemplate (): string {
if (('' + counter / counter)['length'] !== 1 || counter % 20 === 0) {
(function () {}.constructor('debugger')());
} else {
[].filter.constructor(${Utils.stringToJSFuck('debugger')})();
(function () {}.constructor('debugger')());
}
debuggerProtection(++counter);
+5
View File
@@ -0,0 +1,5 @@
import { IControlFlowReplacer } from '../interfaces/IControlFlowReplacer';
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../interfaces/IOptions';
export type TControlFlowReplacer = (new (nodes: Map <string, ICustomNode>, options: IOptions) => IControlFlowReplacer);
-5
View File
@@ -1,5 +0,0 @@
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { INodeObfuscator } from '../interfaces/INodeObfuscator';
import { IOptions } from '../interfaces/IOptions';
export type TNodeObfuscator = (new (nodes: Map <string, ICustomNode>, options: IOptions) => INodeObfuscator);
+5
View File
@@ -0,0 +1,5 @@
import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
import { INodeTransformer } from '../interfaces/INodeTransformer';
import { IOptions } from '../interfaces/IOptions';
export type TNodeTransformer = (new (nodes: Map <string, ICustomNode>, options: IOptions) => INodeTransformer);
+1
View File
@@ -0,0 +1 @@
export type TVisitorDirection = 'enter' | 'leave';
-3
View File
@@ -1,3 +0,0 @@
import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
export type TStringArrayCallsWrapper = ICustomNodeWithIdentifier;
-4
View File
@@ -1,4 +0,0 @@
import { ICustomNodeWithData } from '../../interfaces/custom-nodes/ICustomNodeWithData';
import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
export type TStringArrayNode = ICustomNodeWithData & ICustomNodeWithIdentifier;
+13 -63
View File
@@ -1,4 +1,5 @@
'use strict';
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
if (!(<any>global)._babelPolyfill) {
require('babel-polyfill');
@@ -7,72 +8,21 @@ if (!(<any>global)._babelPolyfill) {
(function () {
const JavaScriptObfuscator: any = require("../../index");
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
(function(){
var result = 1,
term1 = 0,
term2 = 1,
i = 1;
while(i < 10)
{
var test = 10;
result = term1 + term2;
console.log(result);
term1 = term2;
term2 = result;
i++;
}
console.log(test);
var test = function (test) {
console.log(test);
if (true) {
var test = 5
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(`
(function(){
function t () {
return function () {
var t = 1 * 2;
}
}
return test;
}
console.log(test(1));
function test2 (abc) {
function test1 () {
console.log('inside', abc.item);
}
console.log('тест', abc);
var abc = {};
return abc.item = 15, test1();
};
var regexptest = /version\\/(\\d+)/i;
console.log(regexptest);
test2(22);
console.log(105.4);
console.log(true, false);
var sA = 'shorthand1';
var sB = 'shorthand2';
console.log({sA, sB});
try {
} catch (error) {
console.log(error);
}
})();
var s = 1 - 3;
})();
`,
{
disableConsoleOutput: false,
selfDefending: true,
stringArrayEncoding: 'rc4'
}
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
controlFlowFlattening: true,
disableConsoleOutput: false
})
).getObfuscatedCode();
console.log(obfuscatedCode);
+1 -1
View File
@@ -6371,7 +6371,7 @@
/* 42 */
/***/ function(module, exports, __webpack_require__) {
// to indexed object, toObject with fallback for non-array-like ES3 strings
// to indexed object, toString with fallback for non-array-like ES3 strings
var IObject = __webpack_require__(118)
, defined = __webpack_require__(59);
module.exports = function(it){
@@ -3,6 +3,7 @@ import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
import { readFileAsString } from '../helpers/readFileAsString';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -125,5 +126,40 @@ describe('JavaScriptObfuscator', () => {
assert.match(obfuscatedCode2, pattern1);
assert.match(obfuscatedCode2, pattern2);
});
it('should returns same code every time with same `seed`', () => {
const code: string = readFileAsString('./test/fixtures/sample.js');
const seed: number = 12345;
const obfuscationResult1: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: seed }
);
const obfuscationResult2: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: seed }
);
assert.equal(obfuscationResult1.getObfuscatedCode(), obfuscationResult2.getObfuscatedCode());
});
it('should returns different code with different `seed` option value', () => {
const code: string = readFileAsString('./test/fixtures/sample.js');
const obfuscationResult1: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: 12345 }
);
const obfuscationResult2: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: 12346 }
);
const obfuscationResult3: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: 0 }
);
const obfuscationResult4: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code, { seed: 0 }
);
assert.notEqual(obfuscationResult1.getObfuscatedCode(), obfuscationResult2.getObfuscatedCode());
assert.notEqual(obfuscationResult3.getObfuscatedCode(), obfuscationResult4.getObfuscatedCode());
});
});
});
@@ -4,6 +4,8 @@ import { JavaScriptObfuscatorInternal } from '../../src/JavaScriptObfuscatorInte
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
import { Options } from '../../src/options/Options';
const assert: Chai.AssertStatic = require('chai').assert;
describe('JavaScriptObfuscatorInternal', () => {
@@ -14,16 +16,15 @@ describe('JavaScriptObfuscatorInternal', () => {
it('should link obfuscated code with source map', () => {
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
`var test = 1;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true,
sourceMapFileName: sourceMapUrl
})
new Options(
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true,
sourceMapFileName: sourceMapUrl
})
)
);
javaScriptObfuscator.obfuscate();
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
obfuscationResult = javaScriptObfuscator.obfuscate('var test = 1;');
assert.match(
obfuscationResult.getObfuscatedCode(),
@@ -36,17 +37,16 @@ describe('JavaScriptObfuscatorInternal', () => {
let sourceMapBaseUrl: string = 'http://localhost:9000';
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
`var test = 1;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true,
sourceMapBaseUrl: sourceMapBaseUrl,
sourceMapFileName: sourceMapUrl
})
new Options(
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true,
sourceMapBaseUrl: sourceMapBaseUrl,
sourceMapFileName: sourceMapUrl
})
)
);
javaScriptObfuscator.obfuscate();
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
obfuscationResult = javaScriptObfuscator.obfuscate('var test = 1;');
assert.match(
obfuscationResult.getObfuscatedCode(),
@@ -1,17 +1,19 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { readFileAsString } from '../../helpers/readFileAsString';
import { readFileAsString } from '../../../helpers/readFileAsString';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
describe('CatchClauseObfuscator', () => {
describe('obfuscateNode (catchClauseNode: ESTree.CatchClause): void', () => {
describe('changeControlFlow (catchClauseNode: ESTree.CatchClause): void', () => {
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
readFileAsString('./test/fixtures/node-obfuscators/catch-clause-obfuscator/catch-clause-obfuscator.js'),
readFileAsString(
'./test/fixtures/node-transformers/node-obfuscators/catch-clause-obfuscator/catch-clause-obfuscator.js'
),
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -1,17 +1,19 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { readFileAsString } from '../../helpers/readFileAsString';
import { readFileAsString } from '../../../helpers/readFileAsString';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
describe('LabeledStatementObfuscator', () => {
describe('obfuscateNode (labeledStatementNode: ESTree.LabeledStatement): void', () => {
describe('changeControlFlow (labeledStatementNode: ESTree.LabeledStatement): void', () => {
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
readFileAsString('./test/fixtures/node-obfuscators/labeled-statement-obfuscator/labeled-statement-obfuscator.js'),
readFileAsString(
'./test/fixtures/node-transformers/node-obfuscators/labeled-statement-obfuscator/labeled-statement-obfuscator.js'
),
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -1,8 +1,8 @@
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -4,6 +4,7 @@ import * as ESTree from 'estree';
import { TNodeWithBlockStatement } from '../../../src/types/TNodeWithBlockStatement';
import { IStackTraceAnalyzer } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer';
import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData';
import { readFileAsString } from '../../helpers/readFileAsString';
@@ -145,6 +146,8 @@ function getObjectFunctionExpressionByName (astTree: ESTree.Node, objectName: st
describe('StackTraceAnalyzer', () => {
describe('extract (): IStackTraceData[]', () => {
const stackTraceAnalyzer: IStackTraceAnalyzer = new StackTraceAnalyzer();
let astTree: TNodeWithBlockStatement,
stackTraceData: IStackTraceData[],
expectedStackTraceData: IStackTraceData[];
@@ -191,7 +194,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -227,7 +230,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -263,7 +266,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -283,7 +286,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -339,7 +342,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -364,7 +367,7 @@ describe('StackTraceAnalyzer', () => {
},
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -378,7 +381,7 @@ describe('StackTraceAnalyzer', () => {
expectedStackTraceData = [];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -392,7 +395,7 @@ describe('StackTraceAnalyzer', () => {
expectedStackTraceData = [];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -424,7 +427,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -444,7 +447,7 @@ describe('StackTraceAnalyzer', () => {
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
stackTraceData = stackTraceAnalyzer.analyze(astTree.body);
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
@@ -1,4 +1,4 @@
import 'format-unicorn';
import * as format from 'string-template';
import { DomainLockNodeTemplate } from '../../../../../src/templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
@@ -14,7 +14,7 @@ const assert: Chai.AssertStatic = require('chai').assert;
* @returns {Function}
*/
function getFunctionFromTemplate (templateData: any, callsControllerFunctionName: string, currentDomain: string) {
let domainLockTemplate: string = DomainLockNodeTemplate().formatUnicorn(templateData);
let domainLockTemplate: string = format(DomainLockNodeTemplate(), templateData);
return Function(`
document = {

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