123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- import { assert } from 'chai';
- import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
- import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
- import { readFileAsString } from '../../../helpers/readFileAsString';
- import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
- describe('BlockStatementControlFlowTransformer', () => {
- describe('transformNode (blockStatementNode: ESTree.BlockStatement): ESTree.Node', () => {
- describe('variant #1: 5 simple statements', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-1.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1,
- unicodeEscapeSequence: false
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp1: RegExp = /console\['log'\]\(0x1\);/;
- const statementRegExp2: RegExp = /console\['log'\]\(0x2\);/;
- const statementRegExp3: RegExp = /console\['log'\]\(0x3\);/;
- const statementRegExp4: RegExp = /console\['log'\]\(0x4\);/;
- const statementRegExp5: RegExp = /console\['log'\]\(0x5\);/;
- const switchCaseRegExp: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/;
- const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
- const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
- const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-z0-9]){4,6} *= *'(.*?)'/;
- const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
- const switchCaseMapMatch: string = switchCaseMapMatches[1];
- const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
- it('should save all statements', () => {
- assert.match(obfuscatedCode, statementRegExp1);
- assert.match(obfuscatedCode, statementRegExp2);
- assert.match(obfuscatedCode, statementRegExp3);
- assert.match(obfuscatedCode, statementRegExp4);
- assert.match(obfuscatedCode, statementRegExp5);
- });
- it('should wrap block statement statements in switch case structure', () => {
- assert.match(obfuscatedCode, switchCaseRegExp);
- assert.equal(switchCaseLength, 5);
- });
- it('should create variable with order of switch cases sequence', () => {
- assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
- });
- });
- describe('variant #2: 5 simple statements inside while loop without break or continue statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-2.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1,
- unicodeEscapeSequence: false
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp1: RegExp = /console\['log'\]\(0x1\);/;
- const statementRegExp2: RegExp = /console\['log'\]\(0x2\);/;
- const statementRegExp3: RegExp = /console\['log'\]\(0x3\);/;
- const statementRegExp4: RegExp = /console\['log'\]\(0x4\);/;
- const statementRegExp5: RegExp = /console\['log'\]\(0x5\);/;
- const switchCaseRegExp: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/;
- const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
- const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
- const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-z0-9]){4,6} *= *'(.*?)'/;
- const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
- const switchCaseMapMatch: string = switchCaseMapMatches[1];
- const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
- it('should save all statements', () => {
- assert.match(obfuscatedCode, statementRegExp1);
- assert.match(obfuscatedCode, statementRegExp2);
- assert.match(obfuscatedCode, statementRegExp3);
- assert.match(obfuscatedCode, statementRegExp4);
- assert.match(obfuscatedCode, statementRegExp5);
- });
- it('should wrap block statement statements in switch case structure', () => {
- assert.match(obfuscatedCode, switchCaseRegExp);
- assert.equal(switchCaseLength, 5);
- });
- it('should create variable with order of switch cases sequence', () => {
- assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
- });
- });
- describe('variant #3: less then 5 statements', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-one-statement.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\); *\} *\( *\) *\);$/;
- it('shouldn\'t transform block statement if statements length less than 5', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #4: const declaration inside block statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-const-declaration.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
- it('shouldn\'t transform block statement if block statement contain variable declaration with `const` kind', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #5: let declaration inside block statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-let-declaration.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
- it('shouldn\'t transform block statement if block statement contain variable declaration with `let` kind', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #6: break statement inside block statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-break-statement.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *break; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
- it('shouldn\'t transform block statement if block statement contain break statement', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #7: continue statement inside block statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-continue-statement.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *continue; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
- it('shouldn\'t transform block statement if block statement contain continue statement', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #8: function declaration inside block statement', () => {
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-function-declaration.js'
- ),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: 1
- }
- );
- const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
- const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-z0-9]){4,6} *\( *\) *\{ *\} *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
- it('shouldn\'t transform block statement if block statement contain function declaration', () => {
- assert.match(obfuscatedCode, statementRegExp);
- });
- });
- describe('variant #9: `controlFlowFlatteningThreshold` chance', () => {
- const samples: number = 1000;
- const controlFlowFlatteningThreshold: number = 0.5;
- const delta: number = 0.1;
- const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
- readFileAsString(
- './test/fixtures/node-transformers/control-flow-transformers/block-statement-control-flow-transformer-1.js'
- ).repeat(samples),
- {
- ...NO_CUSTOM_NODES_PRESET,
- controlFlowFlattening: true,
- controlFlowFlatteningThreshold: controlFlowFlatteningThreshold,
- }
- );
- const regExp1: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/g;
- const regExp2: RegExp = /\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/g;
- const transformedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
- const untouchedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
- it('should transform block statement with `controlFlowFlatteningThreshold` chance', () => {
- assert.closeTo(transformedStatementMatchesLength / samples, controlFlowFlatteningThreshold, delta);
- assert.closeTo(untouchedStatementMatchesLength / samples, controlFlowFlatteningThreshold, delta);
- });
- });
- });
- });
|