From 31b2d71b0ea011a985ccff6ea8a648d069dc17b9 Mon Sep 17 00:00:00 2001 From: sanex3339 Date: Wed, 14 Dec 2016 12:13:48 +0300 Subject: [PATCH] control flow flattening improvements WIP: correct removing of control flow storage nodes which will be replaced --- dist/index.js | 107 ++++++++++++------ .../FunctionControlFlowTransformer.ts | 50 +++++--- 2 files changed, 104 insertions(+), 53 deletions(-) diff --git a/dist/index.js b/dist/index.js index ed7da95e..6d939bfb 100644 --- a/dist/index.js +++ b/dist/index.js @@ -957,7 +957,7 @@ var JavaScriptObfuscator = function () { } _createClass(JavaScriptObfuscator, null, [{ - key: "obfuscate", + key: 'obfuscate', value: function obfuscate(sourceCode) { var inputOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; @@ -966,7 +966,7 @@ var JavaScriptObfuscator = function () { return javaScriptObfuscator.obfuscate(sourceCode); } }, { - key: "runCLI", + key: 'runCLI', value: function runCLI(argv) { new JavaScriptObfuscatorCLI_1.JavaScriptObfuscatorCLI(argv).run(); } @@ -4164,7 +4164,8 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function var _this = _possibleConstructorReturn(this, (FunctionControlFlowTransformer.__proto__ || Object.getPrototypeOf(FunctionControlFlowTransformer)).call(this, options)); - _this.cachedControlFlowData = new Map(); + _this.controlFlowData = new Map(); + _this.controlFlowNodesList = []; _this.controlFlowStorageFactory = controlFlowStorageFactory; _this.controlFlowReplacerFactory = controlFlowReplacerFactory; _this.customNodeFactory = customNodeFactory; @@ -4186,24 +4187,53 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function } var controlFlowStorage = this.controlFlowStorageFactory(); var hostNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionNode.body, RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomInteger(1, 5)); - var controlFlowStorageCustomNodeName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(6); - if (!this.cachedControlFlowData.has(hostNode)) { - this.cachedControlFlowData.set(hostNode, { + var controlFlowStorageNodeName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(6); + if (!this.controlFlowData.has(hostNode)) { + this.controlFlowData.set(hostNode, { controlFlowStorage: controlFlowStorage, - controlFlowStorageNodeName: controlFlowStorageCustomNodeName + controlFlowStorageNodeName: controlFlowStorageNodeName }); } else { - hostNode.body.shift(); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; - var _cachedControlFlowDat = this.cachedControlFlowData.get(hostNode), - hostControlFlowStorage = _cachedControlFlowDat.controlFlowStorage, - hostControlFlowStorageNodeName = _cachedControlFlowDat.controlFlowStorageNodeName; + try { + for (var _iterator = this.controlFlowNodesList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var controlFlowNode = _step.value; + + var firstIndexOfNode = hostNode.body.indexOf(controlFlowNode[0]); + if (firstIndexOfNode === -1) { + continue; + } + var statementLength = controlFlowNode.length; + hostNode.body.splice(firstIndexOfNode, statementLength); + break; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + var _controlFlowData$get = this.controlFlowData.get(hostNode), + hostControlFlowStorage = _controlFlowData$get.controlFlowStorage, + hostControlFlowStorageNodeName = _controlFlowData$get.controlFlowStorageNodeName; hostControlFlowStorage.getStorage().forEach(function (customNode, key) { controlFlowStorage.set(key, customNode); }); - controlFlowStorageCustomNodeName = hostControlFlowStorageNodeName; - this.cachedControlFlowData.set(hostNode, { + controlFlowStorageNodeName = hostControlFlowStorageNodeName; + this.controlFlowData.set(hostNode, { controlFlowStorage: controlFlowStorage, controlFlowStorageNodeName: hostControlFlowStorageNodeName }); @@ -4214,15 +4244,17 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function if (controlFlowReplacerName === undefined) { return; } - return __assign({}, _this2.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName), { parentNode: parentNode }); + return __assign({}, _this2.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage, controlFlowStorageNodeName), { parentNode: parentNode }); } }); if (!controlFlowStorage.getLength()) { return; } var controlFlowStorageCustomNode = this.customNodeFactory(CustomNodes_1.CustomNodes.ControlFlowStorageNode); - controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageCustomNodeName); - NodeAppender_1.NodeAppender.prependNode(hostNode, controlFlowStorageCustomNode.getNode()); + controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageNodeName); + var controlFlowStorageNode = controlFlowStorageCustomNode.getNode(); + this.controlFlowNodesList.push(controlFlowStorageNode); + NodeAppender_1.NodeAppender.prependNode(hostNode, controlFlowStorageNode); } }]); @@ -5559,7 +5591,7 @@ var class_validator_1 = __webpack_require__(115); var DefaultPreset_1 = __webpack_require__(31); var OptionsNormalizer_1 = __webpack_require__(84); var ValidationErrorsFormatter_1 = __webpack_require__(85); -var Options = Options_1 = function Options(inputOptions) { +var Options_1 = function Options(inputOptions) { _classCallCheck(this, Options); Object.assign(this, DefaultPreset_1.DEFAULT_PRESET, inputOptions); @@ -5569,41 +5601,42 @@ var Options = Options_1 = function Options(inputOptions) { } Object.assign(this, OptionsNormalizer_1.OptionsNormalizer.normalizeOptions(this)); }; +var Options = Options_1; Options.validatorOptions = { validationError: { target: false } }; -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "compact", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "controlFlowFlattening", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtection", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtectionInterval", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "disableConsoleOutput", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "compact", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "controlFlowFlattening", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtection", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtectionInterval", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "disableConsoleOutput", void 0); __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({ each: true -}), __metadata("design:type", Array)], Options.prototype, "domainLock", void 0); +}), __metadata('design:type', Array)], Options.prototype, "domainLock", void 0); __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({ each: true -}), __metadata("design:type", Array)], Options.prototype, "reservedNames", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "rotateStringArray", void 0); -__decorate([class_validator_1.IsNumber(), __metadata("design:type", Number)], Options.prototype, "seed", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "selfDefending", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "sourceMap", void 0); +}), __metadata('design:type', Array)], Options.prototype, "reservedNames", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "rotateStringArray", void 0); +__decorate([class_validator_1.IsNumber(), __metadata('design:type', Number)], Options.prototype, "seed", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "selfDefending", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "sourceMap", void 0); __decorate([class_validator_1.IsString(), class_validator_1.ValidateIf(function (options) { return Boolean(options.sourceMapBaseUrl); }), class_validator_1.IsUrl({ require_protocol: true, require_valid_protocol: true -}), __metadata("design:type", String)], Options.prototype, "sourceMapBaseUrl", void 0); -__decorate([class_validator_1.IsString(), __metadata("design:type", String)], Options.prototype, "sourceMapFileName", void 0); -__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata("design:type", String)], Options.prototype, "sourceMapMode", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "stringArray", void 0); -__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata("design:type", Object)], Options.prototype, "stringArrayEncoding", void 0); -__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata("design:type", Number)], Options.prototype, "stringArrayThreshold", void 0); -__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "unicodeEscapeSequence", void 0); -Options = Options_1 = __decorate([inversify_1.injectable(), __metadata("design:paramtypes", [Object])], Options); +}), __metadata('design:type', String)], Options.prototype, "sourceMapBaseUrl", void 0); +__decorate([class_validator_1.IsString(), __metadata('design:type', String)], Options.prototype, "sourceMapFileName", void 0); +__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata('design:type', String)], Options.prototype, "sourceMapMode", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "stringArray", void 0); +__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata('design:type', Object)], Options.prototype, "stringArrayEncoding", void 0); +__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata('design:type', Number)], Options.prototype, "stringArrayThreshold", void 0); +__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "unicodeEscapeSequence", void 0); +Options = Options_1 = __decorate([inversify_1.injectable(), __metadata('design:paramtypes', [typeof (_a = typeof TInputOptions_1.TInputOptions !== 'undefined' && TInputOptions_1.TInputOptions) === 'function' && _a || Object])], Options); exports.Options = Options; -var Options_1; +var _a; /***/ }, /* 84 */ diff --git a/src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts b/src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts index a420e30c..b37ad55d 100644 --- a/src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts +++ b/src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts @@ -7,6 +7,8 @@ import * as ESTree from 'estree'; import { TControlFlowReplacerFactory } from '../../types/container/TControlFlowReplacerFactory'; import { TControlFlowStorageFactory } from '../../types/container/TControlFlowStorageFactory'; import { TCustomNodeFactory } from '../../types/container/TCustomNodeFactory'; +import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement'; +import { TStatement } from '../../types/node/TStatement'; import { IControlFlowData } from '../../interfaces/node-transformers/IControlFlowData'; import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode'; @@ -35,7 +37,12 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer { /** * @type {Map} */ - private cachedControlFlowData: Map = new Map (); + private controlFlowData: Map = new Map (); + + /** + * @type {TStatement[][]} + */ + private readonly controlFlowNodesList: TStatement[][] = []; /** * @type {TControlFlowReplacerFactory} @@ -87,25 +94,36 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer { } const controlFlowStorage: IStorage = this.controlFlowStorageFactory(); - const hostNode: ESTree.Node = NodeUtils.getBlockScopeOfNode( + const hostNode: TNodeWithBlockStatement = NodeUtils.getBlockScopeOfNode( functionNode.body, RandomGeneratorUtils.getRandomInteger(1, 5) ); - let controlFlowStorageCustomNodeName: string = RandomGeneratorUtils.getRandomVariableName(6); + let controlFlowStorageNodeName: string = RandomGeneratorUtils.getRandomVariableName(6); - if (!this.cachedControlFlowData.has(hostNode)) { - this.cachedControlFlowData.set(hostNode, { + if (!this.controlFlowData.has(hostNode)) { + this.controlFlowData.set(hostNode, { controlFlowStorage, - controlFlowStorageNodeName: controlFlowStorageCustomNodeName + controlFlowStorageNodeName }); } else { - hostNode.body.shift(); + for (let controlFlowNode of this.controlFlowNodesList) { + const firstIndexOfNode: number = (hostNode.body).indexOf(controlFlowNode[0]); + + if (firstIndexOfNode === -1) { + continue; + } + + const statementLength: number = controlFlowNode.length; + + (hostNode.body).splice(firstIndexOfNode, statementLength); + break; + } const { controlFlowStorage: hostControlFlowStorage, controlFlowStorageNodeName: hostControlFlowStorageNodeName - } = this.cachedControlFlowData.get(hostNode); + } = this.controlFlowData.get(hostNode); hostControlFlowStorage .getStorage() @@ -113,9 +131,9 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer { controlFlowStorage.set(key, customNode); }); - controlFlowStorageCustomNodeName = hostControlFlowStorageNodeName; + controlFlowStorageNodeName = hostControlFlowStorageNodeName; - this.cachedControlFlowData.set(hostNode, { + this.controlFlowData.set(hostNode, { controlFlowStorage, controlFlowStorageNodeName: hostControlFlowStorageNodeName }); @@ -132,7 +150,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer { return { ...this.controlFlowReplacerFactory(controlFlowReplacerName) - .replace(node, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName), + .replace(node, parentNode, controlFlowStorage, controlFlowStorageNodeName), parentNode }; } @@ -144,11 +162,11 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer { const controlFlowStorageCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.ControlFlowStorageNode); - controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageCustomNodeName); + controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageNodeName); - NodeAppender.prependNode( - hostNode, - controlFlowStorageCustomNode.getNode() - ); + const controlFlowStorageNode: TStatement[] = controlFlowStorageCustomNode.getNode(); + + this.controlFlowNodesList.push(controlFlowStorageNode); + NodeAppender.prependNode(hostNode, controlFlowStorageNode); } }