js-confuser 1.5.8 → 1.5.9

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 (62) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/index.js +45 -4
  3. package/dist/obfuscator.js +10 -5
  4. package/dist/options.js +2 -3
  5. package/dist/order.js +3 -3
  6. package/dist/transforms/antiTooling.js +1 -1
  7. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -2
  8. package/dist/transforms/dispatcher.js +3 -3
  9. package/dist/transforms/es5/antiClass.js +6 -2
  10. package/dist/transforms/es5/antiDestructuring.js +1 -1
  11. package/dist/transforms/eval.js +11 -0
  12. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +4 -4
  13. package/dist/transforms/extraction/objectExtraction.js +6 -1
  14. package/dist/transforms/flatten.js +73 -50
  15. package/dist/transforms/hexadecimalNumbers.js +34 -9
  16. package/dist/transforms/identifier/movedDeclarations.js +1 -1
  17. package/dist/transforms/minify.js +22 -6
  18. package/dist/transforms/rgf.js +4 -4
  19. package/dist/transforms/stack.js +1 -1
  20. package/dist/transforms/string/stringConcealing.js +2 -2
  21. package/dist/traverse.js +0 -8
  22. package/dist/util/compare.js +2 -2
  23. package/dist/util/insert.js +20 -6
  24. package/package.json +1 -1
  25. package/src/index.ts +57 -19
  26. package/src/obfuscator.ts +6 -1
  27. package/src/options.ts +10 -2
  28. package/src/order.ts +3 -3
  29. package/src/transforms/antiTooling.ts +1 -1
  30. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +14 -2
  31. package/src/transforms/dispatcher.ts +4 -3
  32. package/src/transforms/es5/antiClass.ts +10 -1
  33. package/src/transforms/es5/antiDestructuring.ts +1 -1
  34. package/src/transforms/eval.ts +18 -0
  35. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +5 -5
  36. package/src/transforms/extraction/objectExtraction.ts +12 -5
  37. package/src/transforms/flatten.ts +181 -128
  38. package/src/transforms/hexadecimalNumbers.ts +37 -9
  39. package/src/transforms/identifier/movedDeclarations.ts +1 -1
  40. package/src/transforms/minify.ts +37 -5
  41. package/src/transforms/rgf.ts +4 -3
  42. package/src/transforms/stack.ts +3 -1
  43. package/src/transforms/string/stringConcealing.ts +2 -2
  44. package/src/traverse.ts +1 -8
  45. package/src/types.ts +9 -1
  46. package/src/util/compare.ts +2 -2
  47. package/src/util/insert.ts +37 -8
  48. package/test/code/ES6.src.js +14 -0
  49. package/test/code/NewFeatures.test.ts +19 -0
  50. package/test/index.test.ts +13 -1
  51. package/test/transforms/antiTooling.test.ts +30 -0
  52. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +22 -0
  53. package/test/transforms/dispatcher.test.ts +24 -0
  54. package/test/transforms/es5/antiClass.test.ts +33 -0
  55. package/test/transforms/eval.test.ts +53 -0
  56. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  57. package/test/transforms/flatten.test.ts +146 -3
  58. package/test/transforms/identifier/renameVariables.test.ts +26 -0
  59. package/test/transforms/minify.test.ts +66 -0
  60. package/test/transforms/rgf.test.ts +56 -0
  61. package/test/transforms/string/stringConcealing.test.ts +33 -0
  62. package/test/util/compare.test.ts +23 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,40 @@
1
+ # `1.5.9`
2
+ Big update
3
+
4
+ This updates comes with many bug fixes:
5
+
6
+ - Fixed [#72](https://github.com/MichaelXF/js-confuser/issues/72)
7
+ - - ES5 to handle Class Fields
8
+
9
+ Note: The `ES5` option is not meant to replace Babel. It is only intended to undo ES6 features the obfuscator may have added to your code.
10
+
11
+ - Fixed [#74](https://github.com/MichaelXF/js-confuser/issues/74)
12
+ - - Anti Tooling to not break Symbols
13
+
14
+ - Fixed [#75](https://github.com/MichaelXF/js-confuser/issues/75)
15
+ - - Minify to properly handle Object constructors
16
+
17
+ - Fixed [#76](https://github.com/MichaelXF/js-confuser/issues/76)
18
+ - - Minify to not cause syntax errors when objects used `^`, `` ` ``, `[`, `]` as property keys
19
+
20
+ - Fixed [#77](https://github.com/MichaelXF/js-confuser/issues/77)
21
+ - - Dispatcher to not break code that uses generic names like `toString` and `hasOwnProperty`
22
+
23
+ - Fixed [#78](https://github.com/MichaelXF/js-confuser/issues/78)
24
+ - - Object Extraction to not error on objects with spread elements
25
+
26
+ - Fixed [#79](https://github.com/MichaelXF/js-confuser/issues/79)
27
+ - - JsConfuser now supports `BigInt` literals
28
+
29
+ - Fixed [#80](https://github.com/MichaelXF/js-confuser/issues/80)
30
+ - - Rename Variables to not break code that had `var` and `let` variables in the same scope
31
+
32
+ - Fixed [#81](https://github.com/MichaelXF/js-confuser/issues/81)
33
+ - - Control Flow Flattening to not break `typeof` expressions
34
+
35
+ - Fixed [#82](https://github.com/MichaelXF/js-confuser/issues/82)
36
+ - - String Concealing to not break class constructors
37
+
1
38
  # `1.5.8`
2
39
  Several fixes
3
40
 
package/dist/index.js CHANGED
@@ -37,6 +37,8 @@ var _object = require("./util/object");
37
37
 
38
38
  var _presets = _interopRequireDefault(require("./presets"));
39
39
 
40
+ var _perf_hooks = require("perf_hooks");
41
+
40
42
  var assert = _interopRequireWildcard(require("assert"));
41
43
 
42
44
  var _options = require("./options");
@@ -103,7 +105,7 @@ var JsConfuser = async function (code, options) {
103
105
  return result;
104
106
  };
105
107
 
106
- var debugTransformations = async function debugTransformations(code, options) {
108
+ const debugTransformations = async function (code, options) {
107
109
  (0, _options.validateOptions)(options);
108
110
  options = await (0, _options.correctOptions)(options);
109
111
  var frames = [];
@@ -121,21 +123,60 @@ var debugTransformations = async function debugTransformations(code, options) {
121
123
  await obfuscator.apply(tree, true);
122
124
  return frames;
123
125
  };
126
+ /**
127
+ * This method is used by the obfuscator website to display a progress bar and additional information
128
+ * about the obfuscation.
129
+ *
130
+ * @param code - Source code to obfuscate
131
+ * @param options - Options
132
+ * @param callback - Progress callback, called after each transformation
133
+ * @returns
134
+ */
135
+
124
136
 
125
137
  exports.debugTransformations = debugTransformations;
126
138
 
127
- var debugObfuscation = async function debugTransformations(code, options, callback) {
139
+ const debugObfuscation = async function (code, options, callback) {
140
+ const startTime = _perf_hooks.performance.now();
141
+
128
142
  (0, _options.validateOptions)(options);
129
143
  options = await (0, _options.correctOptions)(options);
144
+
145
+ const beforeParseTime = _perf_hooks.performance.now();
146
+
130
147
  var tree = (0, _parser.parseSync)(code);
148
+ const parseTime = _perf_hooks.performance.now() - beforeParseTime;
131
149
  var obfuscator = new _obfuscator.default(options);
132
150
  var totalTransforms = obfuscator.array.length;
151
+ var transformationTimes = Object.create(null);
152
+
153
+ var currentTransformTime = _perf_hooks.performance.now();
154
+
133
155
  obfuscator.on("debug", (name, tree, i) => {
156
+ var nowTime = _perf_hooks.performance.now();
157
+
158
+ transformationTimes[name] = nowTime - currentTransformTime;
159
+ currentTransformTime = nowTime;
134
160
  callback(name, i, totalTransforms);
135
161
  });
136
162
  await obfuscator.apply(tree, true);
137
- var output = (0, _compiler.default)(tree, options);
138
- return output;
163
+
164
+ const beforeCompileTime = _perf_hooks.performance.now();
165
+
166
+ 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
+
171
+ return {
172
+ obfuscated: output,
173
+ transformationTimes: transformationTimes,
174
+ obfuscationTime: endTime - startTime,
175
+ parseTime: parseTime,
176
+ compileTime: compileTime,
177
+ totalTransforms: totalTransforms,
178
+ totalPossibleTransforms: obfuscator.totalPossibleTransforms
179
+ };
139
180
  };
140
181
 
141
182
  exports.debugObfuscation = debugObfuscation;
@@ -94,18 +94,23 @@ class Obfuscator extends _events.EventEmitter {
94
94
 
95
95
  _defineProperty(this, "generated", void 0);
96
96
 
97
+ _defineProperty(this, "totalPossibleTransforms", void 0);
98
+
97
99
  this.varCount = 0;
98
100
  this.transforms = Object.create(null);
99
101
  this.generated = new Set();
102
+ this.totalPossibleTransforms = 0;
100
103
  this.push(new _preparation.default(this));
101
104
  this.push(new _renameLabels.default(this));
102
105
 
103
106
  const test = function (map) {
104
- if ((0, _probability.isProbabilityMapProbable)(map)) {
105
- for (var _len = arguments.length, transformers = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
106
- transformers[_key - 1] = arguments[_key];
107
- }
107
+ for (var _len = arguments.length, transformers = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
108
+ transformers[_key - 1] = arguments[_key];
109
+ }
108
110
 
111
+ _this.totalPossibleTransforms += transformers.length;
112
+
113
+ if ((0, _probability.isProbabilityMapProbable)(map)) {
109
114
  // options.verbose && console.log("+ Added " + transformer.name);
110
115
  transformers.forEach(Transformer => _this.push(new Transformer(_this)));
111
116
  } else {// options.verbose && console.log("- Skipped adding " + transformer.name);
@@ -137,7 +142,7 @@ class Obfuscator extends _events.EventEmitter {
137
142
  test(options.stack, _stack.default);
138
143
  test(true, _antiTooling.default);
139
144
  test(options.hideInitializingCode, _hideInitializingCode.default);
140
- test(options.hexadecimalNumbers, _hexadecimalNumbers.default);
145
+ test(true, _hexadecimalNumbers.default); // BigInt support is included
141
146
 
142
147
  if (options.lock && Object.keys(options.lock).filter(x => x == "domainLock" ? options.lock.domainLock && options.lock.domainLock.length : options.lock[x]).length) {
143
148
  test(true, _lock.default);
package/dist/options.js CHANGED
@@ -109,8 +109,7 @@ async function correctOptions(options) {
109
109
 
110
110
  if (options.lock && options.lock.selfDefending) {
111
111
  options.compact = true; // self defending forcibly enables this
112
- } // options.globalVariables was never used.
113
- // GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified.
112
+ } // options.globalVariables outlines generic globals that should be present in the execution context
114
113
 
115
114
 
116
115
  if (!options.hasOwnProperty("globalVariables")) {
@@ -124,7 +123,7 @@ async function correctOptions(options) {
124
123
  ["global", "Buffer", "require", "process", "__dirname", "__filename"].forEach(x => options.globalVariables.add(x));
125
124
  }
126
125
 
127
- ["globalThis", "console", "parseInt", "parseFloat", "Math", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "exports", "module", "isNaN", "isFinite"].forEach(x => options.globalVariables.add(x));
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));
128
127
  }
129
128
 
130
129
  return options;
package/dist/order.js CHANGED
@@ -33,9 +33,9 @@ exports.ObfuscateOrder = ObfuscateOrder;
33
33
  ObfuscateOrder[ObfuscateOrder["Shuffle"] = 24] = "Shuffle";
34
34
  ObfuscateOrder[ObfuscateOrder["NameRecycling"] = 25] = "NameRecycling";
35
35
  ObfuscateOrder[ObfuscateOrder["MovedDeclarations"] = 26] = "MovedDeclarations";
36
- ObfuscateOrder[ObfuscateOrder["RenameVariables"] = 27] = "RenameVariables";
37
- ObfuscateOrder[ObfuscateOrder["RenameLabels"] = 28] = "RenameLabels";
38
- ObfuscateOrder[ObfuscateOrder["Minify"] = 30] = "Minify";
36
+ ObfuscateOrder[ObfuscateOrder["RenameLabels"] = 27] = "RenameLabels";
37
+ ObfuscateOrder[ObfuscateOrder["Minify"] = 28] = "Minify";
38
+ ObfuscateOrder[ObfuscateOrder["RenameVariables"] = 30] = "RenameVariables";
39
39
  ObfuscateOrder[ObfuscateOrder["ES5"] = 31] = "ES5";
40
40
  ObfuscateOrder[ObfuscateOrder["StringEncoding"] = 32] = "StringEncoding";
41
41
  ObfuscateOrder[ObfuscateOrder["AntiTooling"] = 34] = "AntiTooling";
@@ -50,7 +50,7 @@ class AntiTooling extends _transform.default {
50
50
  if (flattened.length > 1) {
51
51
  flattened[0] = { ...flattened[0]
52
52
  };
53
- this.replace(exprs[0], (0, _gen.ExpressionStatement)((0, _gen.UnaryExpression)((0, _random.choice)(["typeof", "void", "~", "!", "+"]), (0, _gen.SequenceExpression)(flattened))));
53
+ this.replace(exprs[0], (0, _gen.ExpressionStatement)((0, _gen.UnaryExpression)((0, _random.choice)(["typeof", "void", "!"]), (0, _gen.SequenceExpression)(flattened))));
54
54
  deleteExprs.push(...exprs.slice(1));
55
55
  }
56
56
 
@@ -30,7 +30,8 @@ class ExpressionObfuscation extends _transform.default {
30
30
  if (stmt.type == "ExpressionStatement") {
31
31
  var expr = stmt.expression;
32
32
 
33
- if (expr.type == "UnaryExpression" && exprs.length) {
33
+ if (expr.type == "UnaryExpression" && !(expr.operator === "typeof" && expr.argument.type === "Identifier") && exprs.length // typeof is special
34
+ ) {
34
35
  expr.argument = (0, _gen.SequenceExpression)([...exprs, { ...expr.argument
35
36
  }]);
36
37
  deleteExprs.push(...exprs);
@@ -42,7 +43,8 @@ class ExpressionObfuscation extends _transform.default {
42
43
  if (exprs.length) {
43
44
  if (stmt.type == "IfStatement") {
44
45
  if (stmt.test.type == "BinaryExpression" && stmt.test.operator !== "**") {
45
- if (stmt.test.left.type == "UnaryExpression") {
46
+ if (stmt.test.left.type == "UnaryExpression" && !(stmt.test.left.operator === "typeof" && stmt.test.left.argument.type === "Identifier") // typeof is special
47
+ ) {
46
48
  stmt.test.left.argument = (0, _gen.SequenceExpression)([...exprs, { ...stmt.test.left.argument
47
49
  }]);
48
50
  } else {
@@ -80,12 +80,12 @@ class Dispatcher extends _transform.default {
80
80
  } // Map of FunctionDeclarations
81
81
 
82
82
 
83
- var functionDeclarations = {}; // Array of Identifier nodes
83
+ var functionDeclarations = Object.create(null); // Array of Identifier nodes
84
84
 
85
85
  var identifiers = [];
86
86
  var illegalFnNames = new Set(); // New Names for Functions
87
87
 
88
- var newFnNames = {}; // [old name]: randomized name
88
+ var newFnNames = Object.create(null); // [old name]: randomized name
89
89
 
90
90
  var context = (0, _insert.isVarContext)(object) ? object : (0, _insert.getVarContext)(object, parents);
91
91
  (0, _traverse.walk)(object, parents, (o, p) => {
@@ -264,7 +264,7 @@ class Dispatcher extends _transform.default {
264
264
 
265
265
  var newName = newFnNames[o.name];
266
266
 
267
- if (!newName) {
267
+ if (!newName || typeof newName !== "string") {
268
268
  return;
269
269
  }
270
270
 
@@ -85,9 +85,13 @@ class AntiClass extends _transform.default {
85
85
  this.replace(o, (0, _gen.Identifier)(superName));
86
86
  }
87
87
  });
88
- }
88
+ } // Support class fields
89
+
89
90
 
90
- if (methodDefinition.kind == "constructor" || methodDefinition.kind == "method") {
91
+ if (methodDefinition.type === "PropertyDefinition") {
92
+ var assignmentExpression = (0, _gen.AssignmentExpression)("=", key, value || (0, _gen.Identifier)("undefined"));
93
+ pushingTo.push((0, _gen.ExpressionStatement)(assignmentExpression));
94
+ } else if (methodDefinition.kind == "constructor" || methodDefinition.kind == "method") {
91
95
  pushingTo.push((0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", key, value)));
92
96
  } else if (methodDefinition.kind == "get" || methodDefinition.kind == "set") {
93
97
  var id = (0, _gen.Identifier)(methodDefinition.kind == "get" ? "getters" : "setters");
@@ -189,7 +189,7 @@ class AntiDestructuring extends _transform.default {
189
189
  var seq = (0, _gen.SequenceExpression)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(temp), (0, _insert.clone)(extracting) || (0, _gen.Identifier)("undefined")), ...exprs]);
190
190
 
191
191
  if (object.type == "VariableDeclarator") {
192
- var i = (0, _insert.getIndexDirect)(object, parents);
192
+ var i = (0, _insert.getIndexDirect)(object, parents[0]);
193
193
  var extra = Array.from(names).map(x => {
194
194
  return {
195
195
  type: "VariableDeclarator",
@@ -31,6 +31,17 @@ class Eval extends _transform.default {
31
31
  }
32
32
 
33
33
  transform(object, parents) {
34
+ // Don't apply to getter/setters or class methods
35
+ if (parents[0]) {
36
+ if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
37
+ return;
38
+ }
39
+
40
+ if (parents[0].type === "Property" && parents[0].value === object && (parents[0].kind !== "init" || parents[0].method)) {
41
+ return;
42
+ }
43
+ }
44
+
34
45
  if (!(0, _probability.ComputeProbabilityMap)(this.options.eval, x => x, object.id && object.id.name)) {
35
46
  return;
36
47
  }
@@ -113,7 +113,7 @@ class DuplicateLiteralsRemoval extends _transform.default {
113
113
  var body = [];
114
114
  var thisShift = (0, _random.getRandomInteger)(-250, 250); // the name of the getter
115
115
 
116
- getterName = this.getPlaceholder();
116
+ getterName = this.getPlaceholder() + "_dLR_" + this.fnGetters.size;
117
117
 
118
118
  if (basedOn) {
119
119
  var shift = this.fnShifts.get(basedOn);
@@ -179,17 +179,17 @@ class DuplicateLiteralsRemoval extends _transform.default {
179
179
  this.arrayExpression = (0, _gen.ArrayExpression)([]);
180
180
  }
181
181
 
182
- var first = this.first.get(value);
182
+ var firstLocation = this.first.get(value);
183
183
 
184
- if (first) {
184
+ if (firstLocation) {
185
185
  this.first.set(value, null);
186
186
  var index = this.map.size;
187
187
  (0, _assert.ok)(!this.map.has(value));
188
188
  this.map.set(value, index);
189
- this.toCaller(first[0], first[1], index);
190
189
  var pushing = (0, _insert.clone)(object);
191
190
  this.arrayExpression.elements.push(pushing);
192
191
  (0, _assert.ok)(this.arrayExpression.elements[index] === pushing);
192
+ this.toCaller(firstLocation[0], firstLocation[1], index);
193
193
  }
194
194
 
195
195
  var index = this.map.get(value);
@@ -97,7 +97,12 @@ class ObjectExtraction extends _transform.default {
97
97
  var nonInitOrComputed = object.properties.find(x => x.kind !== "init" || x.computed);
98
98
 
99
99
  if (nonInitOrComputed) {
100
- this.log(name + " has non-init/computed property: " + nonInitOrComputed.key.name || nonInitOrComputed.key.value);
100
+ if (nonInitOrComputed.key) {
101
+ this.log(name + " has non-init/computed property: " + nonInitOrComputed.key.name || nonInitOrComputed.key.value);
102
+ } else {
103
+ this.log(name + " has spread-element or other type of property");
104
+ }
105
+
101
106
  illegal.add(name);
102
107
  return;
103
108
  } else {
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
+ var _assert = require("assert");
9
+
8
10
  var _constants = require("../constants");
9
11
 
10
12
  var _order = require("../order");
@@ -39,6 +41,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
39
41
  * return [ref1, ref2, refN, returnValue];
40
42
  * }
41
43
  * ```
44
+ *
45
+ * Flatten is used to make functions eligible for the RGF transformation.
42
46
  */
43
47
  class Flatten extends _transform.default {
44
48
  constructor(o) {
@@ -46,15 +50,12 @@ class Flatten extends _transform.default {
46
50
 
47
51
  _defineProperty(this, "definedNames", void 0);
48
52
 
49
- _defineProperty(this, "flatMapName", void 0);
50
-
51
- _defineProperty(this, "flatNode", void 0);
53
+ _defineProperty(this, "flattenedFns", void 0);
52
54
 
53
55
  _defineProperty(this, "gen", void 0);
54
56
 
55
57
  this.definedNames = new Map();
56
- this.flatMapName = null;
57
- this.flatNode = null;
58
+ this.flattenedFns = [];
58
59
  this.gen = this.getGenerator();
59
60
  }
60
61
 
@@ -79,19 +80,43 @@ class Flatten extends _transform.default {
79
80
  }
80
81
  });
81
82
  super.apply(tree);
83
+
84
+ if (this.flattenedFns.length) {
85
+ (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)(this.flattenedFns));
86
+ }
82
87
  }
83
88
 
84
89
  match(object, parents) {
85
- return object.type == "FunctionDeclaration" && object.body.type == "BlockStatement" && !object.generator && !object.async && !object.params.find(x => x.type !== "Identifier");
90
+ return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.generator && !object.params.find(x => x.type !== "Identifier");
86
91
  }
87
92
 
88
93
  transform(object, parents) {
89
94
  return () => {
90
- //
91
- if (parents.find(x => x.type == "ClassExpression" || x.type == "ClassDeclaration" || x.type == "MethodDefinition")) {
92
- return;
95
+ var _object$id, _parents$, _parents$0$id, _parents$0$id2, _parents$2, _parents$3;
96
+
97
+ if (parents[0]) {
98
+ // Don't change class methods
99
+ if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
100
+ return;
101
+ } // Don't change getter/setter methods
102
+
103
+
104
+ if (parents[0].type === "Property" && parents[0].value === object && parents[0].kind !== "init") {
105
+ return;
106
+ }
93
107
  }
94
108
 
109
+ (0, _assert.ok)(object.type === "FunctionDeclaration" || object.type === "FunctionExpression"); // The name is purely for debugging purposes
110
+
111
+ var currentFnName = object.type === "FunctionDeclaration" ? (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name : ((_parents$ = parents[0]) === null || _parents$ === void 0 ? void 0 : _parents$.type) === "VariableDeclarator" && ((_parents$0$id = parents[0].id) === null || _parents$0$id === void 0 ? void 0 : _parents$0$id.type) === "Identifier" && ((_parents$0$id2 = parents[0].id) === null || _parents$0$id2 === void 0 ? void 0 : _parents$0$id2.name);
112
+
113
+ if (((_parents$2 = parents[0]) === null || _parents$2 === void 0 ? void 0 : _parents$2.type) === "Property" && (_parents$3 = parents[0]) !== null && _parents$3 !== void 0 && _parents$3.key) {
114
+ var _parents$4, _parents$4$key, _parents$5, _parents$5$key;
115
+
116
+ currentFnName = currentFnName || String(((_parents$4 = parents[0]) === null || _parents$4 === void 0 ? void 0 : (_parents$4$key = _parents$4.key) === null || _parents$4$key === void 0 ? void 0 : _parents$4$key.name) || ((_parents$5 = parents[0]) === null || _parents$5 === void 0 ? void 0 : (_parents$5$key = _parents$5.key) === null || _parents$5$key === void 0 ? void 0 : _parents$5$key.value));
117
+ }
118
+
119
+ if (!currentFnName) currentFnName = "unnamed";
95
120
  var defined = new Set();
96
121
  var references = new Set();
97
122
  var modified = new Set();
@@ -119,9 +144,7 @@ class Flatten extends _transform.default {
119
144
 
120
145
  if (o.hidden) {
121
146
  illegal.add(o.name);
122
- }
123
-
124
- if (info.spec.isDefined) {
147
+ } else if (info.spec.isDefined) {
125
148
  defined.add(o.name);
126
149
  } else if (info.spec.isModified) {
127
150
  modified.add(o.name);
@@ -171,9 +194,6 @@ class Flatten extends _transform.default {
171
194
  return;
172
195
  }
173
196
 
174
- illegal.forEach(name => {
175
- defined.delete(name);
176
- });
177
197
  defined.forEach(name => {
178
198
  references.delete(name);
179
199
  modified.delete(name);
@@ -186,65 +206,68 @@ class Flatten extends _transform.default {
186
206
  }
187
207
 
188
208
  var output = Array.from(modified);
189
- var newName = this.gen.generate();
190
- var valName = this.getPlaceholder();
209
+ var newName = this.getPlaceholder() + "_flat_" + currentFnName;
191
210
  var resultName = this.getPlaceholder();
192
211
  var propName = this.gen.generate();
212
+ var newOutputNames = Object.create(null);
213
+ output.forEach(name => {
214
+ newOutputNames[name] = this.gen.generate();
215
+ });
216
+ var returnOutputName = this.gen.generate();
193
217
  (0, _insert.getBlockBody)(object.body).push((0, _gen.ReturnStatement)());
194
218
  (0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
195
219
  return () => {
220
+ // Change return statements from
221
+ // return (argument)
222
+ // to
223
+ // return [ [modifiedRefs], ]
196
224
  if (o.type == "ReturnStatement" && (0, _insert.getVarContext)(o, p) === object) {
197
- var elements = output.map(_gen.Identifier);
225
+ var returnObject = (0, _gen.ObjectExpression)(output.map(outputName => (0, _gen.Property)((0, _gen.Literal)(newOutputNames[outputName]), (0, _gen.Identifier)(outputName), true)));
198
226
 
199
227
  if (o.argument && !(o.argument.type == "Identifier" && o.argument.name == "undefined")) {
200
- elements.unshift((0, _insert.clone)(o.argument));
228
+ returnObject.properties.push((0, _gen.Property)((0, _gen.Literal)(returnOutputName), (0, _insert.clone)(o.argument), true));
201
229
  }
202
230
 
203
- o.argument = (0, _gen.ArrayExpression)(elements);
204
- o.argument = (0, _gen.AssignmentExpression)("=", (0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), o.argument);
231
+ o.argument = (0, _gen.AssignmentExpression)("=", (0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), returnObject);
205
232
  }
206
233
  };
207
234
  });
208
235
  var newBody = (0, _insert.getBlockBody)(object.body);
209
- newBody.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.ArrayPattern)([(0, _gen.ArrayPattern)(input.map(_gen.Identifier)), (0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(resultName)]), (0, _gen.Identifier)(valName))));
210
-
211
- if (!this.flatMapName) {
212
- this.flatMapName = this.getPlaceholder();
213
- (0, _insert.prepend)(parents[parents.length - 1], (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.flatMapName, this.flatNode = (0, _gen.ObjectExpression)([]))));
214
- }
215
-
216
- var newFunctionExpression = (0, _gen.FunctionExpression)([(0, _gen.Identifier)(valName)], newBody);
236
+ var newFunctionExpression = (0, _gen.FunctionExpression)([(0, _gen.ArrayPattern)(input.map(_gen.Identifier)), (0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(resultName)], newBody);
217
237
  newFunctionExpression.async = !!object.async;
218
238
  newFunctionExpression.generator = !!object.generator;
219
239
  var property = (0, _gen.Property)((0, _gen.Identifier)(newName), newFunctionExpression, false);
220
240
  property.kind = "set";
221
- this.flatNode.properties.push(property);
222
- var identifier = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.flatMapName), (0, _gen.Identifier)(newName), false);
223
- var newParamNodes = object.params.map(() => (0, _gen.Identifier)(this.getPlaceholder())); // var result = newFn.call([...refs], ...arguments)
241
+ this.flattenedFns.push((0, _gen.VariableDeclarator)(newName, newFunctionExpression));
242
+ var newParamNodes = object.params.map(() => (0, _gen.Identifier)(this.getPlaceholder())); // result.pop()
224
243
 
225
- var call = (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(resultName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)("_", (0, _gen.AssignmentExpression)("=", identifier, (0, _gen.ArrayExpression)([(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), (0, _gen.ArrayExpression)([...newParamNodes]), (0, _gen.Identifier)(resultName)])))]); // result.pop()
244
+ var getOutputMemberExpression = outputName => (0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(propName), true), (0, _gen.Literal)(outputName), true); // newFn.call([...refs], ...arguments, resultObject)
226
245
 
227
- var pop = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), (0, _gen.Literal)("pop"), true), []); // var result = newFn.call([...refs], ...arguments)
228
- // modified1 = result.pop();
229
- // modified2 = result.pop();
230
- // ...modifiedN = result.pop();...
231
- //
232
- // return result.pop()
233
246
 
234
- var newObjectBody = [call];
235
- var outputReversed = [...output].reverse(); // DECOY STATEMENTS
247
+ var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(newName), [(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), (0, _gen.ArrayExpression)([...newParamNodes]), (0, _gen.Identifier)(resultName)]);
248
+ var newObjectBody = [// var resultObject = {};
249
+ (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(resultName, (0, _gen.ObjectExpression)([]))]), (0, _gen.ExpressionStatement)(newFunctionExpression.async ? (0, _gen.AwaitExpression)(callExpression) : callExpression)];
250
+ var outputReversed = [...output].reverse(); // realVar
251
+
252
+ outputReversed.forEach(outputName => {
253
+ newObjectBody.push((0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(outputName), getOutputMemberExpression(newOutputNames[outputName]))));
254
+ }); // DECOY STATEMENTS
236
255
 
237
256
  var decoyKey = this.gen.generate();
238
- var decoyNodes = [(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ThrowStatement)((0, _gen.NewExpression)((0, _gen.Identifier)("Error"), [(0, _gen.Literal)(this.getPlaceholder())]))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(decoyKey), false), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(decoyKey), false))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false))])];
257
+ var decoyNodes = [// if (result.random) throw result.prop.random
258
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ThrowStatement)((0, _gen.NewExpression)((0, _gen.Identifier)("Error"), [getOutputMemberExpression(this.gen.generate())]))]), // if (result.random) return true;
259
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Literal)(true))]), // if (result.random) return result;
260
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), // if (result.random) return result.random;
261
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(decoyKey), true), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(decoyKey), true))]), // if(result.random1) return result.random2;
262
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true))]), // if(result.random) return flatFn;
263
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(newName))]), // if(result.random) flatFn = undefined;
264
+ (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(newName), (0, _gen.Identifier)("undefined")))]), // if(!result) return;
265
+ (0, _gen.IfStatement)((0, _gen.UnaryExpression)("!", (0, _gen.Identifier)(resultName)), [(0, _gen.ReturnStatement)()])].filter(() => Math.random() > 0.25); // if (result.output) return result.output.returnValue;
266
+ // this is the real return statement, it is always added
267
+
268
+ decoyNodes.push((0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(propName), true), [(0, _gen.ReturnStatement)(getOutputMemberExpression(returnOutputName))]));
239
269
  (0, _random.shuffle)(decoyNodes);
240
- decoyNodes.forEach(decoyNode => {
241
- if (Math.random() < 0.5) {
242
- newObjectBody.push(decoyNode);
243
- }
244
- });
245
- newObjectBody.push(...outputReversed.map(name => {
246
- return (0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(name), (0, _insert.clone)(pop)));
247
- }), (0, _gen.ReturnStatement)((0, _insert.clone)(pop)));
270
+ newObjectBody.push(...decoyNodes);
248
271
  object.body = (0, _gen.BlockStatement)(newObjectBody);
249
272
  object.params = newParamNodes;
250
273
  };
@@ -13,24 +13,49 @@ var _gen = require("../util/gen");
13
13
 
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
 
16
+ /**
17
+ * The HexadecimalNumbers transformation converts number literals into the hexadecimal form.
18
+ *
19
+ * This is done by replacing the number literal with an Identifier to ensure escodegen properly outputs it as such
20
+ *
21
+ * This transformation also handles BigInt support, so its always enabled for this reason.
22
+ */
16
23
  class HexadecimalNumbers extends _transform.default {
17
24
  constructor(o) {
18
25
  super(o, _order.ObfuscateOrder.HexadecimalNumbers);
19
26
  }
20
27
 
21
- match(object, parents) {
28
+ isNumberLiteral(object) {
22
29
  return object.type === "Literal" && typeof object.value === "number" && Math.floor(object.value) === object.value;
23
30
  }
24
31
 
32
+ isBigIntLiteral(object) {
33
+ return object.type === "Literal" && typeof object.value === "bigint";
34
+ }
35
+
36
+ match(object, parents) {
37
+ return this.options.hexadecimalNumbers && this.isNumberLiteral(object) || this.isBigIntLiteral(object);
38
+ }
39
+
25
40
  transform(object, parents) {
26
- return () => {
27
- // Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
28
- // This code handles it regardless
29
- var isNegative = object.value < 0;
30
- var hex = Math.abs(object.value).toString(16);
31
- var newStr = (isNegative ? "-" : "") + "0x" + hex;
32
- this.replace(object, (0, _gen.Identifier)(newStr));
33
- };
41
+ if (this.isNumberLiteral(object)) {
42
+ return () => {
43
+ // Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
44
+ // This code handles it regardless
45
+ var isNegative = object.value < 0;
46
+ var hex = Math.abs(object.value).toString(16);
47
+ var newStr = (isNegative ? "-" : "") + "0x" + hex;
48
+ this.replace(object, (0, _gen.Identifier)(newStr));
49
+ };
50
+ } // https://github.com/MichaelXF/js-confuser/issues/79
51
+
52
+
53
+ if (this.isBigIntLiteral(object)) {
54
+ return () => {
55
+ // Use an Identifier with the raw string
56
+ this.replace(object, (0, _gen.Identifier)(object.raw));
57
+ };
58
+ }
34
59
  }
35
60
 
36
61
  }
@@ -44,7 +44,7 @@ class MovedDeclarations extends _transform.default {
44
44
  var variableDeclarations = Object.create(null);
45
45
  (0, _traverse.walk)(object, parents, (o, p) => {
46
46
  if (o.type == "Identifier") {
47
- if ((0, _scope.getLexicalScope)(o, p) !== object) {
47
+ if (o.hidden || (0, _scope.getLexicalScope)(o, p) !== object) {
48
48
  illegal.add(o.name);
49
49
  } else {
50
50
  var info = (0, _identifiers.getIdentifierInfo)(o, p);