🚀 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.7.2

Change Log
===
v0.7.2
---
* runtime error fix [#7](https://github.com/sanex3339/webpack-obfuscator/issues/7)
* shorthand object expression fix [#16](https://github.com/sanex3339/javascript-obfuscator/issues/16)
v0.7.1

@@ -5,0 +11,0 @@ ---

{
"name": "javascript-obfuscator",
"version": "0.7.1",
"version": "0.7.2",
"description": "JavaScript obfuscator",

@@ -25,6 +25,6 @@ "keywords": [

"chance": "^1.0.4",
"class-validator": "^0.5.0",
"class-validator": "^0.6.1",
"commander": "^2.9.0",
"escodegen": "^1.8.1",
"esprima": "^2.7.2",
"esprima": "^3.0.0",
"estraverse": "^4.2.0",

@@ -36,29 +36,29 @@ "format-unicorn": "^1.1.0",

"devDependencies": {
"@types/chai": "^3.4.31",
"@types/chai": "^3.4.32",
"@types/chance": "^0.7.28",
"@types/commander": "^2.3.29",
"@types/escodegen": "^0.0.3",
"@types/esprima": "^2.1.30",
"@types/estraverse": "^0.0.3",
"@types/format-unicorn": "^0.0.28",
"@types/joi": "^9.0.30",
"@types/escodegen": "0.0.3",
"@types/esprima": "^2.1.31",
"@types/estraverse": "0.0.3",
"@types/format-unicorn": "^0.0.29",
"@types/joi": "^9.0.31",
"@types/mkdirp": "^0.3.28",
"@types/mocha": "^2.2.30",
"@types/mocha": "^2.2.31",
"@types/node": "^4.0.30",
"@types/sinon": "^1.16.28",
"babel-cli": "^6.11.4",
"@types/sinon": "^1.16.29",
"babel-cli": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.13.2",
"babel-preset-es2015": "^6.14.0",
"chai": "^3.5.0",
"chai-members-deep": "^1.1.0",
"coveralls": "^2.11.12",
"coveralls": "^2.11.14",
"istanbul": "1.1.0-alpha.1",
"mocha": "^3.0.2",
"sinon": "^2.0.0-pre.2",
"optimize-js-plugin": "0.0.4",
"sinon": "^2.0.0-pre.3",
"ts-loader": "^0.8.2",
"ts-node": "^1.3.0",
"tslint": "^3.14.0",
"tslint": "^3.15.1",
"typescript": "^2.0.0",
"webpack": "^2.1.0-beta.21",
"webpack-node-externals": "^1.3.3"
"webpack": "^2.1.0-beta.25",
"webpack-node-externals": "^1.4.3"
},

@@ -88,2 +88,2 @@ "repository": {

"license": "BSD-2-Clause"
}
}
export interface INode {
type: string;
parentNode?: INode;
obfuscated?: boolean;
}

@@ -35,3 +35,3 @@ import * as estraverse from 'estraverse';

estraverse.traverse(catchClauseNode.param, {
leave: (node: INode): any => this.storeIdentifiersNames(node, this.catchClauseParam)
enter: (node: INode): any => this.storeIdentifiersNames(node, this.catchClauseParam)
});

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

estraverse.replace(catchClauseNode, {
leave: (node: INode, parentNode: INode): any => {
enter: (node: INode, parentNode: INode): any => {
this.replaceIdentifiersWithRandomNames(node, parentNode, this.catchClauseParam);

@@ -48,0 +48,0 @@ }

@@ -44,3 +44,3 @@ import * as estraverse from 'estraverse';

estraverse.traverse(functionDeclarationNode.id, {
leave: (node: INode): any => this.storeIdentifiersNames(node, this.functionName)
enter: (node: INode): any => this.storeIdentifiersNames(node, this.functionName)
});

@@ -47,0 +47,0 @@ }

@@ -7,2 +7,3 @@ import * as estraverse from 'estraverse';

import { NodeObfuscator } from './NodeObfuscator';
import { Nodes } from "../Nodes";

@@ -38,3 +39,3 @@ /**

estraverse.traverse(paramsNode, {
leave: (node: INode): any => this.storeIdentifiersNames(node, this.functionParams)
enter: (node: INode): any => this.storeIdentifiersNames(node, this.functionParams)
});

@@ -49,4 +50,16 @@ });

let replaceVisitor: estraverse.Visitor = {
leave: (node: INode, parentNode: INode): any => {
enter: (node: INode, parentNode: INode): any => {
let newNodeName: string = '';
if (Nodes.isIdentifierNode(node)) {
newNodeName = node.name;
}
this.replaceIdentifiersWithRandomNames(node, parentNode, this.functionParams);
if (Nodes.isIdentifierNode(node)) {
if (node.name !== newNodeName) {
node.obfuscated = true;
}
}
}

@@ -53,0 +66,0 @@ };

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

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

@@ -23,0 +23,0 @@ this.obfuscateLiteralProperty(node);

@@ -33,2 +33,6 @@ import * as escodegen from 'escodegen';

.forEach((property: IPropertyNode) => {
if (property.shorthand) {
property.shorthand = false;
}
estraverse.replace(property.key, {

@@ -35,0 +39,0 @@ leave: (node: INode, parentNode: INode): any => {

@@ -11,3 +11,2 @@ import * as estraverse from 'estraverse';

import { NodeUtils } from "../NodeUtils";
import { Utils } from '../Utils';

@@ -62,26 +61,7 @@ /**

variableDeclarationNode
) : variableParentNode,
isNodeAfterVariableDeclaratorFlag: boolean = false;
) : variableParentNode;
estraverse.replace(scopeNode, {
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: INode, parentNode: INode): any => {
this.replaceIdentifiersWithRandomNames(node, parentNode, this.variableNames);
}
});
}
if (node === variableDeclarationNode) {
isNodeAfterVariableDeclaratorFlag = true;
}
if (isNodeAfterVariableDeclaratorFlag) {
if (!node.obfuscated) {
this.replaceIdentifiersWithRandomNames(node, parentNode, this.variableNames);

@@ -88,0 +68,0 @@ }

@@ -15,2 +15,3 @@ import { IBlockStatementNode } from "./interfaces/nodes/IBlockStatementNode";

import { NodeType } from "./enums/NodeType";
import { ICallExpressionNode } from "./interfaces/nodes/ICallExpressionNode";

@@ -26,3 +27,4 @@ export class Nodes {

'body': bodyNode,
'sourceType': 'script'
'sourceType': 'script',
'obfuscated': false
};

@@ -43,2 +45,10 @@ }

*/
public static isCallExpressionNode (node: INode): node is ICallExpressionNode {
return node.type === NodeType.CallExpression;
}
/**
* @param node
* @returns {boolean}
*/
public static isIdentifierNode (node: INode): node is IIdentifierNode {

@@ -45,0 +55,0 @@ return node.type === NodeType.Identifier;

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

node['parentNode'] = value;
node['obfuscated'] = false;
}

@@ -157,0 +158,0 @@ });

@@ -134,3 +134,3 @@ import * as estraverse from 'estraverse';

estraverse.replace(node, {
leave: (node: INode, parentNode: INode): any => {
enter: (node: INode, parentNode: INode): any => {
this.initializeNodeObfuscators(node, parentNode);

@@ -137,0 +137,0 @@ }

@@ -59,2 +59,7 @@ 'use strict';

var sA = 'shorthand1';
var sB = 'shorthand2';
console.log({sA, sB});
try {

@@ -61,0 +66,0 @@ } catch (error) {

@@ -27,2 +27,20 @@ import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";

});
it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`
(function () {
let a = 0;
let b = 0;
var test = {a, b};
})();
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/var *_0x[a-z0-9]{4,6} *= *\{'\\x61': *_0x[a-z0-9]{4,6}\, *'\\x62': *_0x[a-z0-9]{4,6}\};/
);
});
});

@@ -21,4 +21,4 @@ import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";

assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){6} *= *'\\x61\\x62\\x63';/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){6}\);/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4,6} *= *'\\x61\\x62\\x63';/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
});

@@ -39,5 +39,63 @@

assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){6}\);/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
});
describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
let obfuscationResult: IObfuscationResult,
functionParamIdentifierName: string|null,
innerFunctionParamIdentifierName: string|null,
constructorIdentifierName: string|null,
objectIdentifierName: string|null,
variableDeclarationIdentifierName: string|null;
beforeEach(() => {
obfuscationResult = JavaScriptObfuscator.obfuscate(
`
(function () {
function foo (t, e) {
return function () {
function baz (t) {
console.log(t);
}
return {t: t};
var t;
}();
}
})();
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
});
it('should correct obfuscate variables inside function body', () => {
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function *_0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\,(_0x[a-z0-9]{5,6})\) *\{/);
const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function _0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\) *\{/);
const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/return\{'\\x74':(_0x[a-z0-9]{5,6})\}/);
const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/var *(_0x[a-z0-9]{5,6});/);
functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
assert.equal(functionParamIdentifierName, objectIdentifierName);
assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
});
});
it('should not obfuscate variable call (`identifier` node) outside of block scope of node in which this variable was declared with `let` kind', () => {

@@ -83,9 +141,9 @@ let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(

it('should obfuscate variable call (`identifier` node) before variable declaration if this call is inside function body', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){6}\['\\x69\\x74\\x65\\x6d'\]\);/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\['\\x69\\x74\\x65\\x6d'\]\);/);
});
it('should not obfuscate variable call (`identifier` node) before variable declaration', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(abc\);/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){5,6}\);/);
});
});
});

@@ -26,2 +26,3 @@ import { BabelPolyfill } from './polyfills/BabelPolyfill';

import './functional-tests/JavaScriptObfuscatorInternal.spec';
import './functional-tests/node-obfuscators/FunctionObfuscator.spec';
import './functional-tests/node-obfuscators/LiteralObfuscator.spec';

@@ -28,0 +29,0 @@ import './functional-tests/node-obfuscators/MemberExpressionObfuscator.spec';

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

body: bodyNodes,
sourceType: 'script'
sourceType: 'script',
obfuscated: false
};

@@ -43,3 +44,4 @@ }

type: NodeType.BlockStatement,
body: bodyNodes
body: bodyNodes,
obfuscated: false
};

@@ -56,3 +58,4 @@ }

param: NodeMocks.getIdentifierNode('err'),
body: NodeMocks.getBlockStatementNode(bodyNodes)
body: NodeMocks.getBlockStatementNode(bodyNodes),
obfuscated: false
};

@@ -73,3 +76,4 @@ }

callee: callee,
arguments: args
arguments: args,
obfuscated: false
};

@@ -87,3 +91,4 @@ }

type: NodeType.ExpressionStatement,
expression: expression
expression: expression,
obfuscated: false
};

@@ -109,3 +114,4 @@ }

generator: false,
expression: false
expression: false,
obfuscated: false
};

@@ -124,6 +130,8 @@ }

value: true,
raw: 'true'
raw: 'true',
obfuscated: false
},
consequent: blockStatementNode,
alternate: null
alternate: null,
obfuscated: false
};

@@ -140,2 +148,3 @@ }

name: identifierName,
obfuscated: false
};

@@ -156,3 +165,4 @@ }

precedence: escodegen.Precedence.Primary
}
},
obfuscated: false
};

@@ -174,3 +184,4 @@ }

object: object,
property: property
property: property,
obfuscated: false
};

@@ -191,3 +202,4 @@ }

declarations: declarations,
kind: kind
kind: kind,
obfuscated: false
};

@@ -205,5 +217,6 @@ }

id: id,
init: init
init: init,
obfuscated: false
};
}
}

@@ -17,4 +17,2 @@ import * as chai from 'chai';

chai.use(require('chai-members-deep'));
const assert: any = chai.assert;

@@ -106,3 +104,3 @@

it('should convert code to `INode` structure', () => {
assert.deepEqualIdent(NodeUtils.convertCodeToStructure(code), variableDeclarationNode);
assert.deepEqual(NodeUtils.convertCodeToStructure(code), variableDeclarationNode);
});

@@ -109,0 +107,0 @@ });

'use strict';
let fs = require("fs"),
var fs = require("fs"),
nodeExternals = require('webpack-node-externals'),

@@ -8,7 +8,4 @@ webpack = require('webpack');

function getLicenseText () {
return `/*
Copyright (C) 2016 Timofey Kachalov <sanex3339@yandex.ru>
${fs.readFileSync('./LICENSE.BSD', 'utf8')}
*/`;
return "/*\nCopyright (C) 2016 Timofey Kachalov <sanex3339@yandex.ru>\n\n" +
fs.readFileSync('./LICENSE.BSD', 'utf8') + "\n*/";
}

@@ -29,4 +26,3 @@

resolve: {
extensions: ['', '.ts'],
modulesDirectories: ['./src', './node_modules']
extensions: ['.ts']
},

@@ -36,7 +32,7 @@ plugins: [

{
banner: `${getLicenseText()}\n\nrequire("source-map-support").install();\n`,
banner: getLicenseText() + '\n\nrequire("source-map-support").install();\n',
raw: true,
entryOnly: false
}
)
),
],

@@ -49,2 +45,2 @@ output: {

}
};
};

Sorry, the diff of this file is too big to display