mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge pull request #120 from javascript-obfuscator/0.12.2
0.12.2 release
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
Change Log
|
||||
===
|
||||
v0.12.2
|
||||
---
|
||||
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/119
|
||||
|
||||
v0.12.1
|
||||
---
|
||||
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/117
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+5
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "0.12.1",
|
||||
"version": "0.12.2",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
@@ -23,11 +23,11 @@
|
||||
"chance": "1.0.12",
|
||||
"class-validator": "0.7.3",
|
||||
"commander": "2.11.0",
|
||||
"escodegen-wallaby": "1.6.12",
|
||||
"escodegen-wallaby": "1.6.14",
|
||||
"esmangle": "1.0.1",
|
||||
"esprima": "4.0.0",
|
||||
"estraverse": "4.2.0",
|
||||
"inversify": "4.5.0",
|
||||
"inversify": "4.5.1",
|
||||
"md5": "2.2.1",
|
||||
"mkdirp": "0.5.1",
|
||||
"opencollective": "1.0.3",
|
||||
@@ -47,7 +47,7 @@
|
||||
"@types/md5": "2.1.32",
|
||||
"@types/mkdirp": "0.5.1",
|
||||
"@types/mocha": "2.2.44",
|
||||
"@types/node": "8.0.47",
|
||||
"@types/node": "8.0.50",
|
||||
"@types/sinon": "2.3.7",
|
||||
"@types/string-template": "1.0.2",
|
||||
"@types/webpack-env": "1.13.2",
|
||||
@@ -61,7 +61,7 @@
|
||||
"istanbul": "1.1.0-alpha.1",
|
||||
"mocha": "4.0.1",
|
||||
"pre-commit": "1.2.2",
|
||||
"sinon": "4.1.1",
|
||||
"sinon": "4.1.2",
|
||||
"ts-node": "3.3.0",
|
||||
"tslint": "5.8.0",
|
||||
"tslint-eslint-rules": "4.1.1",
|
||||
|
||||
@@ -82,9 +82,9 @@ export class CLIUtils {
|
||||
|
||||
/**
|
||||
* @param {string} outputPath
|
||||
* @param {any} data
|
||||
* @param {string} data
|
||||
*/
|
||||
public static writeFile (outputPath: string, data: any): void {
|
||||
public static writeFile (outputPath: string, data: string): void {
|
||||
mkdirp.sync(path.dirname(outputPath));
|
||||
|
||||
fs.writeFileSync(outputPath, data, {
|
||||
|
||||
+34
-16
@@ -8,8 +8,10 @@ import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatemen
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
import { ITransformersRunner } from '../../interfaces/node-transformers/ITransformersRunner';
|
||||
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
||||
|
||||
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
|
||||
import { NodeType } from '../../enums/node/NodeType';
|
||||
|
||||
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
|
||||
@@ -29,6 +31,18 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
|
||||
*/
|
||||
private static readonly minCollectedBlockStatementsCount: number = 5;
|
||||
|
||||
/**
|
||||
* @type {NodeTransformer[]}
|
||||
*/
|
||||
private static readonly transformersToRenameBlockScopeIdentifiers: NodeTransformer[] = [
|
||||
NodeTransformer.CatchClauseTransformer,
|
||||
NodeTransformer.ClassDeclarationTransformer,
|
||||
NodeTransformer.FunctionDeclarationTransformer,
|
||||
NodeTransformer.FunctionTransformer,
|
||||
NodeTransformer.LabeledStatementTransformer,
|
||||
NodeTransformer.VariableDeclarationTransformer
|
||||
];
|
||||
|
||||
/**
|
||||
* @type {ESTree.BlockStatement[]}
|
||||
*/
|
||||
@@ -40,14 +54,23 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
|
||||
private collectedBlockStatementsLength: number;
|
||||
|
||||
/**
|
||||
* @type {ITransformersRunner}
|
||||
*/
|
||||
private readonly transformersRunner: ITransformersRunner;
|
||||
|
||||
/**
|
||||
* @param {ITransformersRunner} transformersRunner
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @param {IOptions} options
|
||||
*/
|
||||
constructor (
|
||||
@inject(ServiceIdentifiers.ITransformersRunner) transformersRunner: ITransformersRunner,
|
||||
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions
|
||||
) {
|
||||
super(randomGenerator, options);
|
||||
|
||||
this.transformersRunner = transformersRunner;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,15 +154,14 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
|
||||
blockStatementNode: ESTree.BlockStatement,
|
||||
collectedBlockStatements: ESTree.BlockStatement[]
|
||||
): void {
|
||||
const clonedBlockStatementNode: ESTree.BlockStatement = NodeUtils.clone(blockStatementNode);
|
||||
|
||||
let nestedBlockStatementsCount: number = 0,
|
||||
let clonedBlockStatementNode: ESTree.BlockStatement = NodeUtils.clone(blockStatementNode),
|
||||
nestedBlockStatementsCount: number = 0,
|
||||
isValidBlockStatementNode: boolean = true;
|
||||
|
||||
estraverse.replace(clonedBlockStatementNode, {
|
||||
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): any => {
|
||||
/**
|
||||
* First step: count nested block statements in current block statement
|
||||
* Count nested block statements in current block statement
|
||||
*/
|
||||
if (NodeGuards.isBlockStatementNode(node)) {
|
||||
nestedBlockStatementsCount++;
|
||||
@@ -159,18 +181,6 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Second step: rename all identifiers (except identifiers in member expressions)
|
||||
* in current block statement
|
||||
*/
|
||||
if (
|
||||
NodeGuards.isIdentifierNode(node) &&
|
||||
parentNode &&
|
||||
!NodeGuards.isMemberExpressionNode(parentNode)
|
||||
) {
|
||||
node.name = this.randomGenerator.getRandomVariableName(6);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
});
|
||||
@@ -179,6 +189,14 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We should transform identifiers in the dead code block statement to avoid conflicts with original code
|
||||
*/
|
||||
clonedBlockStatementNode = this.transformersRunner.transform(
|
||||
clonedBlockStatementNode,
|
||||
DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers
|
||||
);
|
||||
|
||||
collectedBlockStatements.push(clonedBlockStatementNode);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,14 +109,41 @@ export class FunctionTransformer extends AbstractNodeTransformer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Property[]} properties
|
||||
* @param {Set<string>} ignoredIdentifierNamesSet
|
||||
*/
|
||||
private addIdentifiersToIgnoredIdentifierNamesSet (
|
||||
properties: ESTree.Property[],
|
||||
ignoredIdentifierNamesSet: Set<string>
|
||||
): void {
|
||||
properties.forEach((property: ESTree.Property) => {
|
||||
if (!NodeGuards.isIdentifierNode(property.key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ignoredIdentifierNamesSet.add(property.key.name);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function} functionNode
|
||||
* @param {number} nodeIdentifier
|
||||
*/
|
||||
private replaceFunctionParams (functionNode: ESTree.Function, nodeIdentifier: number): void {
|
||||
const ignoredIdentifierNamesSet: Set<string> = new Set();
|
||||
|
||||
const replaceVisitor: estraverse.Visitor = {
|
||||
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): any => {
|
||||
if (parentNode && NodeGuards.isReplaceableIdentifierNode(node, parentNode)) {
|
||||
if (NodeGuards.isObjectPatternNode(node)) {
|
||||
this.addIdentifiersToIgnoredIdentifierNamesSet(node.properties, ignoredIdentifierNamesSet);
|
||||
}
|
||||
|
||||
if (
|
||||
parentNode &&
|
||||
NodeGuards.isReplaceableIdentifierNode(node, parentNode) &&
|
||||
!ignoredIdentifierNamesSet.has(node.name)
|
||||
) {
|
||||
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer.replace(node.name, nodeIdentifier);
|
||||
const newIdentifierName: string = newIdentifier.name;
|
||||
|
||||
|
||||
@@ -221,7 +221,9 @@ export class NodeGuards {
|
||||
parentNode.property === node
|
||||
);
|
||||
|
||||
return !parentNodeIsPropertyNode && !parentNodeIsMemberExpressionNode && !NodeGuards.isLabelIdentifierNode(node, parentNode);
|
||||
return !parentNodeIsPropertyNode &&
|
||||
!parentNodeIsMemberExpressionNode &&
|
||||
!NodeGuards.isLabelIdentifierNode(node, parentNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+29
-4
@@ -190,26 +190,26 @@ describe('DeadCodeInjectionTransformer', () => {
|
||||
`if *\\(${variableMatch}\\('${hexMatch}'\\) *=== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
|
||||
`console.*` +
|
||||
`\\} *else *\\{` +
|
||||
`${variableMatch}.*` +
|
||||
`alert.*` +
|
||||
`\\}` +
|
||||
``;
|
||||
const match2: string = `` +
|
||||
`if *\\(${variableMatch}\\('${hexMatch}'\\) *!== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
|
||||
`console.*` +
|
||||
`\\} *else *\\{` +
|
||||
`${variableMatch}.*` +
|
||||
`alert.*` +
|
||||
`\\}` +
|
||||
``;
|
||||
const match3: string = `` +
|
||||
`if *\\(${variableMatch}\\('${hexMatch}'\\) *=== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
|
||||
`${variableMatch}.*` +
|
||||
`alert.*` +
|
||||
`\\} *else *\\{` +
|
||||
`console.*` +
|
||||
`\\}` +
|
||||
``;
|
||||
const match4: string = `` +
|
||||
`if *\\(${variableMatch}\\('${hexMatch}'\\) *!== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
|
||||
`${variableMatch}.*` +
|
||||
`alert.*` +
|
||||
`\\} *else *\\{` +
|
||||
`console.*` +
|
||||
`\\}` +
|
||||
@@ -309,5 +309,30 @@ describe('DeadCodeInjectionTransformer', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('variant #7 - correct obfuscation of dead-code block statements', () => {
|
||||
const variableName: string = 'importantVariableName';
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/obfuscation-of-dead-code-block-statements.js');
|
||||
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_CUSTOM_NODES_PRESET,
|
||||
deadCodeInjection: true,
|
||||
deadCodeInjectionThreshold: 1,
|
||||
debugProtection: true
|
||||
}
|
||||
);
|
||||
|
||||
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should correctly obfuscate dead-code block statements and prevent any exposing of internal variable names', () => {
|
||||
assert.notInclude(obfuscatedCode, variableName);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
function test() {
|
||||
var importantVariableName = 'test';
|
||||
|
||||
return importantVariableName.indexOf('test');
|
||||
}
|
||||
+46
-17
@@ -49,29 +49,58 @@ describe('FunctionTransformer', () => {
|
||||
});
|
||||
|
||||
describe('object pattern as parameter', () => {
|
||||
const functionParameterRegExp: RegExp = /function *\(\{ *bar *\}\) *\{/;
|
||||
const functionBodyRegExp: RegExp = /return *bar;/;
|
||||
describe('variant #1: simple', () => {
|
||||
const functionParameterRegExp: RegExp = /function *\(\{ *bar *\}\) *\{/;
|
||||
const functionBodyRegExp: RegExp = /return *bar;/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/object-pattern-as-parameter.js');
|
||||
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_CUSTOM_NODES_PRESET
|
||||
}
|
||||
);
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/object-pattern-as-parameter-1.js');
|
||||
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_CUSTOM_NODES_PRESET
|
||||
}
|
||||
);
|
||||
|
||||
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
||||
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform function parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, functionParameterRegExp);
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform function parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, functionBodyRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform function parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, functionParameterRegExp);
|
||||
});
|
||||
describe('variant #2: correct transformation when identifier with same name in parent scope exist', () => {
|
||||
const callbackParameterRegExp: RegExp = /\['then'] *\(\({ *data *}\)/;
|
||||
const callbackBodyRegExp: RegExp = /console\['log']\(data\)/;
|
||||
|
||||
it('match #2: shouldn\'t transform function parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, functionBodyRegExp);
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/object-pattern-as-parameter-2.js');
|
||||
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_CUSTOM_NODES_PRESET
|
||||
}
|
||||
);
|
||||
|
||||
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform callback parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, callbackParameterRegExp);
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform callback parameter object pattern identifier', () => {
|
||||
assert.match(obfuscatedCode, callbackBodyRegExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
(function(){
|
||||
function foo (data) {
|
||||
new Promise((resolve) => resolve({data: data}))
|
||||
.then(({data}) => console.log(data));
|
||||
}
|
||||
|
||||
foo(1);
|
||||
})();
|
||||
@@ -52,10 +52,14 @@
|
||||
version "2.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e"
|
||||
|
||||
"@types/node@*", "@types/node@8.0.47":
|
||||
"@types/node@*":
|
||||
version "8.0.47"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.47.tgz#968e596f91acd59069054558a00708c445ca30c2"
|
||||
|
||||
"@types/node@8.0.50":
|
||||
version "8.0.50"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.50.tgz#dc545448e128c88c4eec7cd64025fcc3b7604541"
|
||||
|
||||
"@types/sinon@2.3.7":
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.7.tgz#e92c2fed3297eae078d78d1da032b26788b4af86"
|
||||
@@ -1413,9 +1417,9 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
|
||||
escodegen-wallaby@1.6.12:
|
||||
version "1.6.12"
|
||||
resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.12.tgz#dac2ed380daca6c7a2c9e8496d50c091239fe26f"
|
||||
escodegen-wallaby@1.6.14:
|
||||
version "1.6.14"
|
||||
resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.14.tgz#41a0a7a2a2bd776207d25b4d2f373f12853de23f"
|
||||
dependencies:
|
||||
esprima "^2.7.1"
|
||||
estraverse "^1.9.1"
|
||||
@@ -2037,9 +2041,9 @@ invariant@^2.2.2:
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
inversify@4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.5.0.tgz#1a575ddf1db216ed3292d9b0f70f497de275874e"
|
||||
inversify@4.5.1:
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.5.1.tgz#2f8a249e1fc5346e4f28b4b86dfae5af1b673178"
|
||||
|
||||
invert-kv@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -2300,14 +2304,14 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
|
||||
js-yaml@3.6.1:
|
||||
js-yaml@3.6.1, js-yaml@3.x:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^2.6.0"
|
||||
|
||||
js-yaml@3.x, js-yaml@^3.7.0:
|
||||
js-yaml@^3.7.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
|
||||
dependencies:
|
||||
@@ -2475,9 +2479,9 @@ lolex@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
|
||||
|
||||
lolex@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.1.3.tgz#53f893bbe88c80378156240e127126b905c83087"
|
||||
lolex@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.0.tgz#d6bad0f0aa5caebffcfebb09fb2caa89baaff51c"
|
||||
|
||||
longest@^1.0.1:
|
||||
version "1.0.1"
|
||||
@@ -3431,14 +3435,14 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
|
||||
sinon@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.1.tgz#bd657be815df608887fe1f0b75f9590ec563748a"
|
||||
sinon@4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.2.tgz#65610521d926fb53742dd84cd599f0b89a82f440"
|
||||
dependencies:
|
||||
diff "^3.1.0"
|
||||
formatio "1.2.0"
|
||||
lodash.get "^4.4.2"
|
||||
lolex "^2.1.3"
|
||||
lolex "^2.2.0"
|
||||
nise "^1.2.0"
|
||||
supports-color "^4.4.0"
|
||||
type-detect "^4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user