js-confuser 1.5.9 → 1.7.0

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 (143) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +346 -165
  4. package/dist/constants.js +6 -2
  5. package/dist/index.js +9 -21
  6. package/dist/obfuscator.js +19 -31
  7. package/dist/options.js +5 -5
  8. package/dist/order.js +1 -3
  9. package/dist/presets.js +6 -7
  10. package/dist/probability.js +2 -4
  11. package/dist/templates/bufferToString.js +13 -0
  12. package/dist/templates/crash.js +3 -3
  13. package/dist/templates/es5.js +18 -0
  14. package/dist/templates/functionLength.js +16 -0
  15. package/dist/transforms/calculator.js +77 -21
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
  18. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  19. package/dist/transforms/deadCode.js +33 -25
  20. package/dist/transforms/dispatcher.js +8 -4
  21. package/dist/transforms/es5/antiDestructuring.js +2 -0
  22. package/dist/transforms/es5/es5.js +31 -34
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
  24. package/dist/transforms/finalizer.js +82 -0
  25. package/dist/transforms/flatten.js +229 -148
  26. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  27. package/dist/transforms/identifier/globalConcealing.js +10 -83
  28. package/dist/transforms/identifier/movedDeclarations.js +35 -88
  29. package/dist/transforms/identifier/renameVariables.js +124 -59
  30. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  31. package/dist/transforms/lock/lock.js +0 -37
  32. package/dist/transforms/minify.js +60 -57
  33. package/dist/transforms/opaquePredicates.js +1 -1
  34. package/dist/transforms/preparation/preparation.js +2 -2
  35. package/dist/transforms/preparation.js +231 -0
  36. package/dist/transforms/renameLabels.js +1 -1
  37. package/dist/transforms/rgf.js +139 -247
  38. package/dist/transforms/stack.js +128 -26
  39. package/dist/transforms/string/encoding.js +150 -179
  40. package/dist/transforms/string/stringCompression.js +14 -15
  41. package/dist/transforms/string/stringConcealing.js +25 -8
  42. package/dist/transforms/string/stringEncoding.js +13 -24
  43. package/dist/transforms/transform.js +12 -19
  44. package/dist/traverse.js +24 -10
  45. package/dist/util/gen.js +17 -1
  46. package/dist/util/identifiers.js +37 -3
  47. package/dist/util/insert.js +35 -4
  48. package/dist/util/random.js +15 -0
  49. package/docs/ControlFlowFlattening.md +595 -0
  50. package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
  51. package/{Integrity.md → docs/Integrity.md} +2 -2
  52. package/docs/RGF.md +419 -0
  53. package/package.json +5 -5
  54. package/src/constants.ts +3 -0
  55. package/src/index.ts +2 -2
  56. package/src/obfuscator.ts +19 -31
  57. package/src/options.ts +14 -103
  58. package/src/order.ts +1 -5
  59. package/src/presets.ts +6 -7
  60. package/src/probability.ts +2 -3
  61. package/src/templates/bufferToString.ts +68 -0
  62. package/src/templates/crash.ts +15 -19
  63. package/src/templates/es5.ts +131 -0
  64. package/src/templates/functionLength.ts +14 -0
  65. package/src/transforms/calculator.ts +122 -59
  66. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  67. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
  68. package/src/transforms/deadCode.ts +383 -26
  69. package/src/transforms/dispatcher.ts +9 -4
  70. package/src/transforms/es5/antiDestructuring.ts +2 -0
  71. package/src/transforms/es5/es5.ts +32 -77
  72. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
  73. package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
  74. package/src/transforms/flatten.ts +357 -300
  75. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  76. package/src/transforms/identifier/globalConcealing.ts +14 -103
  77. package/src/transforms/identifier/movedDeclarations.ts +49 -102
  78. package/src/transforms/identifier/renameVariables.ts +149 -78
  79. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  80. package/src/transforms/lock/lock.ts +1 -42
  81. package/src/transforms/minify.ts +91 -75
  82. package/src/transforms/opaquePredicates.ts +2 -2
  83. package/src/transforms/preparation.ts +238 -0
  84. package/src/transforms/renameLabels.ts +2 -2
  85. package/src/transforms/rgf.ts +213 -405
  86. package/src/transforms/stack.ts +156 -36
  87. package/src/transforms/string/encoding.ts +115 -212
  88. package/src/transforms/string/stringCompression.ts +27 -18
  89. package/src/transforms/string/stringConcealing.ts +39 -9
  90. package/src/transforms/string/stringEncoding.ts +18 -18
  91. package/src/transforms/transform.ts +21 -23
  92. package/src/traverse.ts +23 -4
  93. package/src/types.ts +2 -1
  94. package/src/util/gen.ts +28 -3
  95. package/src/util/identifiers.ts +43 -2
  96. package/src/util/insert.ts +38 -3
  97. package/src/util/random.ts +13 -0
  98. package/test/code/Cash.test.ts +1 -1
  99. package/test/code/Dynamic.test.ts +12 -10
  100. package/test/code/ES6.src.js +146 -0
  101. package/test/code/ES6.test.ts +28 -2
  102. package/test/index.test.ts +2 -1
  103. package/test/probability.test.ts +44 -0
  104. package/test/templates/template.test.ts +1 -1
  105. package/test/transforms/antiTooling.test.ts +22 -0
  106. package/test/transforms/calculator.test.ts +40 -0
  107. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
  108. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  109. package/test/transforms/deadCode.test.ts +66 -15
  110. package/test/transforms/dispatcher.test.ts +20 -1
  111. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  112. package/test/transforms/flatten.test.ts +399 -86
  113. package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
  114. package/test/transforms/identifier/renameVariables.test.ts +119 -0
  115. package/test/transforms/lock/antiDebug.test.ts +2 -2
  116. package/test/transforms/lock/lock.test.ts +1 -48
  117. package/test/transforms/minify.test.ts +104 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +261 -381
  120. package/test/transforms/stack.test.ts +143 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +82 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/identifiers.test.ts +113 -1
  127. package/test/util/insert.test.ts +57 -3
  128. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  129. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  130. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  131. package/src/transforms/eval.ts +0 -89
  132. package/src/transforms/hideInitializingCode.ts +0 -432
  133. package/src/transforms/identifier/nameRecycling.ts +0 -280
  134. package/src/transforms/label.ts +0 -64
  135. package/src/transforms/preparation/nameConflicts.ts +0 -102
  136. package/src/transforms/preparation/preparation.ts +0 -176
  137. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  138. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  139. package/test/transforms/eval.test.ts +0 -131
  140. package/test/transforms/hideInitializingCode.test.ts +0 -336
  141. package/test/transforms/identifier/nameRecycling.test.ts +0 -205
  142. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  143. package/test/transforms/preparation/preparation.test.ts +0 -62
package/dist/constants.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.reservedKeywords = exports.reservedIdentifiers = void 0;
6
+ exports.reservedKeywords = exports.reservedIdentifiers = exports.placeholderVariablePrefix = exports.noRenameVariablePrefix = void 0;
7
7
 
8
8
  /**
9
9
  * Keywords disallowed for variable names in ES5 and under.
@@ -15,4 +15,8 @@ const reservedKeywords = new Set(["abstract", "arguments", "await", "boolean", "
15
15
 
16
16
  exports.reservedKeywords = reservedKeywords;
17
17
  const reservedIdentifiers = new Set(["undefined", "null", "NaN", "Infinity", "eval", "arguments"]);
18
- exports.reservedIdentifiers = reservedIdentifiers;
18
+ exports.reservedIdentifiers = reservedIdentifiers;
19
+ const noRenameVariablePrefix = "__NO_JS_CONFUSER_RENAME__";
20
+ exports.noRenameVariablePrefix = noRenameVariablePrefix;
21
+ const placeholderVariablePrefix = "__p_";
22
+ exports.placeholderVariablePrefix = placeholderVariablePrefix;
package/dist/index.js CHANGED
@@ -37,8 +37,6 @@ var _object = require("./util/object");
37
37
 
38
38
  var _presets = _interopRequireDefault(require("./presets"));
39
39
 
40
- var _perf_hooks = require("perf_hooks");
41
-
42
40
  var assert = _interopRequireWildcard(require("assert"));
43
41
 
44
42
  var _options = require("./options");
@@ -136,38 +134,28 @@ const debugTransformations = async function (code, options) {
136
134
 
137
135
  exports.debugTransformations = debugTransformations;
138
136
 
139
- const debugObfuscation = async function (code, options, callback) {
140
- const startTime = _perf_hooks.performance.now();
141
-
137
+ const debugObfuscation = async function (code, options, callback, performance) {
138
+ const startTime = performance.now();
142
139
  (0, _options.validateOptions)(options);
143
140
  options = await (0, _options.correctOptions)(options);
144
-
145
- const beforeParseTime = _perf_hooks.performance.now();
146
-
141
+ const beforeParseTime = performance.now();
147
142
  var tree = (0, _parser.parseSync)(code);
148
- const parseTime = _perf_hooks.performance.now() - beforeParseTime;
143
+ const parseTime = performance.now() - beforeParseTime;
149
144
  var obfuscator = new _obfuscator.default(options);
150
145
  var totalTransforms = obfuscator.array.length;
151
146
  var transformationTimes = Object.create(null);
152
-
153
- var currentTransformTime = _perf_hooks.performance.now();
154
-
147
+ var currentTransformTime = performance.now();
155
148
  obfuscator.on("debug", (name, tree, i) => {
156
- var nowTime = _perf_hooks.performance.now();
157
-
149
+ var nowTime = performance.now();
158
150
  transformationTimes[name] = nowTime - currentTransformTime;
159
151
  currentTransformTime = nowTime;
160
152
  callback(name, i, totalTransforms);
161
153
  });
162
154
  await obfuscator.apply(tree, true);
163
-
164
- const beforeCompileTime = _perf_hooks.performance.now();
165
-
155
+ const beforeCompileTime = performance.now();
166
156
  var output = await (0, _compiler.default)(tree, options);
167
- const compileTime = _perf_hooks.performance.now() - beforeCompileTime;
168
-
169
- const endTime = _perf_hooks.performance.now();
170
-
157
+ const compileTime = performance.now() - beforeCompileTime;
158
+ const endTime = performance.now();
171
159
  return {
172
160
  obfuscated: output,
173
161
  transformationTimes: transformationTimes,
@@ -13,7 +13,7 @@ var _traverse = _interopRequireDefault(require("./traverse"));
13
13
 
14
14
  var _probability = require("./probability");
15
15
 
16
- var _preparation = _interopRequireDefault(require("./transforms/preparation/preparation"));
16
+ var _preparation = _interopRequireDefault(require("./transforms/preparation"));
17
17
 
18
18
  var _objectExtraction = _interopRequireDefault(require("./transforms/extraction/objectExtraction"));
19
19
 
@@ -29,13 +29,13 @@ var _calculator = _interopRequireDefault(require("./transforms/calculator"));
29
29
 
30
30
  var _controlFlowFlattening = _interopRequireDefault(require("./transforms/controlFlowFlattening/controlFlowFlattening"));
31
31
 
32
- var _eval = _interopRequireDefault(require("./transforms/eval"));
33
-
34
32
  var _globalConcealing = _interopRequireDefault(require("./transforms/identifier/globalConcealing"));
35
33
 
34
+ var _stringSplitting = _interopRequireDefault(require("./transforms/string/stringSplitting"));
35
+
36
36
  var _stringConcealing = _interopRequireDefault(require("./transforms/string/stringConcealing"));
37
37
 
38
- var _stringSplitting = _interopRequireDefault(require("./transforms/string/stringSplitting"));
38
+ var _stringCompression = _interopRequireDefault(require("./transforms/string/stringCompression"));
39
39
 
40
40
  var _duplicateLiteralsRemoval = _interopRequireDefault(require("./transforms/extraction/duplicateLiteralsRemoval"));
41
41
 
@@ -51,23 +51,15 @@ var _minify = _interopRequireDefault(require("./transforms/minify"));
51
51
 
52
52
  var _es = _interopRequireDefault(require("./transforms/es5/es5"));
53
53
 
54
- var _stringEncoding = _interopRequireDefault(require("./transforms/string/stringEncoding"));
55
-
56
54
  var _rgf = _interopRequireDefault(require("./transforms/rgf"));
57
55
 
58
56
  var _flatten = _interopRequireDefault(require("./transforms/flatten"));
59
57
 
60
58
  var _stack = _interopRequireDefault(require("./transforms/stack"));
61
59
 
62
- var _stringCompression = _interopRequireDefault(require("./transforms/string/stringCompression"));
63
-
64
- var _nameRecycling = _interopRequireDefault(require("./transforms/identifier/nameRecycling"));
65
-
66
60
  var _antiTooling = _interopRequireDefault(require("./transforms/antiTooling"));
67
61
 
68
- var _hideInitializingCode = _interopRequireDefault(require("./transforms/hideInitializingCode"));
69
-
70
- var _hexadecimalNumbers = _interopRequireDefault(require("./transforms/hexadecimalNumbers"));
62
+ var _finalizer = _interopRequireDefault(require("./transforms/finalizer"));
71
63
 
72
64
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
73
65
 
@@ -100,8 +92,6 @@ class Obfuscator extends _events.EventEmitter {
100
92
  this.transforms = Object.create(null);
101
93
  this.generated = new Set();
102
94
  this.totalPossibleTransforms = 0;
103
- this.push(new _preparation.default(this));
104
- this.push(new _renameLabels.default(this));
105
95
 
106
96
  const test = function (map) {
107
97
  for (var _len = arguments.length, transformers = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
@@ -118,31 +108,29 @@ class Obfuscator extends _events.EventEmitter {
118
108
  }; // Optimization: Only add needed transformers. If a probability always return false, no need in running that extra code.
119
109
 
120
110
 
111
+ test(true, _preparation.default);
112
+ test(true, _renameLabels.default);
121
113
  test(options.objectExtraction, _objectExtraction.default);
122
- test(options.deadCode, _deadCode.default);
114
+ test(options.flatten, _flatten.default);
115
+ test(options.rgf, _rgf.default);
123
116
  test(options.dispatcher, _dispatcher.default);
117
+ test(options.deadCode, _deadCode.default);
118
+ test(options.calculator, _calculator.default);
124
119
  test(options.controlFlowFlattening, _controlFlowFlattening.default);
125
120
  test(options.globalConcealing, _globalConcealing.default);
126
- test(options.stringCompression, _stringCompression.default);
127
- test(options.stringConcealing, _stringConcealing.default);
128
- test(options.stringEncoding, _stringEncoding.default);
129
- test(options.stringSplitting, _stringSplitting.default);
130
- test(options.renameVariables, _renameVariables.default);
131
- test(options.nameRecycling, _nameRecycling.default);
132
- test(options.eval, _eval.default);
133
121
  test(options.opaquePredicates, _opaquePredicates.default);
122
+ test(options.stringSplitting, _stringSplitting.default);
123
+ test(options.stringConcealing, _stringConcealing.default);
124
+ test(options.stringCompression, _stringCompression.default);
125
+ test(options.stack, _stack.default);
134
126
  test(options.duplicateLiteralsRemoval, _duplicateLiteralsRemoval.default);
135
- test(options.minify, _minify.default);
136
- test(options.calculator, _calculator.default);
127
+ test(options.shuffle, _shuffle.default);
137
128
  test(options.movedDeclarations, _movedDeclarations.default);
129
+ test(options.minify, _minify.default);
130
+ test(options.renameVariables, _renameVariables.default);
138
131
  test(options.es5, _es.default);
139
- test(options.shuffle, _shuffle.default);
140
- test(options.flatten, _flatten.default);
141
- test(options.rgf, _rgf.default);
142
- test(options.stack, _stack.default);
143
132
  test(true, _antiTooling.default);
144
- test(options.hideInitializingCode, _hideInitializingCode.default);
145
- test(true, _hexadecimalNumbers.default); // BigInt support is included
133
+ test(true, _finalizer.default); // String Encoding, Hexadecimal Numbers, BigInt support is included
146
134
 
147
135
  if (options.lock && Object.keys(options.lock).filter(x => x == "domainLock" ? options.lock.domainLock && options.lock.domainLock.length : options.lock[x]).length) {
148
136
  test(true, _lock.default);
package/dist/options.js CHANGED
@@ -12,12 +12,12 @@ var _presets = _interopRequireDefault(require("./presets"));
12
12
 
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
14
 
15
- const validProperties = new Set(["preset", "target", "indent", "compact", "hexadecimalNumbers", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "nameRecycling", "controlFlowFlattening", "hideInitializingCode", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "eval", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "stack", "verbose", "globalVariables", "debugComments"]);
15
+ const validProperties = new Set(["preset", "target", "indent", "compact", "hexadecimalNumbers", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "controlFlowFlattening", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "stack", "verbose", "globalVariables", "debugComments"]);
16
16
  const validOses = new Set(["windows", "linux", "osx", "ios", "android"]);
17
17
  const validBrowsers = new Set(["firefox", "chrome", "iexplorer", "edge", "safari", "opera"]);
18
18
 
19
19
  function validateOptions(options) {
20
- if (Object.keys(options).length <= 1) {
20
+ if (!options || Object.keys(options).length <= 1) {
21
21
  /**
22
22
  * Give a welcoming introduction to those who skipped the documentation.
23
23
  */
@@ -117,13 +117,13 @@ async function correctOptions(options) {
117
117
 
118
118
  if (options.target == "browser") {
119
119
  // browser
120
- ["window", "document", "postMessage", "alert", "confirm", "location"].forEach(x => options.globalVariables.add(x));
120
+ ["window", "document", "postMessage", "alert", "confirm", "location", "btoa", "atob", "unescape", "encodeURIComponent"].forEach(x => options.globalVariables.add(x));
121
121
  } else {
122
122
  // node
123
- ["global", "Buffer", "require", "process", "__dirname", "__filename"].forEach(x => options.globalVariables.add(x));
123
+ ["global", "Buffer", "require", "process", "exports", "module", "__dirname", "__filename"].forEach(x => options.globalVariables.add(x));
124
124
  }
125
125
 
126
- ["globalThis", "console", "parseInt", "parseFloat", "Math", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "exports", "module", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol"].forEach(x => options.globalVariables.add(x));
126
+ ["globalThis", "console", "parseInt", "parseFloat", "Math", "JSON", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol"].forEach(x => options.globalVariables.add(x));
127
127
  }
128
128
 
129
129
  return options;
package/dist/order.js CHANGED
@@ -27,7 +27,6 @@ exports.ObfuscateOrder = ObfuscateOrder;
27
27
  ObfuscateOrder[ObfuscateOrder["StringSplitting"] = 16] = "StringSplitting";
28
28
  ObfuscateOrder[ObfuscateOrder["StringConcealing"] = 17] = "StringConcealing";
29
29
  ObfuscateOrder[ObfuscateOrder["StringCompression"] = 18] = "StringCompression";
30
- ObfuscateOrder[ObfuscateOrder["HideInitializingCode"] = 19] = "HideInitializingCode";
31
30
  ObfuscateOrder[ObfuscateOrder["Stack"] = 20] = "Stack";
32
31
  ObfuscateOrder[ObfuscateOrder["DuplicateLiteralsRemoval"] = 22] = "DuplicateLiteralsRemoval";
33
32
  ObfuscateOrder[ObfuscateOrder["Shuffle"] = 24] = "Shuffle";
@@ -37,7 +36,6 @@ exports.ObfuscateOrder = ObfuscateOrder;
37
36
  ObfuscateOrder[ObfuscateOrder["Minify"] = 28] = "Minify";
38
37
  ObfuscateOrder[ObfuscateOrder["RenameVariables"] = 30] = "RenameVariables";
39
38
  ObfuscateOrder[ObfuscateOrder["ES5"] = 31] = "ES5";
40
- ObfuscateOrder[ObfuscateOrder["StringEncoding"] = 32] = "StringEncoding";
41
39
  ObfuscateOrder[ObfuscateOrder["AntiTooling"] = 34] = "AntiTooling";
42
- ObfuscateOrder[ObfuscateOrder["HexadecimalNumbers"] = 35] = "HexadecimalNumbers";
40
+ ObfuscateOrder[ObfuscateOrder["Finalizer"] = 35] = "Finalizer";
43
41
  })(ObfuscateOrder || (exports.ObfuscateOrder = ObfuscateOrder = {}));
package/dist/presets.js CHANGED
@@ -22,7 +22,7 @@ exports.default = void 0;
22
22
  * 10. Minified output
23
23
  *
24
24
  * ## **`Disabled features`**
25
- * - `eval` Use at your own risk!
25
+ * - `rgf` Use at your own risk!
26
26
  *
27
27
  * ### Potential Issues
28
28
  * 1. *String Encoding* can corrupt files. Disable `stringEncoding` manually if this happens.
@@ -57,7 +57,6 @@ const highPreset = {
57
57
  stringEncoding: true,
58
58
  stringSplitting: 0.75,
59
59
  // Use at own risk
60
- eval: false,
61
60
  rgf: false
62
61
  };
63
62
  /**
@@ -71,9 +70,9 @@ const mediumPreset = {
71
70
  calculator: true,
72
71
  compact: true,
73
72
  hexadecimalNumbers: true,
74
- controlFlowFlattening: 0.5,
73
+ controlFlowFlattening: 0.25,
75
74
  deadCode: 0.025,
76
- dispatcher: 0.75,
75
+ dispatcher: 0.5,
77
76
  duplicateLiteralsRemoval: 0.5,
78
77
  globalConcealing: true,
79
78
  identifierGenerator: "randomized",
@@ -99,10 +98,10 @@ const lowPreset = {
99
98
  calculator: true,
100
99
  compact: true,
101
100
  hexadecimalNumbers: true,
102
- controlFlowFlattening: 0.25,
101
+ controlFlowFlattening: 0.1,
103
102
  deadCode: 0.01,
104
- dispatcher: 0.5,
105
- duplicateLiteralsRemoval: true,
103
+ dispatcher: 0.25,
104
+ duplicateLiteralsRemoval: 0.5,
106
105
  identifierGenerator: "randomized",
107
106
  minify: true,
108
107
  movedDeclarations: true,
@@ -77,6 +77,8 @@ function ComputeProbabilityMap(map) {
77
77
 
78
78
 
79
79
  function isProbabilityMapProbable(map) {
80
+ (0, _assert.ok)(!Number.isNaN(map), "Numbers cannot be NaN");
81
+
80
82
  if (!map || typeof map === "undefined") {
81
83
  return false;
82
84
  }
@@ -89,10 +91,6 @@ function isProbabilityMapProbable(map) {
89
91
  if (map > 1 || map < 0) {
90
92
  throw new Error("Numbers must be between 0 and 1 for 0% - 100%");
91
93
  }
92
-
93
- if (isNaN(map)) {
94
- throw new Error("Numbers cannot be NaN");
95
- }
96
94
  }
97
95
 
98
96
  if (Array.isArray(map)) {
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.BufferToStringTemplate = void 0;
7
+
8
+ var _template = _interopRequireDefault(require("./template"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ const BufferToStringTemplate = (0, _template.default)("\n function __getGlobal(){\n try {\n return global||window|| ( new Function(\"return this\") )();\n } catch ( e ) {\n try {\n return this;\n } catch ( e ) {\n return {};\n }\n }\n }\n\n var __globalObject = __getGlobal() || {};\n var __TextDecoder = __globalObject[\"TextDecoder\"];\n var __Uint8Array = __globalObject[\"Uint8Array\"];\n var __Buffer = __globalObject[\"Buffer\"];\n var __String = __globalObject[\"String\"] || String;\n var __Array = __globalObject[\"Array\"] || Array;\n\n var utf8ArrayToStr = (function () {\n var charCache = new __Array(128); // Preallocate the cache for the common single byte chars\n var charFromCodePt = __String[\"fromCodePoint\"] || __String[\"fromCharCode\"];\n var result = [];\n\n return function (array) {\n var codePt, byte1;\n var buffLen = array[\"length\"];\n\n result[\"length\"] = 0;\n\n for (var i = 0; i < buffLen;) {\n byte1 = array[i++];\n\n if (byte1 <= 0x7F) {\n codePt = byte1;\n } else if (byte1 <= 0xDF) {\n codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);\n } else if (byte1 <= 0xEF) {\n codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);\n } else if (__String[\"fromCodePoint\"]) {\n codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);\n } else {\n codePt = 63; // Cannot convert four byte code points, so use \"?\" instead\n i += 3;\n }\n\n result[\"push\"](charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt)));\n }\n\n return result[\"join\"]('');\n };\n })();\n\n function {name}(buffer){\n if(typeof __TextDecoder !== \"undefined\" && __TextDecoder) {\n return new __TextDecoder()[\"decode\"](new __Uint8Array(buffer));\n } else if(typeof __Buffer !== \"undefined\" && __Buffer) {\n return __Buffer[\"from\"](buffer)[\"toString\"](\"utf-8\");\n } else { \n return utf8ArrayToStr(buffer);\n }\n }\n\n \n");
13
+ exports.BufferToStringTemplate = BufferToStringTemplate;
@@ -9,9 +9,9 @@ var _template = _interopRequireDefault(require("./template"));
9
9
 
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
11
 
12
- const CrashTemplate1 = (0, _template.default)("\ntry {\n if(typeof process !== \"undefined\") {\n Math.random() > 0.5 && process && process.exit();\n }\n} catch ( e ) {\n \n}\n\nvar {var} = \"a\";\nwhile(1){\n {var} = {var} += \"a\"; //add as much as the browser can handle\n}\n");
12
+ const CrashTemplate1 = (0, _template.default)("\nvar {var} = \"a\";\nwhile(1){\n {var} = {var} += \"a\";\n}\n");
13
13
  exports.CrashTemplate1 = CrashTemplate1;
14
- const CrashTemplate2 = (0, _template.default)("\nwhile(true) {\n for(var {var} = 99; {var} == {var}; {var} *= {var}) {\n !{var} && console.log({var});\n if ({var} <= 10){\n break;\n }\n };\n };");
14
+ const CrashTemplate2 = (0, _template.default)("\nwhile(true) {\n var {var} = 99;\n for({var} = 99; {var} == {var}; {var} *= {var}) {\n !{var} && console.log({var});\n if ({var} <= 10){\n break;\n }\n };\n if({var} === 100) {\n {var}--\n }\n };");
15
15
  exports.CrashTemplate2 = CrashTemplate2;
16
- const CrashTemplate3 = (0, _template.default)("\ntry {\n function {$2}(y, x){\n return x;\n }\n \n var {$1} = {$2}(this, function () {\n var {$3} = function () {\n var regExp = {$3}\n .constructor('return /\" + this + \"/')()\n .constructor('^([^ ]+( +[^ ]+)+)+[^ ]}');\n \n return !regExp.call({$1});\n };\n \n return {$3}();\n });\n \n {$1}();\n} catch ( e ) {\n while(e ? e : !e){\n var b;\n var c = 0;\n (e ? !e : e) ? (function(e){\n c = e ? 0 : !e ? 1 : 0;\n })(e) : b = 1;\n\n if(b&&c){break;}\n if(b){continue;}\n }\n}\n");
16
+ const CrashTemplate3 = (0, _template.default)("\ntry {\n function {$2}(y, x){\n return x;\n }\n \n var {$1} = {$2}(this, function () {\n var {$3} = function () {\n var regExp = {$3}\n .constructor('return /\" + this + \"/')()\n .constructor('^([^ ]+( +[^ ]+)+)+[^ ]}');\n \n return !regExp.call({$1});\n };\n \n return {$3}();\n });\n \n {$1}();\n} catch ( {$1}e ) {\n while({$1}e ? {$1}e : !{$1}e){\n var {$1}b;\n var {$1}c = 0;\n ({$1}e ? !{$1}e : {$1}e) ? (function({$1}e){\n {$1}c = {$1}e ? 0 : !{$1}e ? 1 : 0;\n })({$1}e) : {$1}b = 1;\n\n if({$1}b&&{$1}c){break;}\n if({$1}b){continue;}\n }\n}\n");
17
17
  exports.CrashTemplate3 = CrashTemplate3;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ES5Template = void 0;
7
+
8
+ var _template = _interopRequireDefault(require("./template"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ /**
13
+ * Provides ES5 polyfills for Array methods
14
+ *
15
+ * Source: https://vanillajstoolkit.com/polyfills/
16
+ */
17
+ const ES5Template = (0, _template.default)("\nif (!Array.prototype.forEach) {\n Array.prototype.forEach = function forEach (callback, thisArg) {\n if (typeof callback !== 'function') {\n throw new TypeError(callback + ' is not a function');\n }\n var array = this;\n thisArg = thisArg || this;\n for (var i = 0, l = array.length; i !== l; ++i) {\n callback.call(thisArg, array[i], i, array);\n }\n };\n}\nif (!Array.prototype.filter)\n Array.prototype.filter = function(func, thisArg) {\n\t'use strict';\n\tif ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )\n\t\tthrow new TypeError();\n\n\tvar len = this.length >>> 0,\n\t\tres = new Array(len), // preallocate array\n\t\tt = this, c = 0, i = -1;\n\tif (thisArg === undefined)\n\t while (++i !== len)\n\t\t// checks to see if the key was set\n\t\tif (i in this)\n\t\t if (func(t[i], i, t))\n\t\t\tres[c++] = t[i];\n\telse\n\t while (++i !== len)\n\t\t// checks to see if the key was set\n\t\tif (i in this)\n\t\t if (func.call(thisArg, t[i], i, t))\n\t\t\tres[c++] = t[i];\n\n\tres.length = c; // shrink down array to proper size\n\treturn res;\n};\nif (!Array.prototype.map) {\n Array.prototype.map = function(callback, thisArg) {\n var T, A, k;\n\n if (this == null) {\n throw new TypeError('this is null or not defined');\n }\n\n // 1. Let O be the result of calling ToObject passing the |this|\n // value as the argument.\n var O = Object(this);\n\n // 2. Let lenValue be the result of calling the Get internal\n // method of O with the argument \"length\".\n // 3. Let len be ToUint32(lenValue).\n var len = O.length >>> 0;\n\n // 4. If IsCallable(callback) is false, throw a TypeError exception.\n // See: http://es5.github.com/#x9.11\n if (typeof callback !== 'function') {\n throw new TypeError(callback + ' is not a function');\n }\n\n // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 1) {\n T = arguments[1];\n }\n\n // 6. Let A be a new array created as if by the expression new Array(len)\n // where Array is the standard built-in constructor with that name and\n // len is the value of len.\n A = new Array(len);\n\n // 7. Let k be 0\n k = 0;\n\n // 8. Repeat, while k < len\n while (k < len) {\n\n var kValue, mappedValue;\n\n // a. Let Pk be ToString(k).\n // This is implicit for LHS operands of the in operator\n // b. Let kPresent be the result of calling the HasProperty internal\n // method of O with argument Pk.\n // This step can be combined with c\n // c. If kPresent is true, then\n if (k in O) {\n\n // i. Let kValue be the result of calling the Get internal\n // method of O with argument Pk.\n kValue = O[k];\n\n // ii. Let mappedValue be the result of calling the Call internal\n // method of callback with T as the this value and argument\n // list containing kValue, k, and O.\n mappedValue = callback.call(T, kValue, k, O);\n\n // iii. Call the DefineOwnProperty internal method of A with arguments\n // Pk, Property Descriptor\n // { Value: mappedValue,\n // Writable: true,\n // Enumerable: true,\n // Configurable: true },\n // and false.\n\n // In browsers that support Object.defineProperty, use the following:\n // Object.defineProperty(A, k, {\n // value: mappedValue,\n // writable: true,\n // enumerable: true,\n // configurable: true\n // });\n\n // For best browser support, use the following:\n A[k] = mappedValue;\n }\n // d. Increase k by 1.\n k++;\n }\n\n // 9. return A\n return A;\n };\n}\n");
18
+ exports.ES5Template = ES5Template;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FunctionLengthTemplate = void 0;
7
+
8
+ var _template = _interopRequireDefault(require("./template"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ /**
13
+ * Helper function to set `function.length` property.
14
+ */
15
+ const FunctionLengthTemplate = (0, _template.default)("\nfunction {name}(functionObject, functionLength){\n Object[\"defineProperty\"](functionObject, \"length\", {\n \"value\": functionLength,\n \"configurable\": true\n });\n return functionObject;\n}\n");
16
+ exports.FunctionLengthTemplate = FunctionLengthTemplate;
@@ -21,10 +21,15 @@ var _precedence = require("../precedence");
21
21
 
22
22
  var _template = _interopRequireDefault(require("../templates/template"));
23
23
 
24
+ var _probability = require("../probability");
25
+
24
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
27
 
26
28
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
27
29
 
30
+ const allowedBinaryOperators = new Set(["+", "-", "*", "/"]);
31
+ const allowedUnaryOperators = new Set(["!", "void", "typeof", "-", "~", "+"]);
32
+
28
33
  class Calculator extends _transform.default {
29
34
  constructor(o) {
30
35
  super(o, _order.ObfuscateOrder.Calculator);
@@ -43,7 +48,7 @@ class Calculator extends _transform.default {
43
48
 
44
49
  this.ops = Object.create(null);
45
50
  this.statesUsed = new Set();
46
- this.calculatorFn = this.getPlaceholder();
51
+ this.calculatorFn = this.getPlaceholder() + "_calc";
47
52
  this.calculatorOpVar = this.getPlaceholder();
48
53
  this.calculatorSetOpFn = this.getPlaceholder();
49
54
  this.gen = this.getGenerator();
@@ -59,10 +64,19 @@ class Calculator extends _transform.default {
59
64
  var leftArg = this.getPlaceholder();
60
65
  var rightArg = this.getPlaceholder();
61
66
  var switchCases = [];
62
- Object.keys(this.ops).forEach(operator => {
63
- var code = this.ops[operator];
64
- var factory = operator == "&&" || operator == "||" ? _gen.LogicalExpression : _gen.BinaryExpression;
65
- var body = [(0, _gen.ReturnStatement)(factory(operator, (0, _gen.Identifier)(leftArg), (0, _gen.Identifier)(rightArg)))];
67
+ Object.keys(this.ops).forEach(opKey => {
68
+ var [type, operator] = opKey.split("_");
69
+ var code = this.ops[opKey];
70
+ var body = [];
71
+
72
+ if (type === "Binary") {
73
+ body = [(0, _gen.ReturnStatement)((0, _gen.BinaryExpression)(operator, (0, _gen.Identifier)(leftArg), (0, _gen.Identifier)(rightArg)))];
74
+ } else if (type === "Unary") {
75
+ body = [(0, _gen.ReturnStatement)((0, _gen.UnaryExpression)(operator, (0, _gen.Identifier)(leftArg)))];
76
+ } else {
77
+ throw new Error("Unknown type: " + type);
78
+ }
79
+
66
80
  switchCases.push((0, _gen.SwitchCase)((0, _gen.Literal)(code), body));
67
81
  });
68
82
  var func = (0, _gen.FunctionDeclaration)(this.calculatorFn, [leftArg, rightArg].map(x => (0, _gen.Identifier)(x)), [(0, _gen.SwitchStatement)((0, _gen.Identifier)(this.calculatorOpVar), switchCases)]);
@@ -75,43 +89,85 @@ class Calculator extends _transform.default {
75
89
  }
76
90
 
77
91
  match(object, parents) {
78
- return object.type == "BinaryExpression";
92
+ return object.type === "BinaryExpression" || object.type === "UnaryExpression";
79
93
  }
80
94
 
81
95
  transform(object, parents) {
82
- var operator = object.operator;
83
- var allowedOperators = new Set(["+", "-", "*", "/"]);
84
-
85
- if (!allowedOperators.has(operator)) {
96
+ // Allow percentage
97
+ if (!(0, _probability.ComputeProbabilityMap)(this.options.calculator)) {
86
98
  return;
87
99
  }
88
100
 
89
- var myPrecedence = _precedence.OPERATOR_PRECEDENCE[operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(operator) / 100;
90
- var precedences = parents.map(x => x.type == "BinaryExpression" && _precedence.OPERATOR_PRECEDENCE[x.operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(x.operator) / 100); // corrupt AST
101
+ var operator = object.operator;
102
+ var type;
91
103
 
92
- if (precedences.find(x => x >= myPrecedence)) {
93
- return;
104
+ if (object.type === "BinaryExpression") {
105
+ type = "Binary";
106
+
107
+ if (!allowedBinaryOperators.has(operator)) {
108
+ return;
109
+ } // Additional checks to ensure complex expressions still work
110
+
111
+
112
+ var myPrecedence = _precedence.OPERATOR_PRECEDENCE[operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(operator) / 100;
113
+ var precedences = parents.map(x => x.type == "BinaryExpression" && _precedence.OPERATOR_PRECEDENCE[x.operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(x.operator) / 100); // corrupt AST
114
+
115
+ if (precedences.find(x => x >= myPrecedence)) {
116
+ return;
117
+ }
118
+
119
+ if (parents.find(x => x.$dispatcherSkip || x.type == "BinaryExpression")) {
120
+ return;
121
+ }
94
122
  }
95
123
 
96
- if (parents.find(x => x.$dispatcherSkip || x.type == "BinaryExpression")) {
97
- return;
124
+ if (object.type === "UnaryExpression") {
125
+ type = "Unary";
126
+
127
+ if (!allowedUnaryOperators.has(operator)) {
128
+ return;
129
+ } // Typeof expression fix
130
+
131
+
132
+ if (operator === "typeof" && object.argument.type === "Identifier") {
133
+ // `typeof name` is special because it can reference the variable `name` without
134
+ // throwing any errors. If changed, an error could be thrown, breaking the users code
135
+ return;
136
+ }
98
137
  }
99
138
 
100
139
  return () => {
101
- if (typeof this.ops[operator] !== "number") {
140
+ const opKey = type + "_" + operator;
141
+
142
+ if (typeof this.ops[opKey] !== "number") {
102
143
  var newState;
103
144
 
104
145
  do {
105
- newState = (0, _random.getRandomInteger)(-1000, 1000 + Object.keys(this.ops).length * 5);
146
+ newState = (0, _random.getRandomInteger)(-50, 50 + Object.keys(this.ops).length * 5);
106
147
  } while (this.statesUsed.has(newState));
107
148
 
108
149
  (0, _assert.ok)(!isNaN(newState));
109
150
  this.statesUsed.add(newState);
110
- this.ops[operator] = newState;
111
- this.log(operator, "calc(".concat(newState, ", left, right)"));
151
+ this.ops[opKey] = newState;
152
+
153
+ if (type === "Binary") {
154
+ this.log("left ".concat(operator, " right ->"), "".concat(this.calculatorFn, "((").concat(newState, ", left, right)"));
155
+ } else if (type === "Unary") {
156
+ this.log("".concat(operator, "(argument) ->"), "".concat(this.calculatorFn, "(").concat(newState, ", argument)"));
157
+ }
158
+ } // The operator expression sets the operator to be used
159
+
160
+
161
+ var operatorExpression = (0, _random.choice)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.calculatorOpVar), (0, _gen.Literal)(this.ops[opKey])), (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorSetOpFn), [(0, _gen.Literal)(this.ops[opKey])])]);
162
+ var newExpression;
163
+
164
+ if (type === "Binary") {
165
+ newExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorFn), [object.left, object.right, operatorExpression]);
166
+ } else {
167
+ newExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorFn), [object.argument, operatorExpression]);
112
168
  }
113
169
 
114
- this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorFn), [object.left, object.right, (0, _random.choice)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.calculatorOpVar), (0, _gen.Literal)(this.ops[operator])), (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorSetOpFn), [(0, _gen.Literal)(this.ops[operator])])])]));
170
+ this.replace(object, newExpression);
115
171
  };
116
172
  }
117
173