js-confuser 1.5.7 → 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 (73) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/index.js +45 -4
  3. package/dist/obfuscator.js +10 -5
  4. package/dist/options.js +6 -7
  5. package/dist/order.js +3 -3
  6. package/dist/transforms/antiTooling.js +1 -1
  7. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +16 -2
  8. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -2
  9. package/dist/transforms/dispatcher.js +3 -3
  10. package/dist/transforms/es5/antiClass.js +6 -2
  11. package/dist/transforms/es5/antiDestructuring.js +1 -1
  12. package/dist/transforms/eval.js +11 -0
  13. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +4 -4
  14. package/dist/transforms/extraction/objectExtraction.js +6 -1
  15. package/dist/transforms/flatten.js +73 -50
  16. package/dist/transforms/hexadecimalNumbers.js +34 -9
  17. package/dist/transforms/identifier/movedDeclarations.js +1 -1
  18. package/dist/transforms/identifier/nameRecycling.js +8 -2
  19. package/dist/transforms/identifier/renameVariables.js +9 -0
  20. package/dist/transforms/lock/antiDebug.js +1 -1
  21. package/dist/transforms/minify.js +22 -6
  22. package/dist/transforms/rgf.js +4 -4
  23. package/dist/transforms/stack.js +1 -1
  24. package/dist/transforms/string/stringConcealing.js +77 -40
  25. package/dist/transforms/transform.js +1 -1
  26. package/dist/traverse.js +0 -8
  27. package/dist/util/compare.js +2 -2
  28. package/dist/util/insert.js +20 -6
  29. package/package.json +2 -2
  30. package/src/index.ts +57 -19
  31. package/src/obfuscator.ts +6 -1
  32. package/src/options.ts +20 -6
  33. package/src/order.ts +3 -3
  34. package/src/transforms/antiTooling.ts +1 -1
  35. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +16 -1
  36. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +14 -2
  37. package/src/transforms/dispatcher.ts +4 -3
  38. package/src/transforms/es5/antiClass.ts +10 -1
  39. package/src/transforms/es5/antiDestructuring.ts +1 -1
  40. package/src/transforms/eval.ts +18 -0
  41. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +5 -5
  42. package/src/transforms/extraction/objectExtraction.ts +12 -5
  43. package/src/transforms/flatten.ts +181 -128
  44. package/src/transforms/hexadecimalNumbers.ts +37 -9
  45. package/src/transforms/identifier/movedDeclarations.ts +1 -1
  46. package/src/transforms/identifier/nameRecycling.ts +14 -3
  47. package/src/transforms/identifier/renameVariables.ts +19 -0
  48. package/src/transforms/lock/antiDebug.ts +1 -1
  49. package/src/transforms/minify.ts +37 -5
  50. package/src/transforms/rgf.ts +4 -3
  51. package/src/transforms/stack.ts +3 -1
  52. package/src/transforms/string/stringConcealing.ts +120 -56
  53. package/src/transforms/transform.ts +1 -1
  54. package/src/traverse.ts +1 -8
  55. package/src/types.ts +9 -1
  56. package/src/util/compare.ts +2 -2
  57. package/src/util/insert.ts +37 -8
  58. package/test/code/ES6.src.js +14 -0
  59. package/test/code/NewFeatures.test.ts +19 -0
  60. package/test/index.test.ts +13 -1
  61. package/test/transforms/antiTooling.test.ts +30 -0
  62. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +58 -0
  63. package/test/transforms/dispatcher.test.ts +24 -0
  64. package/test/transforms/es5/antiClass.test.ts +33 -0
  65. package/test/transforms/eval.test.ts +53 -0
  66. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  67. package/test/transforms/flatten.test.ts +146 -3
  68. package/test/transforms/identifier/nameRecycling.test.ts +39 -0
  69. package/test/transforms/identifier/renameVariables.test.ts +64 -0
  70. package/test/transforms/minify.test.ts +66 -0
  71. package/test/transforms/rgf.test.ts +56 -0
  72. package/test/transforms/string/stringConcealing.test.ts +33 -0
  73. package/test/util/compare.test.ts +23 -1
@@ -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);
@@ -87,7 +87,6 @@ class NameRecycling extends _transform.default {
87
87
  return;
88
88
  }
89
89
 
90
- lastReferenceMap.set(o.name, i);
91
90
  var comparingContext = info.spec.isDefined ? (0, _insert.getDefiningContext)(o, p) : (0, _insert.getReferencingContexts)(o, p).find(x => (0, _insert.isVarContext)(x));
92
91
 
93
92
  if (comparingContext !== context) {
@@ -101,7 +100,12 @@ class NameRecycling extends _transform.default {
101
100
  }
102
101
 
103
102
  if (info.spec.isDefined) {
104
- if (defined.has(o.name) || (0, _traverse.getBlock)(o, p) !== object) {
103
+ // Function Declarations can be used before they're defined, if so, don't change this
104
+ if (info.isFunctionDeclaration && lastReferenceMap.has(o.name)) {
105
+ illegal.add(o.name);
106
+ }
107
+
108
+ if (defined.has(o.name) || (0, _traverse.getBlock)(o, p) !== object || info.isImportSpecifier) {
105
109
  illegal.add(o.name);
106
110
  }
107
111
 
@@ -111,6 +115,8 @@ class NameRecycling extends _transform.default {
111
115
  referencedHere.add(o.name);
112
116
  }
113
117
  }
118
+
119
+ lastReferenceMap.set(o.name, i);
114
120
  };
115
121
  }
116
122
  }); // console.log(i, definedHere);
@@ -165,6 +165,15 @@ class RenameVariables extends _transform.default {
165
165
  if (newName && typeof newName === "string") {
166
166
  if (o.$renamed) {
167
167
  return;
168
+ } // Strange behavior where the `local` and `imported` objects are the same
169
+
170
+
171
+ if (info.isImportSpecifier) {
172
+ var importSpecifierIndex = p.findIndex(x => x.type === "ImportSpecifier");
173
+
174
+ if (importSpecifierIndex != -1 && p[importSpecifierIndex].imported === (p[importSpecifierIndex - 1] || o) && p[importSpecifierIndex].imported && p[importSpecifierIndex].imported.type === "Identifier") {
175
+ p[importSpecifierIndex].imported = (0, _insert.clone)(p[importSpecifierIndex - 1] || o);
176
+ }
168
177
  } // console.log(o.name, "->", newName);
169
178
 
170
179
 
@@ -43,7 +43,7 @@ class AntiDebug extends _transform.default {
43
43
  var startTimeName = this.getPlaceholder();
44
44
  var endTimeName = this.getPlaceholder();
45
45
  var isDevName = this.getPlaceholder();
46
- var functionDeclaration = (0, _gen.FunctionDeclaration)(fnName, [], [...(0, _template.default)("\n var ".concat(startTimeName, " = new Date();\n debugger;\n var ").concat(endTimeName, " = new Date();\n var ").concat(isDevName, " = ").concat(endTimeName, "-").concat(startTimeName, " > 1000;\n ")).compile(), (0, _gen.IfStatement)((0, _gen.Identifier)(isDevName), this.options.lock.countermeasures ? this.lock.getCounterMeasuresCode() : [(0, _gen.WhileStatement)((0, _gen.Identifier)(isDevName), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(startTimeName), (0, _gen.Identifier)(endTimeName)))])], null)]);
46
+ var functionDeclaration = (0, _gen.FunctionDeclaration)(fnName, [], [...(0, _template.default)("\n var ".concat(startTimeName, " = new Date();\n debugger;\n var ").concat(endTimeName, " = new Date();\n var ").concat(isDevName, " = ").concat(endTimeName, "-").concat(startTimeName, " > 1000;\n ")).compile(), (0, _gen.IfStatement)((0, _gen.Identifier)(isDevName), this.options.lock.countermeasures ? this.lock.getCounterMeasuresCode(tree.body, [tree]) : [(0, _gen.WhileStatement)((0, _gen.Identifier)(isDevName), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(startTimeName), (0, _gen.Identifier)(endTimeName)))])], null)]);
47
47
  tree.body.unshift(...DevToolsDetection.compile({
48
48
  functionName: fnName
49
49
  }));
@@ -21,6 +21,8 @@ var _assert = require("assert");
21
21
 
22
22
  var _scope = require("../util/scope");
23
23
 
24
+ var _template = _interopRequireDefault(require("../templates/template"));
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; }
@@ -34,12 +36,13 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
34
36
  * - `x['y']` **->** `x.y`
35
37
  */
36
38
  class Minify extends _transform.default {
39
+ /**
40
+ * A helper function that is introduced preserve function semantics
41
+ */
37
42
  constructor(o) {
38
43
  super(o, _order.ObfuscateOrder.Minify);
39
44
 
40
- _defineProperty(this, "variables", void 0);
41
-
42
- this.variables = new Map();
45
+ _defineProperty(this, "arrowFunctionName", void 0);
43
46
  }
44
47
 
45
48
  match(object, parents) {
@@ -212,15 +215,28 @@ class Minify extends _transform.default {
212
215
  });
213
216
 
214
217
  if (canTransform) {
218
+ if (!this.arrowFunctionName) {
219
+ this.arrowFunctionName = this.getPlaceholder();
220
+ (0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn){\n return function(){ return arrowFn(...arguments) }\n }\n ")).single());
221
+ }
222
+
223
+ const wrap = object => {
224
+ return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object)]);
225
+ };
226
+
215
227
  if (object.type == "FunctionExpression") {
216
228
  object.type = "ArrowFunctionExpression";
229
+ this.replace(object, wrap((0, _insert.clone)(object)));
217
230
  } else {
218
231
  var arrow = { ...(0, _insert.clone)(object),
219
232
  type: "ArrowFunctionExpression"
220
233
  };
221
- this.replace(object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(object.id.name, arrow)));
234
+ this.replace(object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(object.id.name, wrap(arrow))));
222
235
  var x = this.transform(arrow, []);
223
- x();
236
+
237
+ if (typeof x === "function") {
238
+ x();
239
+ }
224
240
  }
225
241
  }
226
242
  };
@@ -372,7 +388,7 @@ class Minify extends _transform.default {
372
388
  object.alternate = null;
373
389
  }
374
390
 
375
- if (object.consequent.body.length == 1 && object.alternate && object.alternate.body.length == 1) {
391
+ if (object.consequent && object.consequent.body && object.consequent.body.length == 1 && object.alternate && object.alternate.body.length == 1) {
376
392
  var stmt1 = (0, _insert.clone)(object.consequent.body[0]);
377
393
  var stmt2 = (0, _insert.clone)(object.alternate.body[0]); // if (a) {return b;} else {return c;} -> return a ? b : c;
378
394
 
@@ -241,7 +241,8 @@ class RGF extends _transform.default {
241
241
  // fn
242
242
  // In most cases the identifier is being used like this (call expression, or referenced to be called later)
243
243
  // Replace it with a simple wrapper function that will pass on the reference array
244
- var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)(memberExpression, [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
244
+ var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)( // clone() is required!
245
+ (0, _gen.CallExpression)((0, _insert.clone)(memberExpression), [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
245
246
  this.replace(o, conditionalExpression);
246
247
  }
247
248
  }
@@ -258,8 +259,6 @@ class RGF extends _transform.default {
258
259
 
259
260
  let [object, parents] = _ref2;
260
261
  var name = object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name;
261
- var hasName = !!name;
262
- var params = object.params.map(x => x.name) || [];
263
262
  var signature = referenceSignatures[names.get(name)];
264
263
  var embeddedName = name || this.getPlaceholder(); // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
265
264
  // RGF runs early and needs completed code before converting to a string.
@@ -272,7 +271,8 @@ class RGF extends _transform.default {
272
271
  integrity: false
273
272
  },
274
273
  eval: false,
275
- hideInitializingCode: false
274
+ hideInitializingCode: false,
275
+ stringEncoding: false
276
276
  });
277
277
  var transforms = Object.values(obfuscator.transforms).filter(x => x.priority > this.priority);
278
278
  var embeddedFunction = { ...object,
@@ -44,7 +44,7 @@ class Stack extends _transform.default {
44
44
  return () => {
45
45
  // Uncaught SyntaxError: Getter must not have any formal parameters.
46
46
  // Uncaught SyntaxError: Setter must have exactly one formal parameter
47
- var propIndex = parents.findIndex(x => x.type == "Property");
47
+ var propIndex = parents.findIndex(x => x.type === "Property" || x.type === "MethodDefinition");
48
48
 
49
49
  if (propIndex !== -1) {
50
50
  if (parents[propIndex].value === (parents[propIndex - 1] || object)) {
@@ -70,17 +70,20 @@ class StringConcealing extends _transform.default {
70
70
 
71
71
  _defineProperty(this, "encoding", Object.create(null));
72
72
 
73
+ _defineProperty(this, "gen", void 0);
74
+
73
75
  _defineProperty(this, "hasAllEncodings", void 0);
74
76
 
75
77
  this.set = new Set();
76
78
  this.index = Object.create(null);
77
79
  this.arrayExpression = (0, _gen.ArrayExpression)([]);
78
- this.hasAllEncodings = false; // Pad array with useless strings
80
+ this.hasAllEncodings = false;
81
+ this.gen = this.getGenerator(); // Pad array with useless strings
79
82
 
80
- var dead = (0, _random.getRandomInteger)(4, 10);
83
+ var dead = (0, _random.getRandomInteger)(5, 15);
81
84
 
82
85
  for (var i = 0; i < dead; i++) {
83
- var str = (0, _random.getRandomString)((0, _random.getRandomInteger)(4, 20));
86
+ var str = (0, _random.getRandomString)((0, _random.getRandomInteger)(5, 40));
84
87
  var fn = this.transform((0, _gen.Literal)(str), []);
85
88
 
86
89
  if (fn) {
@@ -104,7 +107,7 @@ class StringConcealing extends _transform.default {
104
107
  (0, _insert.append)(tree, (0, _template.default)("\n \n function ".concat(getterFn, "(x, y, z, a = ").concat(decodeFn, ", b = ").concat(cacheName, "){\n if ( z ) {\n return y[").concat(cacheName, "[z]] = ").concat(getterFn, "(x, y);\n } else if ( y ) {\n [b, y] = [a(b), x || z]\n }\n \n return y ? x[b[y]] : ").concat(cacheName, "[x] || (z=(b[x], a), ").concat(cacheName, "[x] = z(").concat(this.arrayName, "[x]))\n }\n \n ")).single());
105
108
  });
106
109
  var flowIntegrity = this.getPlaceholder();
107
- (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(cacheName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)(flowIntegrity, (0, _gen.Literal)(0)), (0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("a", this.arrayExpression)), (0, _template.default)("return (".concat(flowIntegrity, " ? a.pop() : ").concat(flowIntegrity, "++, a)")).single()]), []))]));
110
+ (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(cacheName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)(flowIntegrity, (0, _gen.Literal)(0)), (0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("a", this.arrayExpression)), (0, _template.default)("return (".concat(flowIntegrity, " ? a[\"pop\"]() : ").concat(flowIntegrity, "++, a)")).single()]), []))]));
108
111
  }
109
112
 
110
113
  match(object, parents) {
@@ -117,7 +120,7 @@ class StringConcealing extends _transform.default {
117
120
  transform(object, parents) {
118
121
  return () => {
119
122
  // Empty strings are discarded
120
- if (!object.value || this.ignore.has(object.value)) {
123
+ if (!object.value || this.ignore.has(object.value) || object.value.length == 0) {
121
124
  return;
122
125
  }
123
126
 
@@ -143,53 +146,87 @@ class StringConcealing extends _transform.default {
143
146
 
144
147
  if (encoder.decode(encoded) != object.value) {
145
148
  this.ignore.add(object.value);
146
- this.warn(object.value.slice(0, 100));
149
+ this.warn(type, object.value.slice(0, 100));
147
150
  return;
148
- } // Fix 1. weird undefined error
151
+ }
152
+
153
+ var index = -1;
149
154
 
155
+ if (!this.set.has(object.value)) {
156
+ this.arrayExpression.elements.push((0, _gen.Literal)(encoded));
157
+ index = this.arrayExpression.elements.length - 1;
158
+ this.index[object.value] = [index, fnName];
159
+ this.set.add(object.value);
160
+ } else {
161
+ [index, fnName] = this.index[object.value];
162
+ (0, _assert.ok)(typeof index === "number");
163
+ }
150
164
 
151
- if (object.value && object.value.length > 0) {
152
- var index = -1;
165
+ (0, _assert.ok)(index != -1, "index == -1");
166
+ var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
153
167
 
154
- if (!this.set.has(object.value)) {
155
- this.arrayExpression.elements.push((0, _gen.Literal)(encoded));
156
- index = this.arrayExpression.elements.length - 1;
157
- this.index[object.value] = [index, fnName];
158
- this.set.add(object.value);
159
- } else {
160
- [index, fnName] = this.index[object.value];
161
- (0, _assert.ok)(typeof index === "number");
162
- }
168
+ if (Math.random() > 0.5) {
169
+ callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("apply"), false), [(0, _gen.Identifier)("undefined"), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
170
+ } // use `.call`
171
+ else if (Math.random() > 0.5) {
172
+ callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.Identifier)("undefined"), (0, _gen.Literal)(index)]);
173
+ }
163
174
 
164
- (0, _assert.ok)(index != -1, "index == -1");
165
- var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
175
+ var referenceType = "call";
166
176
 
167
- if (Math.random() > 0.5) {
168
- callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("apply"), false), [(0, _gen.ThisExpression)(), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
169
- } // use `.call`
170
- else if (Math.random() > 0.5) {
171
- callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.ThisExpression)(), (0, _gen.Literal)(index)]);
172
- }
177
+ if (parents.length && Math.random() < 0.5 / this.variablesMade) {
178
+ referenceType = "constantReference";
179
+ }
173
180
 
174
- var constantReference = parents.length && Math.random() > 0.5 / this.variablesMade;
181
+ var newExpr = callExpr;
175
182
 
176
- if (constantReference) {
177
- // Define the string earlier, reference the name here
178
- var name = this.getPlaceholder();
179
- var place = (0, _random.choice)(parents.filter(node => (0, _traverse.isBlock)(node)));
183
+ if (referenceType === "constantReference") {
184
+ // Define the string earlier, reference the name here
185
+ this.variablesMade++;
186
+ var constantReferenceType = (0, _random.choice)(["variable", "array", "object"]);
187
+ var place = (0, _random.choice)(parents.filter(node => (0, _traverse.isBlock)(node)));
180
188
 
181
- if (!place) {
182
- this.error(Error("No lexical block to insert code"));
183
- }
189
+ if (!place) {
190
+ this.error(new Error("No lexical block to insert code"));
191
+ }
184
192
 
185
- place.body.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(name, callExpr)));
186
- this.replaceIdentifierOrLiteral(object, (0, _gen.Identifier)(name), parents);
187
- this.variablesMade++;
188
- } else {
189
- // Direct call to the getter function
190
- this.replaceIdentifierOrLiteral(object, callExpr, parents);
193
+ switch (constantReferenceType) {
194
+ case "variable":
195
+ var name = this.getPlaceholder();
196
+ (0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(name, callExpr)));
197
+ newExpr = (0, _gen.Identifier)(name);
198
+ break;
199
+
200
+ case "array":
201
+ if (!place.$stringConcealingArray) {
202
+ place.$stringConcealingArray = (0, _gen.ArrayExpression)([]);
203
+ place.$stringConcealingArrayName = this.getPlaceholder();
204
+ (0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(place.$stringConcealingArrayName, place.$stringConcealingArray)));
205
+ }
206
+
207
+ var arrayIndex = place.$stringConcealingArray.elements.length;
208
+ place.$stringConcealingArray.elements.push(callExpr);
209
+ var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(place.$stringConcealingArrayName), (0, _gen.Literal)(arrayIndex), true);
210
+ newExpr = memberExpression;
211
+ break;
212
+
213
+ case "object":
214
+ if (!place.$stringConcealingObject) {
215
+ place.$stringConcealingObject = (0, _gen.ObjectExpression)([]);
216
+ place.$stringConcealingObjectName = this.getPlaceholder();
217
+ (0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(place.$stringConcealingObjectName, place.$stringConcealingObject)));
218
+ }
219
+
220
+ var propName = this.gen.generate();
221
+ var property = (0, _gen.Property)((0, _gen.Literal)(propName), callExpr, true);
222
+ place.$stringConcealingObject.properties.push(property);
223
+ var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(place.$stringConcealingObjectName), (0, _gen.Literal)(propName), true);
224
+ newExpr = memberExpression;
225
+ break;
191
226
  }
192
227
  }
228
+
229
+ this.replaceIdentifierOrLiteral(object, newExpr, parents);
193
230
  };
194
231
  }
195
232
 
@@ -378,7 +378,7 @@ class Transform {
378
378
  }
379
379
  }
380
380
  /**
381
- * Verbose logging for warning/importing messages.
381
+ * Verbose logging for warning/important messages.
382
382
  * @param messages
383
383
  */
384
384
 
package/dist/traverse.js CHANGED
@@ -40,15 +40,7 @@ function isBlock(object) {
40
40
  }
41
41
 
42
42
  function walk(object, parents, onEnter) {
43
- let seen = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : new Set();
44
-
45
43
  if (typeof object === "object" && object) {
46
- if (seen.has(object)) {
47
- console.log(object);
48
- throw new Error("Already seen: " + object.type);
49
- }
50
-
51
- seen.add(object);
52
44
  var newParents = [object, ...parents];
53
45
 
54
46
  if (!Array.isArray(object)) {