mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge remote-tracking branch 'origin/custom-nodes-transformer' into custom-nodes-transformer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
+44
-6
@@ -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<string, number>((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,
|
||||
+6
-6
@@ -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
|
||||
+11
-11
@@ -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';
|
||||
+4
-3
@@ -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
|
||||
|
||||
+58
-22
@@ -16,80 +16,116 @@ describe('MangledIdentifierNamesGenerator', () => {
|
||||
let identifierNamesGenerator: IIdentifierNamesGenerator,
|
||||
mangledIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
beforeEach(() => {
|
||||
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
|
||||
|
||||
inversifyContainerFacade.load('', {});
|
||||
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user