🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more →

javascript-obfuscator

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

javascript-obfuscator - npm Package Compare versions

Comparing version

to
0.4.0

@@ -22,2 +22,5 @@ "use strict";

compact: true,
debugProtection: false,
debugProtectionInterval: false,
disableConsoleOutput: true,
rotateUnicodeArray: true

@@ -29,2 +32,1 @@ };

exports.JavaScriptObfuscator = JavaScriptObfuscator;
module.exports = JavaScriptObfuscator;

@@ -11,4 +11,10 @@ "use strict";

export class JavaScriptObfuscator {
/**
* @type any
*/
private static defaultOptions: any = {
compact: true,
debugProtection: false,
debugProtectionInterval: false,
disableConsoleOutput: true,
rotateUnicodeArray: true

@@ -53,3 +59,1 @@ };

}
module.exports = JavaScriptObfuscator;
{
"name": "javascript-obfuscator",
"version": "0.3.0",
"version": "0.4.0",
"description": "JavaScript obfuscator",

@@ -25,3 +25,3 @@ "main": "index.js",

"start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
"test": "node tests/dev-test.js"
"tests": "node tests/dev-test.js"
},

@@ -28,0 +28,0 @@ "author": {

@@ -58,3 +58,4 @@ #JavaScript obfuscator for Node.js

{
rotateUnicodeArray: false
rotateUnicodeArray: true
// ...
}

@@ -69,2 +70,27 @@ ```

####debugProtection
Type: `boolean` Default: `false`
#####This option can cause browser freeze while Developer Tools is enabled! Use at own risk.
Force enable debug mode in some browsers (mainly based on WebKit) on page load, if Developers Tools panel is enbaled.
With this options using of Debug panel is impossible.
WebKit based browsers: blocking site window, but you still can navigate through Developers Tools panel.
Firefox: *not* blocking site window, but you still can't use Debug panel.
####debugProtectionInterval
Type: `boolean` Default: `false`
#####This option can cause browser freeze even while Developer Tools is disabled! Use at own risk.
Works if `debugProtection` is enabled.
Force enable debug mode in some browsers (mainly based on WebKit) when Developers Tools panel was enbaled, even after page was loaded.
####disableConsoleOutput
Type: `boolean` Default: `true`
Disable `console.log`, `console.info`, `console.error` and `console.warn` messages output into browser console.
####rotateUnicodeArray

@@ -79,2 +105,2 @@ Type: `boolean` Default: `true`

Not recommended for small source code, because helper function will attract attention.
Not recommended for small source code, because helper function will attract attention.
"use strict";
(function (AppendState) {
AppendState[AppendState["BeforeObfuscation"] = 0] = "BeforeObfuscation";
AppendState[AppendState["AfterObfuscation"] = 1] = "AfterObfuscation";
AppendState[AppendState["AfterObfuscation"] = 0] = "AfterObfuscation";
AppendState[AppendState["BeforeObfuscation"] = 1] = "BeforeObfuscation";
})(exports.AppendState || (exports.AppendState = {}));
var AppendState = exports.AppendState;

@@ -1,1 +0,4 @@

export enum AppendState {BeforeObfuscation, AfterObfuscation}
export enum AppendState {
AfterObfuscation,
BeforeObfuscation
}

@@ -1,2 +0,2 @@

import { INode } from '../interfaces/INode';
import { ICustomNode } from '../interfaces/ICustomNode';

@@ -9,3 +9,3 @@ import { INodesGroup } from '../interfaces/INodesGroup';

*/
protected nodes: Map <string, INode>;
protected nodes: Map <string, ICustomNode>;

@@ -15,5 +15,5 @@ /**

*/
public getNodes (): Map <string, INode> {
public getNodes (): Map <string, ICustomNode> {
return this.nodes;
}
}
}
"use strict";
const NodesGroup_1 = require('./NodesGroup');
const UnicodeArrayNode_1 = require('../nodes/UnicodeArrayNode');
const UnicodeArrayRotateFunctionCallNode_1 = require('../nodes/UnicodeArrayRotateFunctionCallNode');
const UnicodeArrayRotateFunctionNode_1 = require('../nodes/UnicodeArrayRotateFunctionNode');
const UnicodeArrayNode_1 = require('../custom-nodes/unicode-array-nodes/UnicodeArrayNode');
const UnicodeArrayRotateFunctionNode_1 = require('../custom-nodes/unicode-array-nodes/UnicodeArrayRotateFunctionNode');
const Utils_1 = require('../Utils');
class UnicodeArrayNodesGroup extends NodesGroup_1.NodesGroup {
constructor(astTree) {
constructor() {
super();
this.unicodeArrayRotateFunctionIdentifier = Utils_1.Utils.getRandomVariableName();
let unicodeArrayName = Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH), unicodeArrayRotateValue = Utils_1.Utils.getRandomInteger(100, 500);
this.unicodeArrayName = Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH);
this.unicodeArrayRotateValue = Utils_1.Utils.getRandomInteger(100, 500);
let unicodeArrayNode = new UnicodeArrayNode_1.UnicodeArrayNode(this.unicodeArrayName, this.unicodeArrayRotateValue), unicodeArray = unicodeArrayNode.getNodeData();
this.nodes = new Map([
[
'unicodeArrayNode',
new UnicodeArrayNode_1.UnicodeArrayNode(astTree, unicodeArrayName, unicodeArrayRotateValue)
unicodeArrayNode
],
[
'unicodeArrayRotateFunctionNode',
new UnicodeArrayRotateFunctionNode_1.UnicodeArrayRotateFunctionNode(astTree, this.unicodeArrayRotateFunctionIdentifier, unicodeArrayName)
],
[
'unicodeArrayRotateFunctionCallNode',
new UnicodeArrayRotateFunctionCallNode_1.UnicodeArrayRotateFunctionCallNode(astTree, this.unicodeArrayRotateFunctionIdentifier, unicodeArrayName, unicodeArrayRotateValue)
new UnicodeArrayRotateFunctionNode_1.UnicodeArrayRotateFunctionNode(this.unicodeArrayName, unicodeArray, this.unicodeArrayRotateValue)
]

@@ -25,0 +21,0 @@ ]);

@@ -1,9 +0,6 @@

import { ITreeNode } from '../interfaces/nodes/ITreeNode';
import { ICustomNode } from '../interfaces/ICustomNode';
import { INode } from '../interfaces/INode';
import { NodesGroup } from './NodesGroup';
import { UnicodeArrayNode } from '../nodes/UnicodeArrayNode';
import { UnicodeArrayRotateFunctionCallNode } from '../nodes/UnicodeArrayRotateFunctionCallNode';
import { UnicodeArrayRotateFunctionNode } from '../nodes/UnicodeArrayRotateFunctionNode';
import { UnicodeArrayNode } from '../custom-nodes/unicode-array-nodes/UnicodeArrayNode';
import { UnicodeArrayRotateFunctionNode } from '../custom-nodes/unicode-array-nodes/UnicodeArrayRotateFunctionNode';
import { Utils } from '../Utils';

@@ -15,21 +12,22 @@

*/
private unicodeArrayRotateFunctionIdentifier: string = Utils.getRandomVariableName();
private unicodeArrayName: string = Utils.getRandomVariableName(UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH);
/**
* @param astTree
* @type {number}
*/
constructor (astTree: ITreeNode) {
private unicodeArrayRotateValue: number = Utils.getRandomInteger(100, 500);
constructor () {
super();
let unicodeArrayName: string = Utils.getRandomVariableName(UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH),
unicodeArrayRotateValue: number = Utils.getRandomInteger(100, 500);
let unicodeArrayNode: UnicodeArrayNode = new UnicodeArrayNode(
this.unicodeArrayName,
this.unicodeArrayRotateValue
),
unicodeArray: string [] = unicodeArrayNode.getNodeData();
this.nodes = new Map <string, INode> ([
this.nodes = new Map <string, ICustomNode> ([
[
'unicodeArrayNode',
new UnicodeArrayNode(
astTree,
unicodeArrayName,
unicodeArrayRotateValue
)
unicodeArrayNode
],

@@ -39,18 +37,9 @@ [

new UnicodeArrayRotateFunctionNode(
astTree,
this.unicodeArrayRotateFunctionIdentifier,
unicodeArrayName
this.unicodeArrayName,
unicodeArray,
this.unicodeArrayRotateValue
)
],
[
'unicodeArrayRotateFunctionCallNode',
new UnicodeArrayRotateFunctionCallNode(
astTree,
this.unicodeArrayRotateFunctionIdentifier,
unicodeArrayName,
unicodeArrayRotateValue
)
]
])
]);
}
}
}
import * as estraverse from 'estraverse';
import { ICatchClauseNode } from "../interfaces/nodes/ICatchClauseNode";
import { ITreeNode } from '../interfaces/nodes/ITreeNode';
import { INode } from '../interfaces/nodes/INode';

@@ -14,3 +14,3 @@ import { NodeObfuscator } from './NodeObfuscator';

*
* by:
* on:
* try {} catch (_0x12d45f) { console.log(_0x12d45f); };

@@ -38,3 +38,3 @@ *

estraverse.replace(catchClauseNode.param, {
leave: (node: ITreeNode, parentNode: ITreeNode) => {
leave: (node: INode, parentNode: INode): any => {
if (NodeUtils.isIdentifierNode(node)) {

@@ -57,3 +57,3 @@ this.catchClauseParam.set(node.name, Utils.getRandomVariableName());

estraverse.replace(catchClauseNode.body, {
leave: (node: ITreeNode, parentNode: ITreeNode) => {
leave: (node: INode, parentNode: INode): any => {
this.replaceNodeIdentifierByNewValue(node, parentNode, this.catchClauseParam);

@@ -60,0 +60,0 @@ }

"use strict";
const estraverse = require('estraverse');
const NodeType_1 = require("../enums/NodeType");
const NodeObfuscator_1 = require('./NodeObfuscator');

@@ -12,3 +13,3 @@ const NodeUtils_1 = require("../NodeUtils");

obfuscateNode(functionDeclarationNode, parentNode) {
if (parentNode.type === 'Program') {
if (parentNode.type === NodeType_1.NodeType.Program) {
return;

@@ -32,3 +33,3 @@ }

replaceFunctionCalls(functionDeclarationNode) {
let scopeNode = NodeUtils_1.NodeUtils.getNodeScope(functionDeclarationNode);
let scopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionDeclarationNode);
estraverse.replace(scopeNode, {

@@ -35,0 +36,0 @@ enter: (node, parentNode) => {

import * as estraverse from 'estraverse';
import { IFunctionDeclarationNode } from "../interfaces/nodes/IFunctionDeclarationNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { NodeType } from "../enums/NodeType";
import { NodeObfuscator } from './NodeObfuscator';

@@ -15,3 +17,3 @@ import { NodeUtils } from "../NodeUtils";

*
* by:
* on:
* function _0x12d45f () { //... };

@@ -30,4 +32,4 @@ * _0x12d45f();

*/
public obfuscateNode (functionDeclarationNode: IFunctionDeclarationNode, parentNode: ITreeNode): void {
if (parentNode.type === 'Program') {
public obfuscateNode (functionDeclarationNode: IFunctionDeclarationNode, parentNode: INode): void {
if (parentNode.type === NodeType.Program) {
return;

@@ -45,3 +47,3 @@ }

estraverse.replace(functionDeclarationNode.id, {
leave: (node: ITreeNode) => {
leave: (node: INode): any => {
if (NodeUtils.isIdentifierNode(node)) {

@@ -63,3 +65,3 @@ this.functionName.set(node.name, Utils.getRandomVariableName());

private replaceFunctionCalls (functionDeclarationNode: IFunctionDeclarationNode): void {
let scopeNode: ITreeNode = NodeUtils.getNodeScope(
let scopeNode: INode = NodeUtils.getBlockScopeOfNode(
functionDeclarationNode

@@ -69,3 +71,3 @@ );

estraverse.replace(scopeNode, {
enter: (node: ITreeNode, parentNode: ITreeNode) => {
enter: (node: INode, parentNode: INode): any => {
this.replaceNodeIdentifierByNewValue(node, parentNode, this.functionName);

@@ -75,2 +77,2 @@ }

}
}
}
import * as estraverse from 'estraverse';
import { IFunctionNode } from "../interfaces/nodes/IFunctionNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";

@@ -14,3 +14,3 @@ import { NodeObfuscator } from './NodeObfuscator';

*
* by:
* on:
* function foo (_0x12d45f) { return _0x12d45f; };

@@ -37,5 +37,5 @@ *

private replaceFunctionParams (functionNode: IFunctionNode): void {
functionNode.params.forEach((paramsNode) => {
functionNode.params.forEach((paramsNode: INode) => {
estraverse.replace(paramsNode, {
leave: (node: ITreeNode) => {
leave: (node: INode): any => {
if (NodeUtils.isIdentifierNode(node)) {

@@ -59,3 +59,3 @@ this.functionParams.set(node.name, Utils.getRandomVariableName());

estraverse.replace(functionNode.body, {
leave: (node: ITreeNode, parentNode: ITreeNode) => {
leave: (node: INode, parentNode: INode): any => {
this.replaceNodeIdentifierByNewValue(node, parentNode, this.functionParams);

@@ -65,2 +65,2 @@ }

}
}
}

@@ -10,15 +10,25 @@ "use strict";

}
if (literalNode['x-verbatim-property']) {
return;
}
let content;
switch (typeof literalNode.value) {
case 'boolean':
content = this.replaceLiteralBooleanByJSFuck(literalNode.value);
break;
case 'number':
content = this.replaceLiteralNumberByHexadecimalValue(literalNode.value);
break;
case 'string':
if (literalNode['x-verbatim-property']) {
break;
}
literalNode['x-verbatim-property'] = {
content: this.replaceLiteralStringByArrayElement(literalNode.value),
precedence: escodegen.Precedence.Primary
};
content = this.replaceLiteralStringByArrayElement(literalNode.value);
break;
default:
return;
}
literalNode['x-verbatim-property'] = {
content: content,
precedence: escodegen.Precedence.Primary
};
}
}
exports.LiteralObfuscator = LiteralObfuscator;

@@ -5,3 +5,3 @@ import * as escodegen from 'escodegen';

import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { NodeObfuscator } from './NodeObfuscator';

@@ -15,3 +15,3 @@ import { NodeUtils } from "../NodeUtils";

*/
public obfuscateNode (literalNode: ILiteralNode, parentNode: ITreeNode): void {
public obfuscateNode (literalNode: ILiteralNode, parentNode: INode): void {
if (NodeUtils.isPropertyNode(parentNode) && parentNode.key === literalNode) {

@@ -21,16 +21,34 @@ return;

if (literalNode['x-verbatim-property']) {
return;
}
let content: string;
switch (typeof literalNode.value) {
case 'boolean':
content = this.replaceLiteralBooleanByJSFuck(<boolean>literalNode.value);
break;
case 'number':
content = this.replaceLiteralNumberByHexadecimalValue(<number>literalNode.value);
break;
case 'string':
if (literalNode['x-verbatim-property']) {
break;
}
content = this.replaceLiteralStringByArrayElement(<string>literalNode.value);
literalNode['x-verbatim-property'] = {
content : this.replaceLiteralStringByArrayElement(<string>literalNode.value),
precedence: escodegen.Precedence.Primary
};
break;
break;
default:
return;
}
literalNode['x-verbatim-property'] = {
content : content,
precedence: escodegen.Precedence.Primary
};
}
}
}
"use strict";
const escodegen = require('escodegen');
const estraverse = require('estraverse');
const NodeType_1 = require("../enums/NodeType");
const NodeObfuscator_1 = require('./NodeObfuscator');

@@ -26,4 +27,2 @@ const NodeUtils_1 = require("../NodeUtils");

let nodeValue = node.name, literalNode = {
type: 'Literal',
value: nodeValue,
raw: `'${nodeValue}'`,

@@ -33,3 +32,5 @@ 'x-verbatim-property': {

precedence: escodegen.Precedence.Primary
}
},
type: NodeType_1.NodeType.Literal,
value: nodeValue
};

@@ -50,2 +51,4 @@ delete node.name;

break;
default:
break;
}

@@ -52,0 +55,0 @@ }

@@ -7,5 +7,7 @@ import * as escodegen from 'escodegen';

import { IMemberExpressionNode } from "../interfaces/nodes/IMemberExpressionNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { NodeObfuscator } from './NodeObfuscator'
import { NodeType } from "../enums/NodeType";
import { NodeObfuscator } from './NodeObfuscator';
import { NodeUtils } from "../NodeUtils";

@@ -19,3 +21,3 @@

estraverse.replace(memberExpressionNode.property, {
leave: (node: ITreeNode, parentNode: ITreeNode) => {
leave: (node: INode, parentNode: INode): any => {
if (NodeUtils.isLiteralNode(node)) {

@@ -43,3 +45,3 @@ this.literalNodeController(node);

*
* by:
* on:
* object[_0x23d45[25]] = 1;

@@ -55,4 +57,2 @@ *

literalNode: ILiteralNode = {
type: 'Literal',
value: nodeValue,
raw: `'${nodeValue}'`,

@@ -62,3 +62,5 @@ 'x-verbatim-property': {

precedence: escodegen.Precedence.Primary
}
},
type: NodeType.Literal,
value: nodeValue
};

@@ -75,3 +77,3 @@

*
* by:
* on:
* object[_0x23d45[25]] = 1;

@@ -94,4 +96,7 @@ *

break;
default:
break;
}
}
}
}

@@ -5,2 +5,3 @@ "use strict";

const NodeUtils_1 = require("../NodeUtils");
const Utils_1 = require("../Utils");
class MethodDefinitionObfuscator extends NodeObfuscator_1.NodeObfuscator {

@@ -18,6 +19,7 @@ constructor(...args) {

if (NodeUtils_1.NodeUtils.isIdentifierNode(node) &&
this.ignoredNames.indexOf(node.name) < 0 &&
!Utils_1.Utils.arrayContains(this.ignoredNames, node.name) &&
methodDefinitionNode.computed === false) {
methodDefinitionNode.computed = true;
node.name = this.replaceLiteralStringByArrayElement(node.name);
return;
}

@@ -24,0 +26,0 @@ return estraverse.VisitorOption.Skip;

import * as estraverse from 'estraverse';
import { IMethodDefinitionNode } from "../interfaces/nodes/IMethodDefinitionNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { NodeObfuscator } from './NodeObfuscator';
import { NodeUtils } from "../NodeUtils";
import { Utils } from "../Utils";

@@ -14,3 +15,3 @@ /**

*
* by:
* on:
* function _0x12d45f () { //... };

@@ -29,3 +30,3 @@ * _0x12d45f();

*/
public obfuscateNode (methodDefinitionNode: IMethodDefinitionNode, parentNode: ITreeNode): void {
public obfuscateNode (methodDefinitionNode: IMethodDefinitionNode, parentNode: INode): void {
this.replaceMethodName(methodDefinitionNode);

@@ -39,6 +40,6 @@ }

estraverse.replace(methodDefinitionNode.key, {
leave: (node: ITreeNode) => {
leave: (node: INode): any => {
if (
NodeUtils.isIdentifierNode(node) &&
this.ignoredNames.indexOf(node.name) < 0 &&
!Utils.arrayContains(this.ignoredNames, node.name) &&
methodDefinitionNode.computed === false

@@ -48,2 +49,4 @@ ) {

node.name = this.replaceLiteralStringByArrayElement(node.name);
return;
}

@@ -55,2 +58,2 @@

}
}
}
"use strict";
const JSFuck_1 = require("../enums/JSFuck");
const NodeUtils_1 = require("../NodeUtils");

@@ -17,4 +18,14 @@ const Utils_1 = require('../Utils');

}
replaceLiteralBooleanByJSFuck(nodeValue) {
return nodeValue ? JSFuck_1.JSFuck.True : JSFuck_1.JSFuck.False;
}
replaceLiteralNumberByHexadecimalValue(nodeValue) {
const prefix = '0x';
if (!Utils_1.Utils.isInteger(nodeValue)) {
return String(nodeValue);
}
return `${prefix}${Utils_1.Utils.decToHex(nodeValue)}`;
}
replaceLiteralStringByArrayElement(nodeValue) {
let value = Utils_1.Utils.stringToUnicode(nodeValue), unicodeArray = this.nodes.get('unicodeArrayNode').getNodeData(), sameIndex = unicodeArray.indexOf(value), index;
let value = Utils_1.Utils.stringToUnicode(nodeValue), unicodeArray = this.nodes.get('unicodeArrayNode').getNodeData(), sameIndex = unicodeArray.indexOf(value), index, hexadecimalIndex;
if (sameIndex < 0) {

@@ -27,5 +38,6 @@ index = unicodeArray.length;

}
return `${this.nodes.get('unicodeArrayNode').getNodeIdentifier()}[${index}]`;
hexadecimalIndex = this.replaceLiteralNumberByHexadecimalValue(index);
return `${this.nodes.get('unicodeArrayNode').getNodeIdentifier()}[${hexadecimalIndex}]`;
}
}
exports.NodeObfuscator = NodeObfuscator;

@@ -1,5 +0,7 @@

import { INode } from '../interfaces/INode';
import { ICustomNode } from '../interfaces/ICustomNode';
import { INodeObfuscator } from '../interfaces/INodeObfuscator';
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { JSFuck } from "../enums/JSFuck";
import { NodeUtils } from "../NodeUtils";

@@ -12,3 +14,3 @@ import { Utils } from '../Utils';

*/
protected nodes: Map <string, INode>;
protected nodes: Map <string, ICustomNode>;

@@ -18,3 +20,3 @@ /**

*/
constructor(nodes: Map <string, INode>) {
constructor(nodes: Map <string, ICustomNode>) {
this.nodes = nodes;

@@ -27,3 +29,3 @@ }

*/
public abstract obfuscateNode (node: ITreeNode, parentNode?: ITreeNode): void;
public abstract obfuscateNode (node: INode, parentNode?: INode): void;

@@ -35,3 +37,3 @@ /**

*/
protected replaceNodeIdentifierByNewValue (node: ITreeNode, parentNode: ITreeNode, namesMap: Map <string, string>) {
protected replaceNodeIdentifierByNewValue (node: INode, parentNode: INode, namesMap: Map <string, string>): void {
if (NodeUtils.isIdentifierNode(node) && namesMap.has(node.name)) {

@@ -53,7 +55,30 @@ if (

*/
protected replaceLiteralBooleanByJSFuck (nodeValue: boolean): string {
return nodeValue ? JSFuck.True : JSFuck.False;
}
/**
* @param nodeValue
* @returns {string}
*/
protected replaceLiteralNumberByHexadecimalValue (nodeValue: number): string {
const prefix: string = '0x';
if (!Utils.isInteger(nodeValue)) {
return String(nodeValue);
}
return `${prefix}${Utils.decToHex(nodeValue)}`;
}
/**
* @param nodeValue
* @returns {string}
*/
protected replaceLiteralStringByArrayElement (nodeValue: string): string {
let value: string = Utils.stringToUnicode(nodeValue),
unicodeArray = this.nodes.get('unicodeArrayNode').getNodeData(),
unicodeArray: string[] = this.nodes.get('unicodeArrayNode').getNodeData(),
sameIndex: number = unicodeArray.indexOf(value),
index: number;
index: number,
hexadecimalIndex: string;

@@ -67,4 +92,6 @@ if (sameIndex < 0) {

return `${this.nodes.get('unicodeArrayNode').getNodeIdentifier()}[${index}]`;
hexadecimalIndex = this.replaceLiteralNumberByHexadecimalValue(index);
return `${this.nodes.get('unicodeArrayNode').getNodeIdentifier()}[${hexadecimalIndex}]`;
}
}
}
"use strict";
const escodegen = require('escodegen');
const estraverse = require('estraverse');
const NodeType_1 = require("../enums/NodeType");
const NodeObfuscator_1 = require('./NodeObfuscator');

@@ -34,2 +35,4 @@ const NodeUtils_1 = require("../NodeUtils");

break;
default:
break;
}

@@ -39,4 +42,2 @@ }

let nodeValue = node.name, literalNode = {
type: 'Literal',
value: nodeValue,
raw: `'${nodeValue}'`,

@@ -46,3 +47,5 @@ 'x-verbatim-property': {

precedence: escodegen.Precedence.Primary
}
},
type: NodeType_1.NodeType.Literal,
value: nodeValue
};

@@ -49,0 +52,0 @@ delete node.name;

@@ -7,5 +7,8 @@ import * as escodegen from 'escodegen';

import { IObjectExpressionNode } from "../interfaces/nodes/IObjectExpressionNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { IPropertyNode } from "../interfaces/nodes/IPropertyNode";
import { INode } from "../interfaces/nodes/INode";
import { NodeObfuscator } from './NodeObfuscator'
import { NodeType } from "../enums/NodeType";
import { NodeObfuscator } from './NodeObfuscator';
import { NodeUtils } from "../NodeUtils";

@@ -21,3 +24,3 @@ import { Utils } from '../Utils';

*
* by:
* on:
* var object = { '\u0050\u0053\u0045\u0055\u0044\u004f': 1 };

@@ -30,5 +33,5 @@ */

public obfuscateNode (objectExpressionNode: IObjectExpressionNode): void {
objectExpressionNode.properties.forEach((property) => {
objectExpressionNode.properties.forEach((property: IPropertyNode) => {
estraverse.replace(property.key, {
leave: (node: ITreeNode, parentNode: ITreeNode) => {
leave: (node: INode, parentNode: INode): any => {
if (NodeUtils.isLiteralNode(node)) {

@@ -64,2 +67,5 @@ this.literalNodeController(node);

break;
default:
break;
}

@@ -74,4 +80,2 @@ }

literalNode: ILiteralNode = {
type: 'Literal',
value: nodeValue,
raw: `'${nodeValue}'`,

@@ -81,3 +85,5 @@ 'x-verbatim-property': {

precedence: escodegen.Precedence.Primary
}
},
type: NodeType.Literal,
value: nodeValue
};

@@ -89,2 +95,2 @@

}
}
}
"use strict";
const estraverse = require('estraverse');
const NodeType_1 = require("../enums/NodeType");
const NodeObfuscator_1 = require('./NodeObfuscator');

@@ -12,3 +13,3 @@ const NodeUtils_1 = require("../NodeUtils");

obfuscateNode(variableDeclarationNode, parentNode) {
if (parentNode.type === 'Program') {
if (parentNode.type === NodeType_1.NodeType.Program) {
return;

@@ -21,11 +22,7 @@ }

variableDeclarationNode.declarations.forEach((declarationNode) => {
estraverse.replace(declarationNode, {
estraverse.replace(declarationNode.id, {
enter: (node) => {
if (NodeUtils_1.NodeUtils.isVariableDeclaratorNode(node)) {
estraverse.replace(node.id, {
enter: (node) => {
this.variableNames.set(node.name, Utils_1.Utils.getRandomVariableName());
node.name = this.variableNames.get(node.name);
}
});
if (NodeUtils_1.NodeUtils.isIdentifierNode(node)) {
this.variableNames.set(node.name, Utils_1.Utils.getRandomVariableName());
node.name = this.variableNames.get(node.name);
return;

@@ -40,9 +37,12 @@ }

let scopeNode;
scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils_1.NodeUtils.getNodeScope(variableDeclarationNode) : variableParentNode;
scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils_1.NodeUtils.getBlockScopeOfNode(variableDeclarationNode) : variableParentNode;
let isNodeAfterVariableDeclaratorFlag = false;
estraverse.replace(scopeNode, {
enter: (node, parentNode) => {
if (node.type === 'FunctionDeclaration' ||
node.type === 'FunctionExpression' ||
node.type === 'ArrowFunctionExpression') {
const functionNodes = [
NodeType_1.NodeType.ArrowFunctionExpression,
NodeType_1.NodeType.FunctionDeclaration,
NodeType_1.NodeType.FunctionExpression
];
if (Utils_1.Utils.arrayContains(functionNodes, node.type)) {
estraverse.replace(node, {

@@ -49,0 +49,0 @@ enter: (node, parentNode) => {

import * as estraverse from 'estraverse';
import { IIdentifierNode } from "../interfaces/nodes/IIdentifierNode";
import { ITreeNode } from "../interfaces/nodes/ITreeNode";
import { INode } from "../interfaces/nodes/INode";
import { IVariableDeclarationNode } from "../interfaces/nodes/IVariableDeclarationNode";
import { IVariableDeclaratorNode } from "../interfaces/nodes/IVariableDeclaratorNode";
import { NodeType } from "../enums/NodeType";
import { NodeObfuscator } from './NodeObfuscator';

@@ -16,3 +18,3 @@ import { NodeUtils } from "../NodeUtils";

*
* by:
* on:
* var _0x12d45f = 1;

@@ -32,4 +34,4 @@ * _0x12d45f++;

*/
public obfuscateNode (variableDeclarationNode: IVariableDeclarationNode, parentNode: ITreeNode): void {
if (parentNode.type === 'Program') {
public obfuscateNode (variableDeclarationNode: IVariableDeclarationNode, parentNode: INode): void {
if (parentNode.type === NodeType.Program) {
return;

@@ -46,12 +48,8 @@ }

private replaceVariableName (variableDeclarationNode: IVariableDeclarationNode): void {
variableDeclarationNode.declarations.forEach((declarationNode) => {
estraverse.replace(declarationNode, {
enter: (node: ITreeNode) => {
if (NodeUtils.isVariableDeclaratorNode(node)) {
estraverse.replace(node.id, {
enter: (node: IIdentifierNode) => {
this.variableNames.set(node.name, Utils.getRandomVariableName());
node.name = this.variableNames.get(node.name);
}
});
variableDeclarationNode.declarations.forEach((declarationNode: IVariableDeclaratorNode) => {
estraverse.replace(declarationNode.id, {
enter: (node: INode): any => {
if (NodeUtils.isIdentifierNode(node)) {
this.variableNames.set(node.name, Utils.getRandomVariableName());
node.name = this.variableNames.get(node.name);

@@ -71,6 +69,6 @@ return;

*/
private replaceVariableCalls (variableDeclarationNode: IVariableDeclarationNode, variableParentNode: ITreeNode): void {
let scopeNode: ITreeNode;
private replaceVariableCalls (variableDeclarationNode: IVariableDeclarationNode, variableParentNode: INode): void {
let scopeNode: INode;
scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils.getNodeScope(
scopeNode = variableDeclarationNode.kind === 'var' ? NodeUtils.getBlockScopeOfNode(
variableDeclarationNode

@@ -82,10 +80,12 @@ ) : variableParentNode;

estraverse.replace(scopeNode, {
enter: (node: ITreeNode, parentNode: ITreeNode) => {
if (
node.type === 'FunctionDeclaration' ||
node.type === 'FunctionExpression' ||
node.type === 'ArrowFunctionExpression'
) {
enter: (node: INode, parentNode: INode): any => {
const functionNodes: string[] = [
NodeType.ArrowFunctionExpression,
NodeType.FunctionDeclaration,
NodeType.FunctionExpression
];
if (Utils.arrayContains(functionNodes, node.type)) {
estraverse.replace(node, {
enter: (node: ITreeNode, parentNode: ITreeNode) => {
enter: (node: INode, parentNode: INode): any => {
this.replaceNodeIdentifierByNewValue(node, parentNode, this.variableNames);

@@ -92,0 +92,0 @@ }

"use strict";
const estraverse = require('estraverse');
const NodeType_1 = require("./enums/NodeType");
const Utils_1 = require("./Utils");
class NodeUtils {
static getNodeScope(node, deep = 0) {
let scopeNodes = [
'FunctionDeclaration',
'FunctionExpression',
'ArrowFunctionExpression',
'MethodDefinition'
];
if (node.parentNode.type === 'Program') {
return node.parentNode;
static addXVerbatimPropertyToLiterals(node) {
estraverse.replace(node, {
enter: (node, parentNode) => {
if (NodeUtils.isLiteralNode(node)) {
node['x-verbatim-property'] = node.raw;
}
}
});
}
static appendNode(blockScopeBody, node) {
if (!NodeUtils.validateNode(node)) {
return;
}
if (scopeNodes.indexOf(node.parentNode.type) < 0) {
return NodeUtils.getNodeScope(node.parentNode, deep);
blockScopeBody.push(node);
}
static getBlockScopeNodeByIndex(node, index = 0) {
if (NodeUtils.isNodeHasBlockScope(node) && node.body[index]) {
return node.body[index];
}
if (deep > 0) {
return NodeUtils.getNodeScope(node.parentNode, --deep);
}
if (node.type !== 'BlockStatement') {
return NodeUtils.getNodeScope(node.parentNode);
}
return node;
}
static getParentNodeWithType(node, types, limitNodeTypes = [], deep = 0) {
if (node.parentNode.type === 'Program' || limitNodeTypes.indexOf(node.parentNode.type) >= 0) {
static getBlockScopeOfNode(node, depth = 0) {
if (!node.parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
if (node.parentNode.type === NodeType_1.NodeType.Program) {
return node.parentNode;
}
if (types.indexOf(node.parentNode.type) < 0) {
return NodeUtils.getParentNodeWithType(node.parentNode, types, limitNodeTypes, deep);
if (!Utils_1.Utils.arrayContains(NodeUtils.scopeNodes, node.parentNode.type)) {
return NodeUtils.getBlockScopeOfNode(node.parentNode, depth);
}
if (deep > 0) {
return NodeUtils.getParentNodeWithType(node.parentNode, types, limitNodeTypes, --deep);
if (depth > 0) {
return NodeUtils.getBlockScopeOfNode(node.parentNode, --depth);
}
return node.parentNode;
if (node.type !== NodeType_1.NodeType.BlockStatement) {
return NodeUtils.getBlockScopeOfNode(node.parentNode);
}
return node;
}
static insertNodeAtIndex(blockScopeBody, node, index) {
if (!NodeUtils.validateNode(node)) {
return;
}
blockScopeBody.splice(index, 0, node);
}
static isBlockStatementNode(node) {
return node.type === 'BlockStatement';
return node.type === NodeType_1.NodeType.BlockStatement;
}
static isIdentifierNode(node) {
return node.type === 'Identifier';
return node.type === NodeType_1.NodeType.Identifier;
}
static isLiteralNode(node) {
return node.type === 'Literal';
return node.type === NodeType_1.NodeType.Literal;
}
static isMemberExpressionNode(node) {
return node.type === 'MemberExpression';
return node.type === NodeType_1.NodeType.MemberExpression;
}
static isNodeHasBlockScope(node) {
return node.hasOwnProperty('body');
}
static isProgramNode(node) {
return node.type === NodeType_1.NodeType.Program;
}
static isPropertyNode(node) {
return node.type === 'Property';
return node.type === NodeType_1.NodeType.Property;
}
static isVariableDeclaratorNode(node) {
return node.type === 'VariableDeclarator';
return node.type === NodeType_1.NodeType.VariableDeclarator;
}
static parentize(node) {
estraverse.replace(node, {
enter: (node, parentNode) => {
Object.defineProperty(node, 'parentNode', {
configurable: true,
enumerable: true,
value: parentNode || node,
writable: true
});
}
});
}
static prependNode(blockScopeBody, node) {
if (!NodeUtils.validateNode(node)) {
return;
}
blockScopeBody.unshift(node);
}
static validateNode(node) {
return !!node;
}
}
NodeUtils.scopeNodes = [
NodeType_1.NodeType.ArrowFunctionExpression,
NodeType_1.NodeType.FunctionDeclaration,
NodeType_1.NodeType.FunctionExpression,
NodeType_1.NodeType.MethodDefinition
];
exports.NodeUtils = NodeUtils;

@@ -0,1 +1,3 @@

import * as estraverse from 'estraverse';
import { IBlockStatementNode } from "./interfaces/nodes/IBlockStatementNode";

@@ -5,37 +7,60 @@ import { IIdentifierNode } from "./interfaces/nodes/IIdentifierNode";

import { IMemberExpressionNode } from "./interfaces/nodes/IMemberExpressionNode";
import { IProgramNode } from "./interfaces/nodes/IProgramNode";
import { IPropertyNode } from "./interfaces/nodes/IPropertyNode";
import { ITreeNode } from './interfaces/nodes/ITreeNode';
import { INode } from './interfaces/nodes/INode';
import { IVariableDeclaratorNode } from "./interfaces/nodes/IVariableDeclaratorNode";
import { BlockScopeNode } from "./types/BlockScopeNode";
import { NodeType } from "./enums/NodeType";
import { Utils } from "./Utils";
export class NodeUtils {
/**
* @type {string[]}
*/
private static scopeNodes: string[] = [
NodeType.ArrowFunctionExpression,
NodeType.FunctionDeclaration,
NodeType.FunctionExpression,
NodeType.MethodDefinition
];
/**
* @param node
* @param deep
* @returns {ITreeNode}
*/
public static getNodeScope (node: ITreeNode, deep: number = 0): ITreeNode {
let scopeNodes: string[] = [
'FunctionDeclaration',
'FunctionExpression',
'ArrowFunctionExpression',
'MethodDefinition'
];
public static addXVerbatimPropertyToLiterals (node: INode): void {
estraverse.replace(node, {
enter: (node: INode, parentNode: INode): any => {
if (NodeUtils.isLiteralNode(node)) {
node['x-verbatim-property'] = node.raw;
}
}
});
}
if (node.parentNode.type === 'Program') {
return node.parentNode;
/**
* @param blockScopeBody
* @param node
*/
public static appendNode (blockScopeBody: INode[], node: INode): void {
if (!NodeUtils.validateNode(node)) {
return;
}
if (scopeNodes.indexOf(node.parentNode.type) < 0) {
return NodeUtils.getNodeScope(node.parentNode, deep);
}
blockScopeBody.push(node);
}
if (deep > 0) {
return NodeUtils.getNodeScope(node.parentNode, --deep);
/**
* @param node
* @param index
* @returns {INode}
*/
public static getBlockScopeNodeByIndex (node: INode, index: number = 0): INode {
if (NodeUtils.isNodeHasBlockScope(node) && node.body[index]) {
return node.body[index];
}
if (node.type !== 'BlockStatement') {
return NodeUtils.getNodeScope(node.parentNode);
}
return node; // BlockStatement of scopeNodes
return node;
}

@@ -45,34 +70,48 @@

* @param node
* @param types
* @param limitNodeTypes
* @param deep
* @returns {ITreeNode}
* @param depth
* @returns {INode}
*/
public static getParentNodeWithType (
node: ITreeNode,
types: string[],
limitNodeTypes: string[] = [],
deep: number = 0
): ITreeNode {
if (node.parentNode.type === 'Program' || limitNodeTypes.indexOf(node.parentNode.type) >= 0) {
return node.parentNode;
public static getBlockScopeOfNode (node: INode, depth: number = 0): BlockScopeNode {
if (!node.parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
if (types.indexOf(node.parentNode.type) < 0) {
return NodeUtils.getParentNodeWithType(node.parentNode, types, limitNodeTypes, deep);
if (node.parentNode.type === NodeType.Program) {
return <BlockScopeNode> node.parentNode;
}
if (deep > 0) {
return NodeUtils.getParentNodeWithType(node.parentNode, types, limitNodeTypes, --deep);
if (!Utils.arrayContains(NodeUtils.scopeNodes, node.parentNode.type)) {
return NodeUtils.getBlockScopeOfNode(node.parentNode, depth);
}
return node.parentNode;
if (depth > 0) {
return NodeUtils.getBlockScopeOfNode(node.parentNode, --depth);
}
if (node.type !== NodeType.BlockStatement) {
return NodeUtils.getBlockScopeOfNode(node.parentNode);
}
return <BlockScopeNode> node; // blocks statement of scopeNodes
}
/**
* @param blockScopeBody
* @param node
* @param index
*/
public static insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void {
if (!NodeUtils.validateNode(node)) {
return;
}
blockScopeBody.splice(index, 0, node);
}
/**
* @param node
* @returns {boolean}
*/
public static isBlockStatementNode (node: ITreeNode): node is IBlockStatementNode {
return node.type === 'BlockStatement';
public static isBlockStatementNode (node: INode): node is IBlockStatementNode {
return node.type === NodeType.BlockStatement;
}

@@ -84,4 +123,4 @@

*/
public static isIdentifierNode (node: ITreeNode): node is IIdentifierNode {
return node.type === 'Identifier';
public static isIdentifierNode (node: INode): node is IIdentifierNode {
return node.type === NodeType.Identifier;
}

@@ -93,4 +132,4 @@

*/
public static isLiteralNode (node: ITreeNode): node is ILiteralNode {
return node.type === 'Literal';
public static isLiteralNode (node: INode): node is ILiteralNode {
return node.type === NodeType.Literal;
}

@@ -102,6 +141,13 @@

*/
public static isMemberExpressionNode (node: ITreeNode): node is IMemberExpressionNode {
return node.type === 'MemberExpression';
public static isMemberExpressionNode (node: INode): node is IMemberExpressionNode {
return node.type === NodeType.MemberExpression;
}
/**
* @param node
* @returns {boolean}
*/
public static isNodeHasBlockScope (node: INode): node is BlockScopeNode {
return node.hasOwnProperty('body');
}

@@ -113,4 +159,4 @@ /**

*/
public static isPropertyNode (node: ITreeNode): node is IPropertyNode {
return node.type === 'Property';
public static isProgramNode (node: INode): node is IProgramNode {
return node.type === NodeType.Program;
}

@@ -123,5 +169,50 @@

*/
public static isVariableDeclaratorNode (node: ITreeNode): node is IVariableDeclaratorNode {
return node.type === 'VariableDeclarator';
public static isPropertyNode (node: INode): node is IPropertyNode {
return node.type === NodeType.Property;
}
/**
*
* @param node
* @returns {boolean}
*/
public static isVariableDeclaratorNode (node: INode): node is IVariableDeclaratorNode {
return node.type === NodeType.VariableDeclarator;
}
/**
* @param node
*/
public static parentize (node: INode): void {
estraverse.replace(node, {
enter: (node: INode, parentNode: INode): any => {
Object.defineProperty(node, 'parentNode', {
configurable: true,
enumerable: true,
value: parentNode || node,
writable: true
});
}
});
}
/**
* @param blockScopeBody
* @param node
*/
public static prependNode (blockScopeBody: INode[], node: INode): void {
if (!NodeUtils.validateNode(node)) {
return;
}
blockScopeBody.unshift(node);
}
/**
* @param node
* @returns {boolean}
*/
private static validateNode (node: INode): boolean {
return !!node;
}
}
"use strict";
const estraverse = require('estraverse');
const AppendState_1 = require('./enums/AppendState');
const CatchClauseObfuscator_1 = require("./node-obfuscators/CatchClauseObfuscator");
const NodeType_1 = require('./enums/NodeType');
const CatchClauseObfuscator_1 = require('./node-obfuscators/CatchClauseObfuscator');
const ConsoleOutputDisableExpressionNode_1 = require('./custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode');
const DebugProtectionNodesGroup_1 = require('./node-groups/DebugProtectionNodesGroup');
const FunctionDeclarationObfuscator_1 = require('./node-obfuscators/FunctionDeclarationObfuscator');

@@ -10,4 +13,5 @@ const FunctionObfuscator_1 = require('./node-obfuscators/FunctionObfuscator');

const MethodDefinitionObfuscator_1 = require('./node-obfuscators/MethodDefinitionObfuscator');
const NodeUtils_1 = require("./NodeUtils");
const ObjectExpressionObfuscator_1 = require('./node-obfuscators/ObjectExpressionObfuscator');
const UnicodeArrayNode_1 = require('./nodes/UnicodeArrayNode');
const UnicodeArrayNode_1 = require('./custom-nodes/unicode-array-nodes/UnicodeArrayNode');
const UnicodeArrayNodesGroup_1 = require('./node-groups/UnicodeArrayNodesGroup');

@@ -17,38 +21,26 @@ const Utils_1 = require('./Utils');

class Obfuscator {
constructor(options) {
constructor(options = {}) {
this.nodes = new Map();
this.nodeObfuscators = new Map([
['ClassDeclaration', [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator]],
['CatchClause', [CatchClauseObfuscator_1.CatchClauseObfuscator]],
['FunctionDeclaration', [
[NodeType_1.NodeType.ArrowFunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]],
[NodeType_1.NodeType.ClassDeclaration, [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator]],
[NodeType_1.NodeType.CatchClause, [CatchClauseObfuscator_1.CatchClauseObfuscator]],
[NodeType_1.NodeType.FunctionDeclaration, [
FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator,
FunctionObfuscator_1.FunctionObfuscator
]],
['ArrowFunctionExpression', [FunctionObfuscator_1.FunctionObfuscator]],
['FunctionExpression', [FunctionObfuscator_1.FunctionObfuscator]],
['MethodDefinition', [MethodDefinitionObfuscator_1.MethodDefinitionObfuscator]],
['VariableDeclaration', [VariableDeclarationObfuscator_1.VariableDeclarationObfuscator]],
['ObjectExpression', [ObjectExpressionObfuscator_1.ObjectExpressionObfuscator]],
['MemberExpression', [MemberExpressionObfuscator_1.MemberExpressionObfuscator]],
['Literal', [LiteralObfuscator_1.LiteralObfuscator]]
[NodeType_1.NodeType.FunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]],
[NodeType_1.NodeType.MemberExpression, [MemberExpressionObfuscator_1.MemberExpressionObfuscator]],
[NodeType_1.NodeType.MethodDefinition, [MethodDefinitionObfuscator_1.MethodDefinitionObfuscator]],
[NodeType_1.NodeType.ObjectExpression, [ObjectExpressionObfuscator_1.ObjectExpressionObfuscator]],
[NodeType_1.NodeType.VariableDeclaration, [VariableDeclarationObfuscator_1.VariableDeclarationObfuscator]],
[NodeType_1.NodeType.Literal, [LiteralObfuscator_1.LiteralObfuscator]]
]);
this.options = {
rotateUnicodeArray: true
};
Object.assign(this.options, options);
this.options = options;
}
obfuscateNode(node) {
if (this.options['rotateUnicodeArray']) {
this.setNodesGroup(new UnicodeArrayNodesGroup_1.UnicodeArrayNodesGroup(node));
}
else {
this.setNode('unicodeArrayNode', new UnicodeArrayNode_1.UnicodeArrayNode(node, Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH)));
}
this.setNewNodes();
NodeUtils_1.NodeUtils.parentize(node);
this.beforeObfuscation(node);
estraverse.replace(node, {
enter: (node, parent) => this.nodeControllerFirstPass(node, parent)
});
estraverse.replace(node, {
leave: (node, parent) => this.nodeControllerSecondPass(node, parent)
});
this.obfuscate(node);
this.afterObfuscation(node);

@@ -65,13 +57,13 @@ }

}
afterObfuscation(node) {
afterObfuscation(astTree) {
this.nodes.forEach((node) => {
if (node.getAppendState() === AppendState_1.AppendState.AfterObfuscation) {
node.appendNode();
node.appendNode(NodeUtils_1.NodeUtils.getBlockScopeOfNode(astTree));
}
});
}
beforeObfuscation(node) {
beforeObfuscation(astTree) {
this.nodes.forEach((node) => {
if (node.getAppendState() === AppendState_1.AppendState.BeforeObfuscation) {
node.appendNode();
node.appendNode(NodeUtils_1.NodeUtils.getBlockScopeOfNode(astTree));
}

@@ -81,17 +73,3 @@ });

;
nodeControllerFirstPass(node, parent) {
Object.defineProperty(node, 'parentNode', {
enumerable: true,
configurable: true,
writable: true,
value: parent || node
});
}
nodeControllerSecondPass(node, parent) {
switch (node.type) {
default:
this.initializeNodeObfuscators(node, parent);
}
}
initializeNodeObfuscators(node, parent) {
initializeNodeObfuscators(node, parentNode) {
if (!this.nodeObfuscators.has(node.type)) {

@@ -101,6 +79,27 @@ return;

this.nodeObfuscators.get(node.type).forEach((obfuscator) => {
new obfuscator(this.nodes).obfuscateNode(node, parent);
new obfuscator(this.nodes).obfuscateNode(node, parentNode);
});
}
obfuscate(node) {
estraverse.replace(node, {
leave: (node, parentNode) => {
this.initializeNodeObfuscators(node, parentNode);
}
});
}
setNewNodes() {
if (this.options['disableConsoleOutput']) {
this.setNode('consoleOutputDisableExpressionNode', new ConsoleOutputDisableExpressionNode_1.ConsoleOutputDisableExpressionNode());
}
if (this.options['debugProtection']) {
this.setNodesGroup(new DebugProtectionNodesGroup_1.DebugProtectionNodesGroup(this.options));
}
if (this.options['rotateUnicodeArray']) {
this.setNodesGroup(new UnicodeArrayNodesGroup_1.UnicodeArrayNodesGroup());
}
else {
this.setNode('unicodeArrayNode', new UnicodeArrayNode_1.UnicodeArrayNode(Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH)));
}
}
}
exports.Obfuscator = Obfuscator;
import * as estraverse from 'estraverse';
import { INode } from './interfaces/INode';
import { ICustomNode } from './interfaces/ICustomNode';
import { INodeObfuscator } from './interfaces/INodeObfuscator';
import { INodesGroup } from './interfaces/INodesGroup';
import { ITreeNode } from './interfaces/nodes/ITreeNode';
import { INode } from './interfaces/nodes/INode';
import { AppendState } from './enums/AppendState';
import { NodeType } from './enums/NodeType';
import { CatchClauseObfuscator } from "./node-obfuscators/CatchClauseObfuscator";
import { CatchClauseObfuscator } from './node-obfuscators/CatchClauseObfuscator';
import { ConsoleOutputDisableExpressionNode } from './custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode';
import { DebugProtectionNodesGroup } from './node-groups/DebugProtectionNodesGroup';
import { FunctionDeclarationObfuscator } from './node-obfuscators/FunctionDeclarationObfuscator';

@@ -16,4 +19,5 @@ import { FunctionObfuscator } from './node-obfuscators/FunctionObfuscator';

import { MethodDefinitionObfuscator } from './node-obfuscators/MethodDefinitionObfuscator';
import { NodeUtils } from "./NodeUtils";
import { ObjectExpressionObfuscator } from './node-obfuscators/ObjectExpressionObfuscator';
import { UnicodeArrayNode } from './nodes/UnicodeArrayNode';
import { UnicodeArrayNode } from './custom-nodes/unicode-array-nodes/UnicodeArrayNode';
import { UnicodeArrayNodesGroup } from './node-groups/UnicodeArrayNodesGroup';

@@ -27,3 +31,3 @@ import { Utils } from './Utils';

*/
private nodes: Map <string, INode> = new Map <string, INode> ();
private nodes: Map <string, ICustomNode> = new Map <string, ICustomNode> ();

@@ -34,15 +38,15 @@ /**

private nodeObfuscators: Map <string, Function[]> = new Map <string, Function[]> ([
['ClassDeclaration', [FunctionDeclarationObfuscator]],
['CatchClause', [CatchClauseObfuscator]],
['FunctionDeclaration', [
[NodeType.ArrowFunctionExpression, [FunctionObfuscator]],
[NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]],
[NodeType.CatchClause, [CatchClauseObfuscator]],
[NodeType.FunctionDeclaration, [
FunctionDeclarationObfuscator,
FunctionObfuscator
]],
['ArrowFunctionExpression', [FunctionObfuscator]],
['FunctionExpression', [FunctionObfuscator]],
['MethodDefinition', [MethodDefinitionObfuscator]],
['VariableDeclaration', [VariableDeclarationObfuscator]],
['ObjectExpression', [ObjectExpressionObfuscator]],
['MemberExpression', [MemberExpressionObfuscator]],
['Literal', [LiteralObfuscator]]
[NodeType.FunctionExpression, [FunctionObfuscator]],
[NodeType.MemberExpression, [MemberExpressionObfuscator]],
[NodeType.MethodDefinition, [MethodDefinitionObfuscator]],
[NodeType.ObjectExpression, [ObjectExpressionObfuscator]],
[NodeType.VariableDeclaration, [VariableDeclarationObfuscator]],
[NodeType.Literal, [LiteralObfuscator]]
]);

@@ -53,5 +57,3 @@

*/
private options: any = {
rotateUnicodeArray: true
};
private options: any;

@@ -61,4 +63,4 @@ /**

*/
constructor (options: any) {
Object.assign(this.options, options);
constructor (options: any = {}) {
this.options = options;
}

@@ -69,22 +71,9 @@

*/
public obfuscateNode (node: ITreeNode): void {
if (this.options['rotateUnicodeArray']) {
this.setNodesGroup(new UnicodeArrayNodesGroup(node));
} else {
this.setNode(
'unicodeArrayNode',
new UnicodeArrayNode(node, Utils.getRandomVariableName(UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH))
);
}
public obfuscateNode (node: INode): void {
this.setNewNodes();
NodeUtils.parentize(node);
this.beforeObfuscation(node);
estraverse.replace(node, {
enter: (node: ITreeNode, parent: ITreeNode) => this.nodeControllerFirstPass(node, parent)
});
estraverse.replace(node, {
leave: (node: ITreeNode, parent: ITreeNode) => this.nodeControllerSecondPass(node, parent)
});
this.obfuscate(node);
this.afterObfuscation(node);

@@ -97,3 +86,3 @@ }

*/
public setNode (nodeName: string, node: INode): void {
public setNode (nodeName: string, node: ICustomNode): void {
this.nodes.set(nodeName, node);

@@ -106,5 +95,5 @@ }

public setNodesGroup (nodesGroup: INodesGroup): void {
let nodes: Map <string, INode> = nodesGroup.getNodes();
let nodes: Map <string, ICustomNode> = nodesGroup.getNodes();
nodes.forEach((node: INode, key: string) => {
nodes.forEach((node: ICustomNode, key: string) => {
this.nodes.set(key, node);

@@ -115,8 +104,8 @@ });

/**
* @param node
* @param astTree
*/
private afterObfuscation (node: ITreeNode): void {
this.nodes.forEach((node: INode) => {
private afterObfuscation (astTree: INode): void {
this.nodes.forEach((node: ICustomNode) => {
if (node.getAppendState() === AppendState.AfterObfuscation) {
node.appendNode();
node.appendNode(NodeUtils.getBlockScopeOfNode(astTree));
}

@@ -127,8 +116,8 @@ });

/**
* @param node
* @param astTree
*/
private beforeObfuscation (node: ITreeNode): void {
this.nodes.forEach((node: INode) => {
private beforeObfuscation (astTree: INode): void {
this.nodes.forEach((node: ICustomNode) => {
if (node.getAppendState() === AppendState.BeforeObfuscation) {
node.appendNode();
node.appendNode(NodeUtils.getBlockScopeOfNode(astTree));
}

@@ -138,12 +127,14 @@ });

/**
* @param node
* @param parent
* @param parentNode
*/
private nodeControllerFirstPass (node: ITreeNode, parent: ITreeNode): void {
Object.defineProperty(node, 'parentNode', {
enumerable: true,
configurable: true,
writable: true,
value: parent || node
private initializeNodeObfuscators (node: INode, parentNode: INode): void {
if (!this.nodeObfuscators.has(node.type)) {
return;
}
this.nodeObfuscators.get(node.type).forEach((obfuscator: Function) => {
new (<INodeObfuscator> obfuscator(this.nodes)).obfuscateNode(node, parentNode);
});

@@ -154,24 +145,35 @@ }

* @param node
* @param parent
*/
private nodeControllerSecondPass (node: ITreeNode, parent: ITreeNode): void {
switch (node.type) {
default:
this.initializeNodeObfuscators(node, parent);
}
private obfuscate (node: INode): void {
estraverse.replace(node, {
leave: (node: INode, parentNode: INode): any => {
this.initializeNodeObfuscators(node, parentNode);
}
});
}
/**
* @param node
* @param parent
*/
private initializeNodeObfuscators (node: ITreeNode, parent: ITreeNode): void {
if (!this.nodeObfuscators.has(node.type)) {
return;
private setNewNodes (): void {
if (this.options['disableConsoleOutput']) {
this.setNode(
'consoleOutputDisableExpressionNode',
new ConsoleOutputDisableExpressionNode()
);
}
this.nodeObfuscators.get(node.type).forEach((obfuscator: Function) => {
new (<INodeObfuscator> obfuscator(this.nodes)).obfuscateNode(node, parent);
});
if (this.options['debugProtection']) {
this.setNodesGroup(new DebugProtectionNodesGroup(this.options));
}
/**
* Important to set this nodes latest to prevent runtime errors cause by `rotateUnicodeArray` option
*/
if (this.options['rotateUnicodeArray']) {
this.setNodesGroup(new UnicodeArrayNodesGroup());
} else {
this.setNode(
'unicodeArrayNode',
new UnicodeArrayNode(Utils.getRandomVariableName(UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH))
);
}
}
}
}
"use strict";
class Utils {
static arrayContains(array, searchElement) {
return array.indexOf(searchElement) >= 0;
}
static arrayRotate(array, times, reverse = false) {

@@ -21,3 +24,3 @@ if (times < 0) {

static decToHex(dec) {
return (dec + Math.pow(16, 6)).toString(16).substr(-6);
return (dec + Math.pow(16, 6)).toString(16).substr(-6).replace(Utils.hexRepetitiveZerosRegExp, '');
}

@@ -28,5 +31,11 @@ static getRandomInteger(min, max) {

static getRandomVariableName(length = 6) {
const prefix = '_0x';
return `${prefix}${(Utils.decToHex(Utils.getRandomInteger(10000, 99999999))).substr(0, length)}`;
const rangeMinInteger = 10000, rangeMaxInteger = 99999999, prefix = '_0x';
return `${prefix}${(Utils.decToHex(Utils.getRandomInteger(rangeMinInteger, rangeMaxInteger))).substr(0, length)}`;
}
static isInteger(number) {
return number % 1 === 0;
}
static strEnumify(obj) {
return obj;
}
static stringToUnicode(string) {

@@ -38,2 +47,3 @@ return `'${string.replace(/[\s\S]/g, (escape) => {

}
Utils.hexRepetitiveZerosRegExp = new RegExp('^(0{2,})+(?!$)', '');
exports.Utils = Utils;
export class Utils {
/**
* @type {RegExp}
*/
private static hexRepetitiveZerosRegExp: RegExp = new RegExp('^(0{2,})+(?!$)', '');
/**
* @param array
* @param searchElement
* @returns {boolean}
*/
public static arrayContains (array: any[], searchElement: any): boolean {
return array.indexOf(searchElement) >= 0;
}
/**
* @param array
* @param times

@@ -34,3 +48,3 @@ * @param reverse

public static decToHex(dec: number): string {
return (dec + Math.pow(16, 6)).toString(16).substr(-6);
return (dec + Math.pow(16, 6)).toString(16).substr(-6).replace(Utils.hexRepetitiveZerosRegExp, '');
}

@@ -52,8 +66,26 @@

public static getRandomVariableName (length: number = 6): string {
const prefix = '_0x';
const rangeMinInteger: number = 10000,
rangeMaxInteger: number = 99999999,
prefix: string = '_0x';
return `${prefix}${(Utils.decToHex(Utils.getRandomInteger(10000, 99999999))).substr(0, length)}`;
return `${prefix}${(Utils.decToHex(Utils.getRandomInteger(rangeMinInteger, rangeMaxInteger))).substr(0, length)}`;
}
/**
* @param number
* @returns {boolean}
*/
public static isInteger (number: number): boolean {
return number % 1 === 0;
}
/**
* @param obj
* @returns {T}
*/
public static strEnumify <T extends {[prop: string]: ''|string}> (obj: T): T {
return obj;
}
/**
* @param string

@@ -63,6 +95,6 @@ * @returns {string}

public static stringToUnicode (string: string): string {
return `'${string.replace(/[\s\S]/g, (escape) => {
return `'${string.replace(/[\s\S]/g, (escape: string): string => {
return `\\u${('0000' + escape.charCodeAt(0).toString(16)).slice(-4)}`;
})}'`;
}
}
}

@@ -1,3 +0,4 @@

var JavaScriptObfuscator = require('../index.js');
var obfuscatedCode = JavaScriptObfuscator.obfuscate(`
"use strict";
const index_1 = require("../index");
let obfuscatedCode = index_1.JavaScriptObfuscator.obfuscate(`
(function(){

@@ -45,4 +46,7 @@ var result = 1,

test2(22);
console.log(105.4);
console.log(true, false);
})();
`, {
disableConsoleOutput: false,
rotateUnicodeArray: false

@@ -49,0 +53,0 @@ });

@@ -1,4 +0,4 @@

var JavaScriptObfuscator = require('../index.js');
import { JavaScriptObfuscator } from "../index";
var obfuscatedCode = JavaScriptObfuscator.obfuscate(
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`

@@ -47,5 +47,8 @@ (function(){

test2(22);
console.log(105.4);
console.log(true, false);
})();
`,
{
disableConsoleOutput: false,
rotateUnicodeArray: false

@@ -56,2 +59,2 @@ }

console.log(obfuscatedCode);
console.log(eval(obfuscatedCode));
console.log(eval(obfuscatedCode));

@@ -6,5 +6,7 @@ {

"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#6834f97fb33561a3ad40695084da2b660efaee29",
"estree": "github:DefinitelyTyped/DefinitelyTyped/estree/estree.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd",
"esprima": "github:DefinitelyTyped/DefinitelyTyped/esprima/esprima.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd"
"estree": "github:DefinitelyTyped/DefinitelyTyped/estree/estree.d.ts",
"esprima": "github:DefinitelyTyped/DefinitelyTyped/esprima/esprima.d.ts",
"escodegen": "github:DefinitelyTyped/DefinitelyTyped/escodegen/escodegen.d.ts",
"estraverse": "github:DefinitelyTyped/DefinitelyTyped/estraverse/estraverse.d.ts"
}
}

@@ -0,3 +1,5 @@

/// <reference path="browser/ambient/escodegen/index.d.ts" />
/// <reference path="browser/ambient/esprima/index.d.ts" />
/// <reference path="browser/ambient/estraverse/index.d.ts" />
/// <reference path="browser/ambient/estree/index.d.ts" />
/// <reference path="browser/ambient/node/index.d.ts" />
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/esprima/esprima.d.ts
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/esprima/esprima.d.ts
// Type definitions for Esprima v2.1.0

@@ -4,0 +4,0 @@ // Project: http://esprima.org

// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/estree/estree.d.ts
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/estree/estree.d.ts
// Type definitions for ESTree AST specification

@@ -4,0 +4,0 @@ // Project: https://github.com/estree/estree

@@ -0,3 +1,5 @@

/// <reference path="main/ambient/escodegen/index.d.ts" />
/// <reference path="main/ambient/esprima/index.d.ts" />
/// <reference path="main/ambient/estraverse/index.d.ts" />
/// <reference path="main/ambient/estree/index.d.ts" />
/// <reference path="main/ambient/node/index.d.ts" />
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/esprima/esprima.d.ts
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/esprima/esprima.d.ts
// Type definitions for Esprima v2.1.0

@@ -4,0 +4,0 @@ // Project: http://esprima.org

// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/estree/estree.d.ts
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/estree/estree.d.ts
// Type definitions for ESTree AST specification

@@ -4,0 +4,0 @@ // Project: https://github.com/estree/estree