From f4fd3d74b8d1704012d6348c1c1cea6ac4989f00 Mon Sep 17 00:00:00 2001 From: sanex3339 Date: Tue, 27 Dec 2016 16:49:32 +0300 Subject: [PATCH] FunctionControlFlowTransformer tests --- .../ObjectExpressionCalleeDataExtractor.ts | 5 +- .../function-control-flow-transformer-1.js | 3 + .../function-control-flow-transformer-2.js | 11 +++ ...ConsoleOutputDisableExpressionNode.spec.ts | 1 - .../FunctionControlFlowTransformer.spec.ts | 90 +++++++++++++++++++ test/index.spec.ts | 1 + 6 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-1.js create mode 100644 test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-2.js create mode 100644 test/functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec.ts diff --git a/src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts b/src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts index 23d75c76..80a401bf 100644 --- a/src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts +++ b/src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts @@ -23,10 +23,7 @@ export class ObjectExpressionCalleeDataExtractor extends AbstractCalleeDataExtra functionExpressionName: string|number|null = null; if (Node.isMemberExpressionNode(callee)) { - const objectMembersCallsChain: TObjectMembersCallsChain = this.createObjectMembersCallsChain( - [], - callee - ); + const objectMembersCallsChain: TObjectMembersCallsChain = this.createObjectMembersCallsChain([], callee); if (!objectMembersCallsChain.length) { return null; diff --git a/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-1.js b/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-1.js new file mode 100644 index 00000000..d7ade6fd --- /dev/null +++ b/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-1.js @@ -0,0 +1,3 @@ +(function () { + var variable = 1 + 2; +})(); diff --git a/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-2.js b/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-2.js new file mode 100644 index 00000000..0916c2b8 --- /dev/null +++ b/test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-2.js @@ -0,0 +1,11 @@ +(function () { + function foo () { + function bar () { + function baz () { + function bash () { + var variable = 1 + 2; + } + } + } + } +})(); diff --git a/test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts b/test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts index 6f6edd3c..bf5ffaee 100644 --- a/test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts +++ b/test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts @@ -15,7 +15,6 @@ describe('ConsoleOutputDisableExpressionNode', () => { { ...NO_CUSTOM_NODES_PRESET, disableConsoleOutput: true - } ); diff --git a/test/functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec.ts b/test/functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec.ts new file mode 100644 index 00000000..8181dcb6 --- /dev/null +++ b/test/functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec.ts @@ -0,0 +1,90 @@ +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('FunctionControlFlowTransformer', () => { + const variableMatch: string = '_0x([a-z0-9]){4,6}'; + const rootControlFlowStorageNodeMatch: string = `` + + `var *${variableMatch} *= *\\{` + + `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` + + `return *${variableMatch} *\\+ *${variableMatch};` + + `\\}` + + `\\};` + + ``; + const innerControlFlowStorageNodeMatch: string = `` + + `var *${variableMatch} *= *\\{` + + `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` + + `return *${variableMatch}\\['(\\\\x[a-f0-9]*){3}'\\]\\(${variableMatch}, *${variableMatch}\\);` + + `\\}` + + `\\};` + + ``; + + describe('transformNode (functionNode: ESTree.Function): ESTree.Node', () => { + describe('variant #1 - single `control flow storage` node with single item', () => { + const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate( + readFileAsString( + './test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-1.js' + ), + { + ...NO_CUSTOM_NODES_PRESET, + controlFlowFlattening: true, + controlFlowFlatteningThreshold: 1 + } + ); + const obfuscatedCode: string = obfuscationResult.getObfuscatedCode(); + const regexp: RegExp = new RegExp(rootControlFlowStorageNodeMatch); + + it('should add `control flow storage` node to the obfuscated code', () => { + assert.match(obfuscatedCode, regexp); + }); + }); + + describe('variant #2 - two `control flow storage` nodes: root and inner', () => { + const samplesCount: number = 150; + const delta: number = 0.1; + const expectedValue: number = 0.5; + const regExp1: RegExp = new RegExp( + `\\(function\\(\\) *\\{ *${rootControlFlowStorageNodeMatch}`, + 'g' + ); + const regExp2: RegExp = new RegExp( + `function *${variableMatch} *\\(\\) *\\{ *${innerControlFlowStorageNodeMatch}`, + 'g' + ); + + let totalValue: number = 0; + + for (let i = 0; i < samplesCount; i++) { + const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate( + readFileAsString( + './test/fixtures/node-transformers/node-control-flow-transformers/function-control-flow-transformer-2.js' + ), + { + ...NO_CUSTOM_NODES_PRESET, + controlFlowFlattening: true, + controlFlowFlatteningThreshold: 1 + } + ); + const obfuscatedCode: string = obfuscationResult.getObfuscatedCode(); + + if (regExp1.test(obfuscatedCode)) { + totalValue += obfuscatedCode.match(regExp1)!.length; + + if (regExp2.test(obfuscatedCode)) { + totalValue += obfuscatedCode.match(regExp2)!.length; + } + } + } + + it('should add two `control flow storage` nodes (root and inner) to the obfuscated code in different scopes', () => { + assert.closeTo((totalValue - samplesCount) / samplesCount, expectedValue, delta); + }); + }); + }); +}); diff --git a/test/index.spec.ts b/test/index.spec.ts index 0603adc1..af20e64f 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -30,6 +30,7 @@ import './functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec'; import './functional-tests/custom-nodes/string-array-nodes/StringArrayCallsWrapper.spec'; import './functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.spec'; import './functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec'; +import './functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec'; import './functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.spec'; import './functional-tests/node-transformers/node-obfuscators/CatchClauseObfuscator.spec'; import './functional-tests/node-transformers/node-obfuscators/FunctionDeclarationObfuscator.spec';