diff --git a/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts b/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts index 9db6bb4f..b34ab45a 100644 --- a/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts +++ b/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts @@ -52,20 +52,10 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene private static generateNewMangledName (previousMangledName: string): string { const generateNewMangledName: (name: string) => string = (name: string): string => { const nameSequence: string[] = MangledIdentifierNamesGenerator.nameSequence; - const zeroSequenceCache: string[] = []; const nameLength: number = name.length; const zeroSequence: (num: number) => string = (num: number): string => { - let result: string = zeroSequenceCache[num]; - - if (result !== undefined) { - return result; - } - - result = '0'.repeat(num); - zeroSequenceCache[num] = result; - - return result; + return '0'.repeat(num); }; let index: number = nameLength - 1; @@ -78,7 +68,8 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene if (indexInSequence !== lastNameSequenceIndex) { const previousNamePart: string = name.substring(0, index); const nextCharacter: string = nameSequence[indexInSequence + 1]; - const zeroSequenceCharacters: string = zeroSequence(nameLength - (index + 1)); + const zeroSequenceLength: number = nameLength - (index + 1); + const zeroSequenceCharacters: string = zeroSequence(zeroSequenceLength); return previousNamePart + nextCharacter + zeroSequenceCharacters; } diff --git a/src/node/NodeAppender.ts b/src/node/NodeAppender.ts index 5fffcff0..b34fe6cc 100644 --- a/src/node/NodeAppender.ts +++ b/src/node/NodeAppender.ts @@ -13,10 +13,6 @@ export class NodeAppender { * @param {TStatement[]} scopeStatements */ public static appendNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void { - if (!NodeAppender.validateScopeStatements(scopeStatements)) { - scopeStatements = []; - } - scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements); NodeAppender.setScopeNodeStatements(scopeNode, [ @@ -112,10 +108,6 @@ export class NodeAppender { * @param {number} index */ public static insertNodeAtIndex (scopeNode: TNodeWithScope, scopeStatements: TStatement[], index: number): void { - if (!NodeAppender.validateScopeStatements(scopeStatements)) { - scopeStatements = []; - } - scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements); NodeAppender.setScopeNodeStatements(scopeNode, [ @@ -130,10 +122,6 @@ export class NodeAppender { * @param {TStatement[]} scopeStatements */ public static prependNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void { - if (!NodeAppender.validateScopeStatements(scopeStatements)) { - scopeStatements = []; - } - scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements); NodeAppender.setScopeNodeStatements(scopeNode, [ @@ -180,14 +168,4 @@ export class NodeAppender { scopeNode.body = statements; } - - /** - * @param {TStatement[]} scopeStatement - * @returns {boolean} - */ - private static validateScopeStatements (scopeStatement: TStatement[]): boolean { - return scopeStatement.every((statementNode: TStatement) => { - return !!statementNode && statementNode.hasOwnProperty('type'); - }); - } } diff --git a/src/node/Nodes.ts b/src/node/Nodes.ts index 1527e6af..cbaa65e5 100644 --- a/src/node/Nodes.ts +++ b/src/node/Nodes.ts @@ -101,19 +101,6 @@ export class Nodes { return breakStatementNode; } - /** - * @param {Statement[]} body - * @returns {CatchClause} - */ - public static getCatchClauseNode (body: ESTree.Statement[] = []): ESTree.CatchClause { - return { - type: NodeType.CatchClause, - param: Nodes.getIdentifierNode('err'), - body: Nodes.getBlockStatementNode(body), - obfuscatedNode: false - }; - } - /** * @param {Expression} callee * @param {(Expression | SpreadElement)[]} args @@ -231,20 +218,6 @@ export class Nodes { }; } - /** - * @param {Identifier} label - * @param {Statement} body - * @returns {LabeledStatement} - */ - public static getLabeledStatement (label: ESTree.Identifier, body: ESTree.Statement): ESTree.LabeledStatement { - return { - type: NodeType.LabeledStatement, - label, - body, - obfuscatedNode: false - }; - } - /** * @param {boolean | number | string} value * @param {string} raw diff --git a/test/functional-tests/templates/GlobalVariableNoEvalTemplate.spec.ts b/test/functional-tests/templates/GlobalVariableNoEvalTemplate.spec.ts new file mode 100644 index 00000000..e17b60a6 --- /dev/null +++ b/test/functional-tests/templates/GlobalVariableNoEvalTemplate.spec.ts @@ -0,0 +1,77 @@ +import 'reflect-metadata'; + +import * as format from 'string-template'; + +import { assert } from 'chai'; + +import { GlobalVariableNoEvalTemplate } from '../../../src/templates/GlobalVariableNoEvalTemplate'; + +describe('GlobalVariableNoEvalTemplate (): string', () => { + describe('variant #1: simple', () => { + const expectedGlobalObject: NodeJS.Global = global; + + let globalObject: NodeJS.Global; + + before(() => { + const globalVariableNoEvalTemplate: string = format(GlobalVariableNoEvalTemplate()); + + globalObject = Function(` + ${globalVariableNoEvalTemplate} + + return that; + `)(); + }); + + it('should correctly return global object', () => { + assert.deepEqual(globalObject, expectedGlobalObject); + }); + }); + + describe('variant #2: call inside function', () => { + const expectedGlobalObject: NodeJS.Global = global; + + let globalObject: NodeJS.Global; + + before(() => { + const globalVariableNoEvalTemplate: string = format(GlobalVariableNoEvalTemplate()); + + globalObject = Function(` + return (function () { + ${globalVariableNoEvalTemplate} + + return that; + })(); + `)(); + }); + + it('should correctly return global object', () => { + assert.deepEqual(globalObject, expectedGlobalObject); + }); + }); + + describe('variant #3: return `window`', () => { + const expectedGlobalObject: {} = { + document: {} + }; + + let globalObject: NodeJS.Global; + + before(() => { + const globalVariableNoEvalTemplate: string = format(GlobalVariableNoEvalTemplate()); + + globalObject = Function(` + this.window = { + document: {} + }; + + ${globalVariableNoEvalTemplate} + + return that; + `)(); + }); + + it('should correctly return `window` object', () => { + assert.deepEqual(globalObject, expectedGlobalObject); + }); + }); +}); diff --git a/test/functional-tests/templates/custom-nodes/debug-protection-nodes/DebufProtectionFunctionCallTemplate.spec.ts b/test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts similarity index 74% rename from test/functional-tests/templates/custom-nodes/debug-protection-nodes/DebufProtectionFunctionCallTemplate.spec.ts rename to test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts index e7ea6a66..d899b56e 100644 --- a/test/functional-tests/templates/custom-nodes/debug-protection-nodes/DebufProtectionFunctionCallTemplate.spec.ts +++ b/test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts @@ -1,13 +1,15 @@ import { assert } from 'chai'; import { spawn } from 'threads'; -import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult'; +import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult'; -import { readFileAsString } from '../../../../helpers/readFileAsString'; +import { readFileAsString } from '../../../helpers/readFileAsString'; -import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes'; +import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes'; -import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade'; +import { ObfuscationTarget } from '../../../../src/enums/ObfuscationTarget'; + +import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscatorFacade'; function spawnThread(inputCallback: Function, threadCallback: Function, timeoutCallback: Function): void { const thread = spawn((input: string, postMessage: Function) => { @@ -100,7 +102,43 @@ describe('DebugProtectionFunctionCallTemplate (): string', () => { }); }); - describe('variant #3: obfuscated code with removed debug protection code', () => { + describe('variant #3: correctly obfuscated code with target `extension`', () => { + const expectedEvaluationResult: number = 1; + + let obfuscatedCode: string, + evaluationResult: number = 0; + + beforeEach((done) => { + const code: string = readFileAsString(__dirname + '/fixtures/input.js'); + const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate( + code, + { + ...NO_ADDITIONAL_NODES_PRESET, + debugProtection: true, + target: ObfuscationTarget.Extension + } + ); + + obfuscatedCode = obfuscationResult.getObfuscatedCode(); + + spawnThread( + () => obfuscatedCode, + (response: number) => { + evaluationResult = response; + done(); + }, + () => { + done(); + } + ); + }); + + it('should correctly evaluate code with enabled debug protection', () => { + assert.equal(evaluationResult, expectedEvaluationResult); + }); + }); + + describe('variant #4: obfuscated code with removed debug protection code', () => { const expectedEvaluationResult: number = 0; let obfuscatedCode: string, @@ -136,7 +174,7 @@ describe('DebugProtectionFunctionCallTemplate (): string', () => { }); }); - describe('variant #4: single call of debug protection code', () => { + describe('variant #5: single call of debug protection code', () => { const expectedEvaluationResult: number = 1; let obfuscatedCode: string, diff --git a/test/functional-tests/templates/custom-nodes/debug-protection-nodes/fixtures/input.js b/test/functional-tests/templates/debug-protection-nodes/fixtures/input.js similarity index 100% rename from test/functional-tests/templates/custom-nodes/debug-protection-nodes/fixtures/input.js rename to test/functional-tests/templates/debug-protection-nodes/fixtures/input.js diff --git a/test/functional-tests/templates/custom-nodes/debug-protection-nodes/fixtures/single-call.js b/test/functional-tests/templates/debug-protection-nodes/fixtures/single-call.js similarity index 100% rename from test/functional-tests/templates/custom-nodes/debug-protection-nodes/fixtures/single-call.js rename to test/functional-tests/templates/debug-protection-nodes/fixtures/single-call.js diff --git a/test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts b/test/functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec.ts similarity index 87% rename from test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts rename to test/functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec.ts index 47ccbc32..0bfe9cd1 100644 --- a/test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts +++ b/test/functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec.ts @@ -2,15 +2,15 @@ import * as format from 'string-template'; import { assert } from 'chai'; -import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifiers'; +import { ServiceIdentifiers } from '../../../../src/container/ServiceIdentifiers'; -import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils'; -import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade'; +import { ICryptUtils } from '../../../../src/interfaces/utils/ICryptUtils'; +import { IInversifyContainerFacade } from '../../../../src/interfaces/container/IInversifyContainerFacade'; -import { DomainLockNodeTemplate } from '../../../../../src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate'; -import { GlobalVariableTemplate1 } from '../../../../../src/templates/GlobalVariableTemplate1'; +import { DomainLockNodeTemplate } from '../../../../src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate'; +import { GlobalVariableTemplate1 } from '../../../../src/templates/GlobalVariableTemplate1'; -import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade'; +import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade'; /** * @param templateData diff --git a/test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts b/test/functional-tests/templates/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts similarity index 77% rename from test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts rename to test/functional-tests/templates/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts index 300c5207..9081afd0 100644 --- a/test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts +++ b/test/functional-tests/templates/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts @@ -4,20 +4,20 @@ import * as format from 'string-template'; import { assert } from 'chai'; -import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifiers'; +import { ServiceIdentifiers } from '../../../../src/container/ServiceIdentifiers'; -import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils'; -import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade'; -import { IRandomGenerator } from '../../../../../src/interfaces/utils/IRandomGenerator'; +import { ICryptUtils } from '../../../../src/interfaces/utils/ICryptUtils'; +import { IInversifyContainerFacade } from '../../../../src/interfaces/container/IInversifyContainerFacade'; +import { IRandomGenerator } from '../../../../src/interfaces/utils/IRandomGenerator'; -import { AtobTemplate } from '../../../../../src/templates/AtobTemplate'; -import { GlobalVariableTemplate1 } from '../../../../../src/templates/GlobalVariableTemplate1'; -import { Rc4Template } from '../../../../../src/templates/Rc4Template'; -import { StringArrayBase64DecodeNodeTemplate } from '../../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate'; -import { StringArrayCallsWrapperTemplate } from '../../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate'; -import { StringArrayRc4DecodeNodeTemplate } from '../../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate'; +import { AtobTemplate } from '../../../../src/templates/AtobTemplate'; +import { GlobalVariableTemplate1 } from '../../../../src/templates/GlobalVariableTemplate1'; +import { Rc4Template } from '../../../../src/templates/Rc4Template'; +import { StringArrayBase64DecodeNodeTemplate } from '../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate'; +import { StringArrayCallsWrapperTemplate } from '../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate'; +import { StringArrayRc4DecodeNodeTemplate } from '../../../../src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate'; -import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade'; +import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade'; describe('StringArrayCallsWrapperNodeTemplate (): string', () => { const stringArrayName: string = 'stringArrayName'; diff --git a/test/index.spec.ts b/test/index.spec.ts index 71fd19b9..ea096807 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -68,9 +68,10 @@ import './functional-tests/node-transformers/preparing-transformers/eval-call-ex import './functional-tests/node-transformers/preparing-transformers/comments-transformer/CommentsTransformer.spec'; import './functional-tests/node-transformers/preparing-transformers/obfuscating-guards/black-list-obfuscating-guard/BlackListObfuscatingGuard.spec'; import './functional-tests/node-transformers/preparing-transformers/obfuscating-guards/conditional-comment-obfuscating-guard/ConditionalCommentObfuscatingGuard.spec'; -import './functional-tests/templates/custom-nodes/debug-protection-nodes/DebufProtectionFunctionCallTemplate.spec'; -import './functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec'; -import './functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec'; +import './functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec'; +import './functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec'; +import './functional-tests/templates/GlobalVariableNoEvalTemplate.spec'; +import './functional-tests/templates/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec'; /** * Performance tests diff --git a/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts b/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts index 876fed90..85443665 100644 --- a/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts +++ b/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts @@ -16,80 +16,116 @@ describe('MangledIdentifierNamesGenerator', () => { let identifierNamesGenerator: IIdentifierNamesGenerator, mangledIdentifierName: string; - before(() => { + beforeEach(() => { const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade(); inversifyContainerFacade.load('', {}); identifierNamesGenerator = inversifyContainerFacade.getNamed( ServiceIdentifiers.IIdentifierNamesGenerator, IdentifierNamesGenerator.MangledIdentifierNamesGenerator - ) + ); }); describe('variant #1: initial mangled name', () => { const expectedMangledIdentifierName: string = 'a'; - before(() => { + beforeEach(() => { mangledIdentifierName = identifierNamesGenerator.generate(4); }); - it('should return hexadecimal name', () => { + it('should return mangled name', () => { assert.equal(mangledIdentifierName, expectedMangledIdentifierName); - }) + }); }); describe('variant #2: second mangled name', () => { const expectedMangledIdentifierName: string = 'b'; + const expectedMangledIdentifierPosition: number = 1; - before(() => { - mangledIdentifierName = identifierNamesGenerator.generate(6); + beforeEach(() => { + for (let i: number = 0; i <= expectedMangledIdentifierPosition; i++) { + mangledIdentifierName = identifierNamesGenerator.generate(6); + } }); - it('should return hexadecimal name', () => { + it('should return mangled name', () => { assert.equal(mangledIdentifierName, expectedMangledIdentifierName); - }) + }); }); describe('variant #3: last mangled name with single character', () => { const expectedMangledIdentifierName: string = 'Z'; + const expectedMangledIdentifierPosition: number = 51; - before(() => { - for (let i: number = 0; i <= 49; i++) { + beforeEach(() => { + for (let i: number = 0; i <= expectedMangledIdentifierPosition; i++) { mangledIdentifierName = identifierNamesGenerator.generate(6); } }); - it('should return hexadecimal name', () => { + it('should return mangled name', () => { assert.equal(mangledIdentifierName, expectedMangledIdentifierName); - }) + }); }); describe('variant #4: correct increase of mangled name length', () => { const expectedMangledIdentifierName: string = 'a0'; + const expectedMangledIdentifierPosition: number = 52; - before(() => { - for (let i: number = 0; i < 1; i++) { + beforeEach(() => { + for (let i: number = 0; i <= expectedMangledIdentifierPosition; i++) { mangledIdentifierName = identifierNamesGenerator.generate(6); } }); - it('should return hexadecimal name', () => { + it('should return mangled name', () => { assert.equal(mangledIdentifierName, expectedMangledIdentifierName); - }) + }); }); - describe('variant #4: correct increase of mangled name length #2', () => { + describe('variant #5: correct increase of mangled name length #2', () => { const expectedMangledIdentifierName: string = 'aa'; + const expectedMangledIdentifierPosition: number = 62; - before(() => { - for (let i: number = 0; i < 10; i++) { + beforeEach(() => { + for (let i: number = 0; i <= expectedMangledIdentifierPosition; i++) { mangledIdentifierName = identifierNamesGenerator.generate(6); } }); - it('should return hexadecimal name', () => { + it('should return mangled name', () => { assert.equal(mangledIdentifierName, expectedMangledIdentifierName); - }) + }); + }); + + describe('variant #6: reserved names', () => { + const expectedMangledIdentifierName1: string = 'dn'; + const expectedMangledIdentifierName2: string = 'dp'; + const expectedMangledIdentifierPosition1: number = 261; + const expectedMangledIdentifierPosition2: number = 262; + + let mangledIdentifierName1: string, + mangledIdentifierName2: string; + + beforeEach(() => { + for (let i: number = 0; i <= expectedMangledIdentifierPosition2; i++) { + mangledIdentifierName = identifierNamesGenerator.generate(6); + + if (i === expectedMangledIdentifierPosition1) { + mangledIdentifierName1 = mangledIdentifierName; + } else if (i === expectedMangledIdentifierPosition2) { + mangledIdentifierName2 = mangledIdentifierName; + } + } + }); + + it('should return mangled name', () => { + assert.equal(mangledIdentifierName1, expectedMangledIdentifierName1); + }); + + it('shouldn\'t return reserved mangled name', () => { + assert.equal(mangledIdentifierName2, expectedMangledIdentifierName2); + }); }); }); });