ソースを参照

control flow flattening algoritm optimizations
move from underscore to lodash

sanex3339 8 年 前
コミット
f5f94a654e

+ 47 - 33
dist/index.js

@@ -88,7 +88,7 @@ module.exports =
 /******/ 	__webpack_require__.p = "";
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 122);
+/******/ 	return __webpack_require__(__webpack_require__.s = 123);
 /******/ })
 /************************************************************************/
 /******/ ([
@@ -424,7 +424,7 @@ var _createClass = (function () { function defineProperties(target, props) { for
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
-var _ = __webpack_require__(35);
+var _ = __webpack_require__(34);
 var JSFuck_1 = __webpack_require__(27);
 
 var Utils = function () {
@@ -951,7 +951,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] : {};
 
@@ -960,7 +960,7 @@ var JavaScriptObfuscator = function () {
             return javaScriptObfuscator.obfuscate(sourceCode);
         }
     }, {
-        key: 'runCLI',
+        key: "runCLI",
         value: function runCLI(argv) {
             new JavaScriptObfuscatorCLI_1.JavaScriptObfuscatorCLI(argv).run();
         }
@@ -1713,13 +1713,13 @@ module.exports = require("esprima");
 /* 34 */
 /***/ function(module, exports) {
 
-module.exports = require("path");
+module.exports = require("lodash");
 
 /***/ },
 /* 35 */
 /***/ function(module, exports) {
 
-module.exports = require("underscore");
+module.exports = require("path");
 
 /***/ },
 /* 36 */
@@ -2061,7 +2061,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
 
 var fs = __webpack_require__(119);
 var mkdirp = __webpack_require__(120);
-var path = __webpack_require__(34);
+var path = __webpack_require__(35);
 
 var CLIUtils = function () {
     function CLIUtils() {
@@ -2160,7 +2160,7 @@ var __assign = undefined && undefined.__assign || Object.assign || function (t)
     return t;
 };
 var commander = __webpack_require__(117);
-var path = __webpack_require__(34);
+var path = __webpack_require__(35);
 var SourceMapMode_1 = __webpack_require__(19);
 var StringArrayEncoding_1 = __webpack_require__(22);
 var DefaultPreset_1 = __webpack_require__(31);
@@ -4153,7 +4153,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var estraverse = __webpack_require__(5);
-var _ = __webpack_require__(35);
+var _ = __webpack_require__(34);
 var CustomNodes_1 = __webpack_require__(12);
 var NodeType_1 = __webpack_require__(10);
 var AbstractNodeTransformer_1 = __webpack_require__(11);
@@ -4192,7 +4192,7 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function
                 return;
             }
             var controlFlowStorage = this.controlFlowStorageFactory();
-            var hostNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionNode.body, RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomInteger(1, 5));
+            var hostNode = FunctionControlFlowTransformer_1.getHostNode(functionNode);
             var controlFlowStorageNodeName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(6);
             if (!this.controlFlowData.has(hostNode)) {
                 this.controlFlowData.set(hostNode, {
@@ -4232,6 +4232,18 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function
             NodeAppender_1.NodeAppender.prependNode(hostNode, controlFlowStorageNode);
         }
     }], [{
+        key: "getHostNode",
+        value: function getHostNode(functionNode) {
+            var currentBlockScopeDepth = NodeUtils_1.NodeUtils.getNodeBlockScopeDepth(functionNode);
+            if (currentBlockScopeDepth <= 1) {
+                return functionNode.body;
+            }
+            var minDepth = _.clamp(FunctionControlFlowTransformer_1.hostNodeSearchMinDepth, 0, currentBlockScopeDepth);
+            var maxDepth = Math.min(currentBlockScopeDepth, FunctionControlFlowTransformer_1.hostNodeSearchMaxDepth);
+            var depth = _.clamp(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomInteger(minDepth, maxDepth) - 1, 0, Infinity);
+            return NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionNode, depth);
+        }
+    }, {
         key: "removeOldControlFlowNodeFromHostNodeBody",
         value: function removeOldControlFlowNodeFromHostNodeBody(hostNodeBody, controlFlowNodesList) {
             var _iteratorNormalCompletion = true;
@@ -4270,6 +4282,8 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function
     return FunctionControlFlowTransformer;
 }(AbstractNodeTransformer_1.AbstractNodeTransformer);
 FunctionControlFlowTransformer.controlFlowReplacersMap = new Map([[NodeType_1.NodeType.BinaryExpression, NodeControlFlowReplacers_1.NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer]]);
+FunctionControlFlowTransformer.hostNodeSearchMinDepth = 2;
+FunctionControlFlowTransformer.hostNodeSearchMaxDepth = 10;
 FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<IStorage<ICustomNode>>'])), __param(1, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<IControlFlowReplacer>'])), __param(2, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<ICustomNode>'])), __param(3, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Function, Function, Function, Object])], FunctionControlFlowTransformer);
 exports.FunctionControlFlowTransformer = FunctionControlFlowTransformer;
 var FunctionControlFlowTransformer_1;
@@ -5599,7 +5613,7 @@ var class_validator_1 = __webpack_require__(116);
 var DefaultPreset_1 = __webpack_require__(31);
 var OptionsNormalizer_1 = __webpack_require__(85);
 var ValidationErrorsFormatter_1 = __webpack_require__(86);
-var Options_1 = function Options(inputOptions) {
+var Options = Options_1 = function Options(inputOptions) {
     _classCallCheck(this, Options);
 
     Object.assign(this, DefaultPreset_1.DEFAULT_PRESET, inputOptions);
@@ -5609,42 +5623,41 @@ var 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', [typeof (_a = typeof TInputOptions_1.TInputOptions !== 'undefined' && TInputOptions_1.TInputOptions) === 'function' && _a || 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", [Object])], Options);
 exports.Options = Options;
-var _a;
+var Options_1;
 
 /***/ },
 /* 85 */
@@ -6866,7 +6879,8 @@ module.exports = require("mkdirp");
 module.exports = require("reflect-metadata");
 
 /***/ },
-/* 122 */
+/* 122 */,
+/* 123 */
 /***/ function(module, exports, __webpack_require__) {
 
 "use strict";

+ 3 - 3
package.json

@@ -28,11 +28,11 @@
     "esprima": "3.1.2",
     "estraverse": "4.2.0",
     "inversify": "^3.0.0-rc.2",
+    "lodash": "^4.17.2",
     "mkdirp": "0.5.1",
     "reflect-metadata": "^0.1.8",
     "source-map-support": "0.4.6",
-    "string-template": "^1.0.0",
-    "underscore": "^1.8.3"
+    "string-template": "^1.0.0"
   },
   "devDependencies": {
     "@types/chai": "3.4.34",
@@ -43,12 +43,12 @@
     "@types/estraverse": "0.0.6",
     "@types/estree": "0.0.34",
     "@types/joi": "9.0.33",
+    "@types/lodash": "^4.14.43",
     "@types/mkdirp": "0.3.29",
     "@types/mocha": "2.2.33",
     "@types/node": "6.0.52",
     "@types/sinon": "1.16.33",
     "@types/string-template": "1.0.2",
-    "@types/underscore": "^1.7.36",
     "awesome-typescript-loader": "3.0.0-beta.17",
     "babel-cli": "6.18.0",
     "babel-loader": "6.2.9",

+ 31 - 6
src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
-import * as _ from 'underscore';
+import * as _ from 'lodash';
 
 import { TControlFlowReplacerFactory } from '../../types/container/TControlFlowReplacerFactory';
 import { TControlFlowStorageFactory } from '../../types/container/TControlFlowStorageFactory';
@@ -35,6 +35,16 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         [NodeType.BinaryExpression, NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer]
     ]);
 
+    /**
+     * @type {number}
+     */
+    private static readonly hostNodeSearchMinDepth: number = 2;
+
+    /**
+     * @type {number}
+     */
+    private static readonly hostNodeSearchMaxDepth: number = 10;
+
     /**
      * @type {Map<ESTree.Node, IControlFlowNodeMetadata>}
      */
@@ -79,6 +89,24 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         this.customNodeFactory = customNodeFactory;
     }
 
+    /**
+     * @param functionNode
+     * @returns {TNodeWithBlockStatement}
+     */
+    private static getHostNode (functionNode: ESTree.FunctionDeclaration | ESTree.FunctionExpression): TNodeWithBlockStatement {
+        const currentBlockScopeDepth: number = NodeUtils.getNodeBlockScopeDepth(functionNode);
+
+        if (currentBlockScopeDepth <= 1) {
+            return functionNode.body;
+        }
+
+        const minDepth: number = _.clamp(FunctionControlFlowTransformer.hostNodeSearchMinDepth, 0, currentBlockScopeDepth);
+        const maxDepth: number = Math.min(currentBlockScopeDepth, FunctionControlFlowTransformer.hostNodeSearchMaxDepth);
+        const depth: number = _.clamp(RandomGeneratorUtils.getRandomInteger(minDepth, maxDepth) - 1, 0, Infinity);
+
+        return NodeUtils.getBlockScopeOfNode(functionNode, depth);
+    }
+
     /**
      * @param hostNodeBody
      * @param controlFlowNodesList
@@ -116,10 +144,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         }
 
         const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
-        const hostNode: TNodeWithBlockStatement = NodeUtils.getBlockScopeOfNode(
-            functionNode.body,
-            RandomGeneratorUtils.getRandomInteger(1, 5)
-        );
+        const hostNode: TNodeWithBlockStatement = FunctionControlFlowTransformer.getHostNode(functionNode);
 
         let controlFlowStorageNodeName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
@@ -129,7 +154,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
                 controlFlowStorageNodeName
             });
         } else {
-            hostNode.body = FunctionControlFlowTransformer
+            hostNode.body = <ESTree.Statement[]>FunctionControlFlowTransformer
                 .removeOldControlFlowNodeFromHostNodeBody(hostNode.body, this.controlFlowNodesList);
 
             const {

+ 1 - 1
src/utils/Utils.ts

@@ -1,4 +1,4 @@
-import * as _ from 'underscore';
+import * as _ from 'lodash';
 import { JSFuck } from '../enums/JSFuck';
 
 export class Utils {