js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.prettierrc +4 -0
  2. package/CHANGELOG.md +42 -8
  3. package/Migration.md +23 -8
  4. package/README.md +2 -2
  5. package/dist/constants.js +11 -2
  6. package/dist/index.js +49 -6
  7. package/dist/obfuscator.js +121 -10
  8. package/dist/order.js +0 -1
  9. package/dist/probability.js +1 -96
  10. package/dist/templates/getGlobalTemplate.js +4 -1
  11. package/dist/templates/integrityTemplate.js +1 -1
  12. package/dist/templates/stringCompressionTemplate.js +3 -3
  13. package/dist/templates/tamperProtectionTemplates.js +1 -1
  14. package/dist/templates/template.js +17 -12
  15. package/dist/transforms/controlFlowFlattening.js +112 -83
  16. package/dist/transforms/deadCode.js +21 -22
  17. package/dist/transforms/dispatcher.js +62 -37
  18. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
  19. package/dist/transforms/extraction/objectExtraction.js +1 -2
  20. package/dist/transforms/finalizer.js +1 -1
  21. package/dist/transforms/flatten.js +2 -19
  22. package/dist/transforms/identifier/globalConcealing.js +3 -4
  23. package/dist/transforms/identifier/movedDeclarations.js +12 -5
  24. package/dist/transforms/identifier/renameVariables.js +40 -6
  25. package/dist/transforms/lock/integrity.js +9 -1
  26. package/dist/transforms/lock/lock.js +16 -9
  27. package/dist/transforms/minify.js +64 -27
  28. package/dist/transforms/opaquePredicates.js +6 -7
  29. package/dist/transforms/pack.js +32 -5
  30. package/dist/transforms/plugin.js +20 -39
  31. package/dist/transforms/preparation.js +25 -36
  32. package/dist/transforms/renameLabels.js +1 -2
  33. package/dist/transforms/rgf.js +36 -16
  34. package/dist/transforms/shuffle.js +10 -11
  35. package/dist/transforms/string/stringCompression.js +14 -10
  36. package/dist/transforms/string/stringConcealing.js +7 -5
  37. package/dist/transforms/string/stringEncoding.js +4 -2
  38. package/dist/transforms/string/stringSplitting.js +4 -2
  39. package/dist/transforms/variableMasking.js +3 -2
  40. package/dist/utils/NameGen.js +5 -2
  41. package/dist/utils/PredicateGen.js +62 -0
  42. package/dist/utils/ast-utils.js +24 -9
  43. package/dist/utils/random-utils.js +10 -0
  44. package/dist/validateOptions.js +2 -2
  45. package/index.d.ts +16 -2
  46. package/package.json +2 -2
  47. package/src/constants.ts +15 -5
  48. package/src/index.ts +15 -5
  49. package/src/obfuscationResult.ts +7 -1
  50. package/src/obfuscator.ts +152 -12
  51. package/src/options.ts +26 -8
  52. package/src/order.ts +0 -2
  53. package/src/templates/getGlobalTemplate.ts +5 -1
  54. package/src/templates/integrityTemplate.ts +14 -19
  55. package/src/templates/stringCompressionTemplate.ts +4 -28
  56. package/src/templates/tamperProtectionTemplates.ts +7 -3
  57. package/src/templates/template.ts +5 -3
  58. package/src/transforms/controlFlowFlattening.ts +139 -83
  59. package/src/transforms/deadCode.ts +27 -30
  60. package/src/transforms/dispatcher.ts +24 -5
  61. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
  62. package/src/transforms/extraction/objectExtraction.ts +1 -2
  63. package/src/transforms/finalizer.ts +1 -1
  64. package/src/transforms/flatten.ts +3 -22
  65. package/src/transforms/identifier/globalConcealing.ts +26 -17
  66. package/src/transforms/identifier/movedDeclarations.ts +18 -6
  67. package/src/transforms/identifier/renameVariables.ts +48 -6
  68. package/src/transforms/lock/integrity.ts +11 -1
  69. package/src/transforms/lock/lock.ts +26 -10
  70. package/src/transforms/minify.ts +85 -38
  71. package/src/transforms/opaquePredicates.ts +6 -9
  72. package/src/transforms/pack.ts +41 -5
  73. package/src/transforms/plugin.ts +47 -69
  74. package/src/transforms/preparation.ts +33 -46
  75. package/src/transforms/renameLabels.ts +1 -2
  76. package/src/transforms/rgf.ts +52 -23
  77. package/src/transforms/shuffle.ts +28 -26
  78. package/src/transforms/string/encoding.ts +1 -1
  79. package/src/transforms/string/stringCompression.ts +22 -13
  80. package/src/transforms/string/stringConcealing.ts +13 -7
  81. package/src/transforms/string/stringEncoding.ts +6 -2
  82. package/src/transforms/string/stringSplitting.ts +9 -4
  83. package/src/transforms/variableMasking.ts +2 -2
  84. package/src/utils/NameGen.ts +13 -3
  85. package/src/utils/PredicateGen.ts +61 -0
  86. package/src/utils/ast-utils.ts +16 -9
  87. package/src/utils/random-utils.ts +14 -0
  88. package/src/validateOptions.ts +7 -4
  89. package/src/probability.ts +0 -110
  90. package/src/transforms/functionOutlining.ts +0 -225
  91. package/src/utils/ControlObject.ts +0 -141
@@ -14,7 +14,6 @@ var _integrity = require("./integrity");
14
14
  var _integrityTemplate = require("../../templates/integrityTemplate");
15
15
  var _constants = require("../../constants");
16
16
  var _tamperProtectionTemplates = require("../../templates/tamperProtectionTemplates");
17
- var _probability = require("../../probability");
18
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
19
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
20
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
@@ -26,6 +25,7 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
26
25
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
27
26
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
28
27
  var _default = exports["default"] = function _default(_ref) {
28
+ var _me$options$lock$defa;
29
29
  var Plugin = _ref.Plugin;
30
30
  var me = Plugin(_order.Order.Lock, {
31
31
  changeData: {
@@ -33,12 +33,20 @@ var _default = exports["default"] = function _default(_ref) {
33
33
  }
34
34
  });
35
35
  if (me.options.lock.startDate instanceof Date) {
36
+ // Ensure date is in the past
37
+ if (me.options.lock.startDate.getTime() > Date.now()) {
38
+ me.warn("lock.startDate is detected to be in the future");
39
+ }
36
40
  me.options.lock.customLocks.push({
37
41
  code: ["\n if(Date.now()<".concat(me.options.lock.startDate.getTime(), ") {\n {countermeasures}\n }\n "), "\n if((new Date()).getTime()<".concat(me.options.lock.startDate.getTime(), ") {\n {countermeasures}\n }\n ")],
38
42
  percentagePerBlock: 0.5
39
43
  });
40
44
  }
41
45
  if (me.options.lock.endDate instanceof Date) {
46
+ // Ensure date is in the future
47
+ if (me.options.lock.endDate.getTime() < Date.now()) {
48
+ me.warn("lock.endDate is detected to be in the past");
49
+ }
42
50
  me.options.lock.customLocks.push({
43
51
  code: ["\n if(Date.now()>".concat(me.options.lock.endDate.getTime(), ") {\n {countermeasures}\n }\n "), "\n if((new Date()).getTime()>".concat(me.options.lock.endDate.getTime(), ") {\n {countermeasures}\n }\n ")],
44
52
  percentagePerBlock: 0.5
@@ -71,7 +79,7 @@ var _default = exports["default"] = function _default(_ref) {
71
79
  }
72
80
  if (me.options.lock.selfDefending) {
73
81
  me.options.lock.customLocks.push({
74
- code: "\n (\n function(){\n // Breaks any code formatter\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n\n if(test()) {\n {countermeasures}\n }\n }\n\n return namedFunction();\n }\n )();\n ",
82
+ code: "\n (\n function(){\n // Breaks any code formatter\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n\n if(test()) {\n {countermeasures}\n }\n }\n\n // Prepack Breaker\n if(Math.random() > 1) {\n while(true) {\n console.log(\"Prepack Breaker\");\n }\n }\n\n return namedFunction();\n }\n )();\n ",
75
83
  percentagePerBlock: 0.5
76
84
  });
77
85
  }
@@ -98,13 +106,12 @@ var _default = exports["default"] = function _default(_ref) {
98
106
  return new _template["default"]("while(true){}").compile();
99
107
  };
100
108
  me.globalState.lock.createCountermeasuresCode = createCountermeasuresCode;
109
+ var defaultMaxCount = (_me$options$lock$defa = me.options.lock.defaultMaxCount) !== null && _me$options$lock$defa !== void 0 ? _me$options$lock$defa : 25;
101
110
  function applyLockToBlock(path, customLock) {
102
- var times = timesMap.get(customLock);
103
- if (typeof times === "undefined") {
104
- times = 0;
105
- }
106
- var maxCount = customLock.maxCount || 100; // 100 is default max count
107
- var minCount = customLock.minCount || 1; // 1 is default min count
111
+ var _customLock$maxCount, _customLock$minCount;
112
+ var times = timesMap.get(customLock) || 0;
113
+ var maxCount = (_customLock$maxCount = customLock.maxCount) !== null && _customLock$maxCount !== void 0 ? _customLock$maxCount : defaultMaxCount; // 25 is default max count
114
+ var minCount = (_customLock$minCount = customLock.minCount) !== null && _customLock$minCount !== void 0 ? _customLock$minCount : 1; // 1 is default min count
108
115
 
109
116
  if (maxCount >= 0 && times > maxCount) {
110
117
  // Limit creation, allowing -1 to disable the limit entirely
@@ -257,7 +264,7 @@ var _default = exports["default"] = function _default(_ref) {
257
264
  if (me.options.lock.countermeasures && functionName === me.options.lock.countermeasures) return;
258
265
  // Don't apply to invokeCountermeasures function (Intended)
259
266
  if (me.obfuscator.isInternalVariable(functionName)) return;
260
- if (!(0, _probability.computeProbabilityMap)(me.options.lock.integrity, functionName)) return;
267
+ if (!me.computeProbabilityMap(me.options.lock.integrity, functionName)) return;
261
268
  var newFnName = me.getPlaceholder();
262
269
  var newFunctionDeclaration = t.functionDeclaration(t.identifier(newFnName), funcDecPath.node.params, funcDecPath.node.body);
263
270
 
@@ -25,6 +25,33 @@ identifierMap.set("undefined", function () {
25
25
  identifierMap.set("Infinity", function () {
26
26
  return t.binaryExpression("/", t.numericLiteral(1), t.numericLiteral(0));
27
27
  });
28
+ function trySimpleDestructuring(id, init) {
29
+ // Simple array/object destructuring
30
+ if (id.isArrayPattern() && init.isArrayExpression()) {
31
+ var elements = id.get("elements");
32
+ var initElements = init.get("elements");
33
+ if (elements.length === 1 && initElements.length === 1) {
34
+ id.replaceWith(elements[0]);
35
+ init.replaceWith(initElements[0]);
36
+ }
37
+ }
38
+ if (id.isObjectPattern() && init.isObjectExpression()) {
39
+ var properties = id.get("properties");
40
+ var initProperties = init.get("properties");
41
+ if (properties.length === 1 && initProperties.length === 1) {
42
+ var firstProperty = properties[0];
43
+ var firstInitProperty = initProperties[0];
44
+ if (firstProperty.isObjectProperty() && firstInitProperty.isObjectProperty()) {
45
+ var firstKey = firstProperty.get("key");
46
+ var firstInitKey = firstInitProperty.get("key");
47
+ if (firstKey.isIdentifier() && firstInitKey.isIdentifier() && firstKey.node.name === firstInitKey.node.name) {
48
+ id.replaceWith(firstProperty.node.value);
49
+ init.replaceWith(firstInitProperty.node.value);
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
28
55
 
29
56
  /**
30
57
  * Minify removes unnecessary code and shortens the length for file size.
@@ -125,6 +152,16 @@ var _default = exports["default"] = function _default(_ref) {
125
152
  }
126
153
  }
127
154
  },
155
+ // "a" + "b" -> "ab"
156
+ BinaryExpression: {
157
+ exit: function exit(path) {
158
+ if (path.node.operator !== "+") return;
159
+ var left = path.get("left");
160
+ var right = path.get("right");
161
+ if (!left.isStringLiteral() || !right.isStringLiteral()) return;
162
+ path.replaceWith(t.stringLiteral(left.node.value + right.node.value));
163
+ }
164
+ },
128
165
  // a["key"] -> a.key
129
166
  MemberExpression: {
130
167
  exit: function exit(path) {
@@ -204,7 +241,7 @@ var _default = exports["default"] = function _default(_ref) {
204
241
  FunctionDeclaration: {
205
242
  exit: function exit(path) {
206
243
  var id = path.get("id");
207
- if (id.isIdentifier() && !id.node.name.startsWith(_constants.placeholderVariablePrefix)) {
244
+ if (id.isIdentifier() && !id.node.name.startsWith(_constants.placeholderVariablePrefix) && !path.node[_constants.NO_REMOVE]) {
208
245
  var binding = path.scope.getBinding(id.node.name);
209
246
  if (binding && binding.constantViolations.length === 0 && binding.referencePaths.length === 0 && !binding.referenced) {
210
247
  path.remove();
@@ -222,32 +259,7 @@ var _default = exports["default"] = function _default(_ref) {
222
259
  }
223
260
  var id = path.get("id");
224
261
  var init = path.get("init");
225
-
226
- // Simple array/object destructuring
227
- if (id.isArrayPattern() && init.isArrayExpression()) {
228
- var elements = id.get("elements");
229
- var initElements = init.get("elements");
230
- if (elements.length === 1 && initElements.length === 1) {
231
- id.replaceWith(elements[0]);
232
- init.replaceWith(initElements[0]);
233
- }
234
- }
235
- if (id.isObjectPattern() && init.isObjectExpression()) {
236
- var properties = id.get("properties");
237
- var initProperties = init.get("properties");
238
- if (properties.length === 1 && initProperties.length === 1) {
239
- var firstProperty = properties[0];
240
- var firstInitProperty = initProperties[0];
241
- if (firstProperty.isObjectProperty() && firstInitProperty.isObjectProperty()) {
242
- var firstKey = firstProperty.get("key");
243
- var firstInitKey = firstInitProperty.get("key");
244
- if (firstKey.isIdentifier() && firstInitKey.isIdentifier() && firstKey.node.name === firstInitKey.node.name) {
245
- id.replaceWith(firstProperty.node.value);
246
- init.replaceWith(firstInitProperty.node.value);
247
- }
248
- }
249
- }
250
- }
262
+ trySimpleDestructuring(id, init);
251
263
 
252
264
  // Remove unused variables
253
265
  // Can only remove if it's pure
@@ -255,6 +267,9 @@ var _default = exports["default"] = function _default(_ref) {
255
267
  // Do not remove variables in unsafe functions
256
268
  var fn = (0, _astUtils.getParentFunctionOrProgram)(path);
257
269
  if (fn.node[_constants.UNSAFE]) return;
270
+
271
+ // Node explicitly marked as not to be removed
272
+ if (id[_constants.NO_REMOVE]) return;
258
273
  var binding = path.scope.getBinding(id.node.name);
259
274
  if (binding && binding.constantViolations.length === 0 && binding.referencePaths.length === 0) {
260
275
  if (!init.node || init.isPure()) {
@@ -266,6 +281,28 @@ var _default = exports["default"] = function _default(_ref) {
266
281
  }
267
282
  }
268
283
  },
284
+ // Simple destructuring
285
+ // Simple arithmetic operations
286
+ AssignmentExpression: {
287
+ exit: function exit(path) {
288
+ if (path.node.operator === "=") {
289
+ trySimpleDestructuring(path.get("left"), path.get("right"));
290
+ }
291
+ if (path.node.operator === "+=") {
292
+ var left = path.get("left");
293
+ var right = path.get("right");
294
+
295
+ // a += 1 -> a++
296
+ if (right.isNumericLiteral({
297
+ value: 1
298
+ })) {
299
+ if (left.isIdentifier() || left.isMemberExpression()) {
300
+ path.replaceWith(t.updateExpression("++", left.node));
301
+ }
302
+ }
303
+ }
304
+ }
305
+ },
269
306
  // return undefined->return
270
307
  ReturnStatement: {
271
308
  exit: function exit(path) {
@@ -7,9 +7,9 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports["default"] = void 0;
8
8
  var _order = require("../order");
9
9
  var t = _interopRequireWildcard(require("@babel/types"));
10
- var _astUtils = require("../utils/ast-utils");
11
10
  var _randomUtils = require("../utils/random-utils");
12
- var _probability = require("../probability");
11
+ var _PredicateGen = _interopRequireDefault(require("../utils/PredicateGen"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
13
13
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
14
14
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
15
15
  var _default = exports["default"] = function _default(_ref) {
@@ -19,10 +19,9 @@ var _default = exports["default"] = function _default(_ref) {
19
19
  opaquePredicates: 0
20
20
  }
21
21
  });
22
+ var predicateGen = new _PredicateGen["default"](me);
22
23
  function createTruePredicate(path) {
23
- var controlObject = me.getControlObject((0, _astUtils.getBlock)(path));
24
- var trueValue = controlObject.createTruePredicate();
25
- return trueValue;
24
+ return predicateGen.generateTrueExpression(path);
26
25
  }
27
26
  var active = true;
28
27
  var transformCount = 0;
@@ -31,10 +30,10 @@ var _default = exports["default"] = function _default(_ref) {
31
30
  if (path.find(function (p) {
32
31
  return me.isSkipped(p);
33
32
  })) return false;
34
- if (!(0, _probability.computeProbabilityMap)(me.options.opaquePredicates)) return false;
33
+ if (!me.computeProbabilityMap(me.options.opaquePredicates)) return false;
35
34
  transformCount++;
36
35
  var depth = path.getAncestry().length;
37
- return (0, _randomUtils.chance)(1000 - transformCount - depth * 100);
36
+ return (0, _randomUtils.chance)(500 - transformCount - depth * 100);
38
37
  }
39
38
  function wrapWithPredicate(path) {
40
39
  var newExpression = t.logicalExpression("&&", createTruePredicate(path), path.node);
@@ -27,16 +27,32 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
27
27
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
28
28
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
29
29
  function pack(_ref) {
30
+ var _me$obfuscator$parent;
30
31
  var Plugin = _ref.Plugin;
31
32
  var me = Plugin(_order.Order.Pack, {
32
33
  changeData: {
33
34
  globals: 0
34
35
  }
35
36
  });
36
- var _objectName = me.obfuscator.nameGen.generate();
37
- var mappings = new Map();
38
- var setterPropsNeeded = new Set();
39
- var typeofMappings = new Map();
37
+
38
+ // RGF functions will re-use parent Pack Interface
39
+ var packInterface = (_me$obfuscator$parent = me.obfuscator.parentObfuscator) === null || _me$obfuscator$parent === void 0 ? void 0 : _me$obfuscator$parent.packInterface;
40
+
41
+ // Create new Pack Interface (root)
42
+ if (!packInterface) {
43
+ packInterface = {
44
+ objectName: me.obfuscator.nameGen.generate(),
45
+ mappings: new Map(),
46
+ setterPropsNeeded: new Set(),
47
+ typeofMappings: new Map()
48
+ };
49
+ me.obfuscator.packInterface = packInterface;
50
+ }
51
+ var _packInterface = packInterface,
52
+ _objectName = _packInterface.objectName,
53
+ mappings = _packInterface.mappings,
54
+ setterPropsNeeded = _packInterface.setterPropsNeeded,
55
+ typeofMappings = _packInterface.typeofMappings;
40
56
  var prependNodes = [];
41
57
  return {
42
58
  // Transform identifiers, preserve import statements
@@ -59,9 +75,18 @@ function pack(_ref) {
59
75
  if (path.node[_constants.WITH_STATEMENT]) return;
60
76
  var identifierName = path.node.name;
61
77
  if (_constants.reservedIdentifiers.has(identifierName)) return;
62
- if (me.obfuscator.options.globalVariables.has(identifierName)) return;
78
+ if (me.options.target === "node" && _constants.reservedNodeModuleIdentifiers.has(identifierName)) {
79
+ // Allow module.exports and require
80
+ } else {
81
+ if (me.options.globalVariables.has(identifierName)) return;
82
+ }
63
83
  if (identifierName === _constants.variableFunctionName) return;
84
+ if (identifierName === _objectName) return;
64
85
  if (!path.scope.hasGlobal(identifierName)) return;
86
+ if (path.scope.hasBinding(identifierName)) return;
87
+
88
+ // Check user's custom implementation
89
+ if (!me.computeProbabilityMap(me.options.pack, identifierName)) return;
65
90
  if (path.key === "argument" && path.parentPath.isUnaryExpression({
66
91
  operator: "typeof"
67
92
  })) {
@@ -91,6 +116,8 @@ function pack(_ref) {
91
116
  // Final AST handler
92
117
  // Very last step in the obfuscation process
93
118
  finalASTHandler: function finalASTHandler(ast) {
119
+ if (me.obfuscator.parentObfuscator) return ast; // Only for root obfuscator
120
+
94
121
  // Create object expression
95
122
  // Very similar to flatten, maybe refactor to use the same code
96
123
  var objectProperties = [];
@@ -9,10 +9,7 @@ var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _constants = require("../constants");
10
10
  var _setFunctionLengthTemplate = require("../templates/setFunctionLengthTemplate");
11
11
  var _astUtils = require("../utils/ast-utils");
12
- var _ControlObject = _interopRequireDefault(require("../utils/ControlObject"));
13
- var _assert = require("assert");
14
12
  var _node = require("../utils/node");
15
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
16
13
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
17
14
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
18
15
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
@@ -28,6 +25,7 @@ var PluginInstance = exports.PluginInstance = /*#__PURE__*/function () {
28
25
  _defineProperty(this, "changeData", {});
29
26
  this.pluginOptions = pluginOptions;
30
27
  this.obfuscator = obfuscator;
28
+ this.computeProbabilityMap = obfuscator.computeProbabilityMap.bind(this.obfuscator);
31
29
  }
32
30
  return _createClass(PluginInstance, [{
33
31
  key: "name",
@@ -78,21 +76,25 @@ var PluginInstance = exports.PluginInstance = /*#__PURE__*/function () {
78
76
  value: function setFunctionLength(path, originalLength) {
79
77
  path.node[_constants.FN_LENGTH] = originalLength;
80
78
 
81
- // Function length
82
- if (this.options.preserveFunctionLength && originalLength > 0) {
83
- if (!this.setFunctionLengthName) {
84
- this.setFunctionLengthName = this.getPlaceholder("fnLength");
85
- this.skip((0, _astUtils.prependProgram)(path, _setFunctionLengthTemplate.SetFunctionLengthTemplate.compile({
86
- fnName: this.setFunctionLengthName
87
- })));
88
- }
89
- if (t.isFunctionDeclaration(path.node)) {
90
- (0, _astUtils.prepend)(path.parentPath, t.expressionStatement(t.callExpression(t.identifier(this.setFunctionLengthName), [t.identifier(path.node.id.name), (0, _node.numericLiteral)(originalLength)])));
91
- } else if (t.isFunctionExpression(path.node) || t.isArrowFunctionExpression(path.node)) {
92
- path.replaceWith(t.callExpression(t.identifier(this.setFunctionLengthName), [path.node, (0, _node.numericLiteral)(originalLength)]));
93
- } else {
94
- // TODO
95
- }
79
+ // Skip if user disabled this feature
80
+ if (!this.options.preserveFunctionLength) return;
81
+
82
+ // Skip if function has no parameters
83
+ if (originalLength === 0) return;
84
+
85
+ // Create the function length setter if it doesn't exist
86
+ if (!this.setFunctionLengthName) {
87
+ this.setFunctionLengthName = this.getPlaceholder("fnLength");
88
+ this.skip((0, _astUtils.prependProgram)(path, _setFunctionLengthTemplate.SetFunctionLengthTemplate.compile({
89
+ fnName: this.setFunctionLengthName
90
+ })));
91
+ }
92
+ if (t.isFunctionDeclaration(path.node)) {
93
+ (0, _astUtils.prepend)(path.parentPath, t.expressionStatement(t.callExpression(t.identifier(this.setFunctionLengthName), [t.identifier(path.node.id.name), (0, _node.numericLiteral)(originalLength)])));
94
+ } else if (t.isFunctionExpression(path.node) || t.isArrowFunctionExpression(path.node)) {
95
+ path.replaceWith(t.callExpression(t.identifier(this.setFunctionLengthName), [path.node, (0, _node.numericLiteral)(originalLength)]));
96
+ } else {
97
+ // TODO
96
98
  }
97
99
  }
98
100
 
@@ -110,27 +112,6 @@ var PluginInstance = exports.PluginInstance = /*#__PURE__*/function () {
110
112
  return "__p_" + (0, _randomUtils.getRandomString)(4) + (suffix ? "_" + suffix : "");
111
113
  }
112
114
 
113
- /**
114
- * Retrieves (or creates) a `ControlObject` for the given `blockPath`.
115
- */
116
- }, {
117
- key: "getControlObject",
118
- value: function getControlObject(blockPath) {
119
- var createMultiple = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
120
- (0, _assert.ok)(blockPath.isBlock());
121
- var controlObjects = blockPath.node[_constants.CONTROL_OBJECTS];
122
- if (!controlObjects) {
123
- controlObjects = [];
124
- }
125
- if (controlObjects.length === 0 || createMultiple && (0, _randomUtils.chance)(controlObjects[0].propertyNames.size - 15 * controlObjects.length)) {
126
- var newControlObject = new _ControlObject["default"](this, blockPath);
127
- controlObjects.push(newControlObject);
128
- blockPath.node[_constants.CONTROL_OBJECTS] = controlObjects;
129
- return newControlObject;
130
- }
131
- return (0, _randomUtils.choice)(controlObjects);
132
- }
133
-
134
115
  /**
135
116
  * Logs a message to the console, only if `verbose` is enabled.
136
117
  * @param messages
@@ -11,6 +11,8 @@ var _constants = require("../constants");
11
11
  var _assert = require("assert");
12
12
  var _astUtils = require("../utils/ast-utils");
13
13
  var _functionUtils = require("../utils/function-utils");
14
+ var _template = _interopRequireDefault(require("../templates/template"));
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
14
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
15
17
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
16
18
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -49,6 +51,29 @@ var _default = exports["default"] = function _default(_ref) {
49
51
  markFunctionUnsafe(path);
50
52
  }
51
53
  },
54
+ // @js-confuser-var "myVar" -> __JS_CONFUSER_VAR__(myVar)
55
+ StringLiteral: {
56
+ exit: function exit(path) {
57
+ var _path$node$leadingCom;
58
+ // Check for @js-confuser-var comment
59
+ if ((_path$node$leadingCom = path.node.leadingComments) !== null && _path$node$leadingCom !== void 0 && _path$node$leadingCom.find(function (comment) {
60
+ return comment.value.includes("@js-confuser-var");
61
+ })) {
62
+ var identifierName = path.node.value;
63
+ (0, _assert.ok)(t.isValidIdentifier(identifierName), "Invalid identifier name: " + identifierName);
64
+
65
+ // Create a new __JS_CONFUSER_VAR__ call with the identifier
66
+ var newExpression = new _template["default"]("__JS_CONFUSER_VAR__({identifier})").expression({
67
+ identifier: t.identifier(identifierName)
68
+ });
69
+ path.replaceWith(newExpression);
70
+
71
+ // Remove comment and skip further processing
72
+ path.node.leadingComments = [];
73
+ path.skip();
74
+ }
75
+ }
76
+ },
52
77
  // `Hello ${username}` -> "Hello " + username
53
78
  TemplateLiteral: {
54
79
  exit: function exit(path) {
@@ -256,42 +281,6 @@ var _default = exports["default"] = function _default(_ref) {
256
281
  path.node.body = t.blockStatement([path.node.body]);
257
282
  }
258
283
  }
259
- },
260
- // function a(param = ()=>b)
261
- // _getB = ()=> ()=>b
262
- // function a(param = _getB())
263
- // Basically Babel scope.rename misses this edge case, so we need to manually handle it
264
- // Here were essentially making the variables easier to understand
265
- Function: {
266
- exit: function exit(path) {
267
- var _iterator3 = _createForOfIteratorHelper(path.get("params")),
268
- _step3;
269
- try {
270
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
271
- var param = _step3.value;
272
- param.traverse({
273
- "FunctionExpression|ArrowFunctionExpression": function FunctionExpressionArrowFunctionExpression(_innerPath) {
274
- var innerPath = _innerPath;
275
- var child = innerPath.find(function (path) {
276
- var _path$parentPath;
277
- return (_path$parentPath = path.parentPath) === null || _path$parentPath === void 0 ? void 0 : _path$parentPath.isAssignmentPattern();
278
- });
279
- if (!child) return;
280
- if (t.isAssignmentPattern(child.parent) && child.parent.right === child.node) {
281
- var creatorName = me.getPlaceholder();
282
- var insertPath = path.insertBefore(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(creatorName), t.arrowFunctionExpression([], innerPath.node, false))]))[0];
283
- path.scope.parent.registerDeclaration(insertPath);
284
- innerPath.replaceWith(t.callExpression(t.identifier(creatorName), []));
285
- }
286
- }
287
- });
288
- }
289
- } catch (err) {
290
- _iterator3.e(err);
291
- } finally {
292
- _iterator3.f();
293
- }
294
- }
295
284
  }
296
285
  }
297
286
  };
@@ -9,7 +9,6 @@ var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _order = require("../order");
10
10
  var _NameGen = require("../utils/NameGen");
11
11
  var _assert = require("assert");
12
- var _probability = require("../probability");
13
12
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
14
13
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
15
14
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -91,7 +90,7 @@ function _default(_ref) {
91
90
  var isRequired = labelInterface.required;
92
91
  if (isRequired) {
93
92
  var newName = labelInterface.label;
94
- if ((0, _probability.computeProbabilityMap)(me.options.renameLabels, labelInterface.label)) {
93
+ if (me.computeProbabilityMap(me.options.renameLabels, labelInterface.label)) {
95
94
  newName = nameGen.generate();
96
95
  }
97
96
  labelInterface.renamed = newName;
@@ -8,7 +8,6 @@ exports["default"] = void 0;
8
8
  var _order = require("../order");
9
9
  var t = _interopRequireWildcard(require("@babel/types"));
10
10
  var _obfuscator = _interopRequireDefault(require("../obfuscator"));
11
- var _probability = require("../probability");
12
11
  var _astUtils = require("../utils/ast-utils");
13
12
  var _constants = require("../constants");
14
13
  var _functionUtils = require("../utils/function-utils");
@@ -18,6 +17,8 @@ var _tamperProtectionTemplates = require("../templates/tamperProtectionTemplates
18
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
19
18
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
20
19
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
20
+ var RGF_ELIGIBLE = Symbol("rgfEligible");
21
+
21
22
  /**
22
23
  * RGF (Runtime-Generated-Function) uses the `new Function("code")` syntax to create executable code from strings.
23
24
  *
@@ -58,19 +59,26 @@ var _default = exports["default"] = function _default(_ref) {
58
59
  }
59
60
  },
60
61
  "FunctionDeclaration|FunctionExpression": {
61
- exit: function exit(_path) {
62
+ enter: function enter(_path) {
62
63
  var _me$options$lock;
63
64
  if (!active) return;
65
+
66
+ // On enter, determine if Function is eligible for RGF transformation
67
+
64
68
  var path = _path;
65
69
  if (me.isSkipped(path)) return;
66
70
 
71
+ // Skip nested functions if the parent function is already deemed eligible
72
+ if (path.find(function (p) {
73
+ return p.node[RGF_ELIGIBLE] || p.node[_constants.MULTI_TRANSFORM];
74
+ })) return;
75
+
67
76
  // Skip async and generator functions
68
77
  if (path.node.async || path.node.generator) return;
69
78
  var name = (0, _astUtils.getFunctionName)(path);
70
79
  if (name === ((_me$options$lock = me.options.lock) === null || _me$options$lock === void 0 ? void 0 : _me$options$lock.countermeasures)) return;
71
80
  if (me.obfuscator.isInternalVariable(name)) return;
72
- me.log(name);
73
- if (!(0, _probability.computeProbabilityMap)(me.options.rgf, name, path.getFunctionParent() === null)) return;
81
+ if (!me.computeProbabilityMap(me.options.rgf, name, path.getFunctionParent() === null)) return;
74
82
 
75
83
  // Skip functions with references to outside variables
76
84
  // Check the scope to see if this function relies on any variables defined outside the function
@@ -86,13 +94,12 @@ var _default = exports["default"] = function _default(_ref) {
86
94
  if (me.options.globalVariables.has(name)) return;
87
95
  var binding = idPath.scope.getBinding(name);
88
96
  if (!binding) {
89
- identifierPreventingTransform = name;
90
- idPath.stop();
97
+ // Global variables are allowed
91
98
  return;
92
99
  }
93
-
100
+ var isOutsideVariable = path.scope.parent.getBinding(name) === binding;
94
101
  // If the binding is not in the current scope, it is an outside reference
95
- if (binding.scope !== path.scope) {
102
+ if (isOutsideVariable) {
96
103
  identifierPreventingTransform = name;
97
104
  idPath.stop();
98
105
  }
@@ -102,14 +109,24 @@ var _default = exports["default"] = function _default(_ref) {
102
109
  me.log("Skipping function " + name + " due to reference to outside variable: " + identifierPreventingTransform);
103
110
  return;
104
111
  }
112
+ me.log("Function " + name + " is eligible for RGF transformation");
113
+ path.node[RGF_ELIGIBLE] = true;
114
+ },
115
+ exit: function exit(_path) {
116
+ if (!active) return;
117
+ var path = _path;
118
+ if (me.isSkipped(path)) return;
119
+
120
+ // Function is not eligible for RGF transformation
121
+ if (!path.node[RGF_ELIGIBLE]) return;
105
122
  var embeddedName = me.getPlaceholder() + "_embedded";
106
123
  var replacementName = me.getPlaceholder() + "_replacement";
107
- var thisName = me.getPlaceholder() + "_this";
124
+ var argumentsName = me.getPlaceholder() + "_args";
108
125
  var lastNode = t.expressionStatement(t.identifier(embeddedName));
109
126
  lastNode[_constants.SKIP] = true;
110
127
 
111
128
  // Transform the function
112
- var evalProgram = t.program([t.functionDeclaration(t.identifier(embeddedName), [], t.blockStatement([t.variableDeclaration("var", [t.variableDeclarator(t.arrayPattern([t.identifier(thisName), t.identifier(rgfArrayName)]), t.thisExpression())]), t.functionDeclaration(t.identifier(replacementName), path.node.params, path.node.body), t.returnStatement(t.callExpression(t.memberExpression(t.identifier(replacementName), t.identifier("apply")), [t.identifier(thisName), t.identifier("arguments")]))])), lastNode]);
129
+ var evalProgram = t.program([t.functionDeclaration(t.identifier(embeddedName), [], t.blockStatement([t.variableDeclaration("var", [t.variableDeclarator(t.arrayPattern([t.identifier(rgfArrayName), t.identifier(argumentsName)]), t.identifier("arguments"))]), t.functionDeclaration(t.identifier(replacementName), path.node.params, path.node.body), t.returnStatement(t.callExpression(t.memberExpression(t.identifier(replacementName), t.identifier("apply")), [t.thisExpression(), t.identifier(argumentsName)]))])), lastNode]);
113
130
  var strictModeEnforcingBlock = path.find(function (p) {
114
131
  return (0, _astUtils.isStrictMode)(p);
115
132
  });
@@ -125,12 +142,14 @@ var _default = exports["default"] = function _default(_ref) {
125
142
  }).map(function (plugin) {
126
143
  return plugin.pluginInstance.order;
127
144
  }));
128
- newObfuscator.plugins = newObfuscator.plugins.filter(function (plugin) {
129
- return plugin.pluginInstance.order == _order.Order.Preparation || !hasRan.has(plugin.pluginInstance.order);
130
- });
131
- newObfuscator.obfuscateAST(evalFile, {
132
- disablePack: true
145
+
146
+ // Global Concealing will likely cause issues when Pack is also enabled
147
+ var disallowedTransforms = new Set([_order.Order.GlobalConcealing]);
148
+ newObfuscator.plugins = newObfuscator.plugins.filter(function (_ref2) {
149
+ var pluginInstance = _ref2.pluginInstance;
150
+ return (pluginInstance.order == _order.Order.Preparation || !hasRan.has(pluginInstance.order)) && !disallowedTransforms.has(pluginInstance.order);
133
151
  });
152
+ newObfuscator.obfuscateAST(evalFile);
134
153
  var generated = _obfuscator["default"].generateCode(evalFile);
135
154
  var functionExpression = t.callExpression(t.identifier(rgfEvalName), [t.stringLiteral(generated)]);
136
155
  var index = rgfArrayExpression.elements.length;
@@ -147,7 +166,8 @@ var _default = exports["default"] = function _default(_ref) {
147
166
  me.skip(path);
148
167
 
149
168
  // Update body to point to new function
150
- path.get("body").replaceWith(t.blockStatement([t.returnStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(rgfArrayName), (0, _node.numericLiteral)(index), true), t.stringLiteral("apply"), true), [t.arrayExpression([t.thisExpression(), t.identifier(rgfArrayName)]), t.identifier("arguments")]))]));
169
+ path.get("body").replaceWith(t.blockStatement([t.returnStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(rgfArrayName), (0, _node.numericLiteral)(index), true), t.stringLiteral("apply"), true), [t.thisExpression(), t.arrayExpression([t.identifier(rgfArrayName), t.identifier("arguments")])]))]));
170
+ path.skip();
151
171
  me.setFunctionLength(path, originalLength);
152
172
  me.changeData.functions++;
153
173
  }