|
@@ -12,7 +12,7 @@ import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
|
|
|
describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
describe('variant #1: identifier reference', () => {
|
|
|
const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6})\)/;
|
|
|
- const variableReferenceIdentifierRegExp: RegExp = /eval *\('(_0x(?:[a-f0-9]){4,6});'\);/;
|
|
|
+ const evalExpressionRegExp: RegExp = /eval *\('(_0x(?:[a-f0-9]){4,6});'\);/;
|
|
|
|
|
|
let functionIdentifierName: string | null,
|
|
|
obfuscatedCode: string,
|
|
@@ -30,11 +30,11 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
|
|
|
|
|
functionIdentifierName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp);
|
|
|
- variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should obfuscate eval string', () => {
|
|
|
- assert.match(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ assert.match(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should correctly transform function parameter inside eval expression', () => {
|
|
@@ -44,7 +44,7 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
|
|
|
describe('variant #2: call expression with identifier reference', () => {
|
|
|
const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6})\)/;
|
|
|
- const variableReferenceIdentifierRegExp: RegExp = /eval *\('console\[\\'log\\']\((_0x(?:[a-f0-9]){4,6})\);'\);/;
|
|
|
+ const evalExpressionRegExp: RegExp = /eval *\('console\[\\'log\\']\((_0x(?:[a-f0-9]){4,6})\);'\);/;
|
|
|
|
|
|
let functionIdentifierName: string | null,
|
|
|
obfuscatedCode: string,
|
|
@@ -62,11 +62,11 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
|
|
|
|
|
functionIdentifierName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp);
|
|
|
- variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should obfuscate eval string', () => {
|
|
|
- assert.match(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ assert.match(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should correctly transform function parameter inside eval expression', () => {
|
|
@@ -75,7 +75,7 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
});
|
|
|
|
|
|
describe('variant #3: multiple statements in eval', () => {
|
|
|
- const regExp: RegExp = /eval *\('_0x([a-f0-9]){4,6}; *\\n_0x([a-f0-9]){4,6};'\);/;
|
|
|
+ const regExp: RegExp = /eval *\('_0x([a-f0-9]){4,6}; *_0x([a-f0-9]){4,6};'\);/;
|
|
|
|
|
|
let obfuscatedCode: string;
|
|
|
|
|
@@ -127,7 +127,7 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
|
|
|
describe('variant #5: eval expression as argument', () => {
|
|
|
const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6})\)/;
|
|
|
- const variableReferenceIdentifierRegExp: RegExp = /console\['log']\(eval *\('(_0x(?:[a-f0-9]){4,6});'\)\);/;
|
|
|
+ const evalExpressionRegExp: RegExp = /console\['log']\(eval *\('(_0x(?:[a-f0-9]){4,6});'\)\);/;
|
|
|
|
|
|
let functionIdentifierName: string | null,
|
|
|
obfuscatedCode: string,
|
|
@@ -145,11 +145,11 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
|
|
|
|
|
functionIdentifierName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp);
|
|
|
- variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should obfuscate eval string', () => {
|
|
|
- assert.match(obfuscatedCode, variableReferenceIdentifierRegExp);
|
|
|
+ assert.match(obfuscatedCode, evalExpressionRegExp);
|
|
|
});
|
|
|
|
|
|
it('should correctly transform function parameter inside eval expression', () => {
|
|
@@ -157,7 +157,83 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- describe('variant #6: integration with control flow flattening', () => {
|
|
|
+ describe('variant #6: nested eval expressions', () => {
|
|
|
+ const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6}), *(_0x(?:[a-f0-9]){4,6})\)/;
|
|
|
+ const evalExpressionMatch: string = `` +
|
|
|
+ `eval *\\('` +
|
|
|
+ `var *(_0x(?:[a-f0-9]){4,6}) *= *(_0x(?:[a-f0-9]){4,6}) *\\+ *(_0x(?:[a-f0-9]){4,6});` +
|
|
|
+ `eval\\(\\\\'` +
|
|
|
+ `(_0x(?:[a-f0-9]){4,6}) *\\+ *(_0x(?:[a-f0-9]){4,6});` +
|
|
|
+ `\\\\'\\);` +
|
|
|
+ `'\\);` +
|
|
|
+ ``;
|
|
|
+ const evalExpressionRegExp: RegExp = new RegExp(evalExpressionMatch);
|
|
|
+ const expectedEvaluationResult: number = 4;
|
|
|
+
|
|
|
+ let evaluationResult: number,
|
|
|
+ functionIdentifierAName: string | null,
|
|
|
+ functionIdentifierBName: string | null,
|
|
|
+ obfuscatedCode: string,
|
|
|
+ variableReferenceIdentifierAName1: string | null,
|
|
|
+ variableReferenceIdentifierAName2: string | null,
|
|
|
+ variableReferenceIdentifierBName: string | null,
|
|
|
+ variableReferenceIdentifierCName1: string | null,
|
|
|
+ variableReferenceIdentifierCName2: string | null;
|
|
|
+
|
|
|
+ before(() => {
|
|
|
+ const code: string = readFileAsString(__dirname + '/fixtures/nested-eval-expressions.js');
|
|
|
+ const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
|
|
+ code,
|
|
|
+ {
|
|
|
+ ...NO_ADDITIONAL_NODES_PRESET
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
|
|
+
|
|
|
+ functionIdentifierAName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp, 0);
|
|
|
+ functionIdentifierBName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp, 1);
|
|
|
+
|
|
|
+ // parameter `a` reference inside parent eval expression
|
|
|
+ variableReferenceIdentifierAName1 = getRegExpMatch(obfuscatedCode, evalExpressionRegExp, 1);
|
|
|
+ // parameter `a` reference inside nested eval expression
|
|
|
+ variableReferenceIdentifierAName2 = getRegExpMatch(obfuscatedCode, evalExpressionRegExp, 3);
|
|
|
+ // parameter `b` reference inside parent eval expression
|
|
|
+ variableReferenceIdentifierBName = getRegExpMatch(obfuscatedCode, evalExpressionRegExp, 2);
|
|
|
+ // variable declaration `c` inside parent eval expression
|
|
|
+ variableReferenceIdentifierCName1 = getRegExpMatch(obfuscatedCode, evalExpressionRegExp, 0);
|
|
|
+ // variable `c` reference inside nested eval expression
|
|
|
+ variableReferenceIdentifierCName2 = getRegExpMatch(obfuscatedCode, evalExpressionRegExp, 4);
|
|
|
+
|
|
|
+ evaluationResult = eval(obfuscatedCode);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should obfuscate eval string', () => {
|
|
|
+ assert.match(obfuscatedCode, evalExpressionRegExp);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should generate correct code', () => {
|
|
|
+ assert.equal(evaluationResult, expectedEvaluationResult);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('match #1: should correctly transform function parameter `a` inside eval expression', () => {
|
|
|
+ assert.equal(functionIdentifierAName, variableReferenceIdentifierAName1);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('match #2: should correctly transform function parameter `a` inside nested eval expression', () => {
|
|
|
+ assert.equal(functionIdentifierAName, variableReferenceIdentifierAName2);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('match #3: should correctly transform function parameter `b` inside eval expression', () => {
|
|
|
+ assert.equal(functionIdentifierBName, variableReferenceIdentifierBName);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('match #4: should correctly transform variable declaration and variable reference inside eval and nested eval expressions', () => {
|
|
|
+ assert.equal(variableReferenceIdentifierCName1, variableReferenceIdentifierCName2);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('variant #7: integration with control flow flattening', () => {
|
|
|
const variableMatch: string = '_0x([a-f0-9]){4,6}';
|
|
|
const controlFlowStorageNodeMatch: string = `` +
|
|
|
`var *${variableMatch} *= *\\{` +
|