js-confuser 1.5.6 → 1.5.8

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 (29) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/options.js +4 -4
  3. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +16 -2
  4. package/dist/transforms/identifier/nameRecycling.js +8 -2
  5. package/dist/transforms/identifier/renameVariables.js +9 -0
  6. package/dist/transforms/lock/antiDebug.js +1 -1
  7. package/dist/transforms/lock/integrity.js +6 -2
  8. package/dist/transforms/lock/lock.js +40 -32
  9. package/dist/transforms/preparation/preparation.js +0 -7
  10. package/dist/transforms/rgf.js +32 -3
  11. package/dist/transforms/string/stringConcealing.js +77 -40
  12. package/dist/transforms/transform.js +1 -1
  13. package/package.json +2 -2
  14. package/src/options.ts +10 -4
  15. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +16 -1
  16. package/src/transforms/identifier/nameRecycling.ts +14 -3
  17. package/src/transforms/identifier/renameVariables.ts +19 -0
  18. package/src/transforms/lock/antiDebug.ts +1 -1
  19. package/src/transforms/lock/integrity.ts +13 -1
  20. package/src/transforms/lock/lock.ts +81 -44
  21. package/src/transforms/preparation/preparation.ts +2 -21
  22. package/src/transforms/rgf.ts +39 -3
  23. package/src/transforms/string/stringConcealing.ts +120 -56
  24. package/src/transforms/transform.ts +1 -1
  25. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +36 -0
  26. package/test/transforms/identifier/nameRecycling.test.ts +39 -0
  27. package/test/transforms/identifier/renameVariables.test.ts +38 -0
  28. package/test/transforms/lock/countermeasures.test.ts +18 -0
  29. package/test/transforms/rgf.test.ts +37 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # `1.5.8`
2
+ Several fixes
3
+
4
+ - Fixed [#46](https://github.com/MichaelXF/js-confuser/issues/46)
5
+ - - Updated the validation on `lock` options
6
+
7
+ - Fixed [#68](https://github.com/MichaelXF/js-confuser/issues/68)
8
+ - - Name Recycling fixed to not break certain function declarations
9
+
10
+ - Fixed [#69](https://github.com/MichaelXF/js-confuser/issues/69), [#70](https://github.com/MichaelXF/js-confuser/issues/70) and [#71](https://github.com/MichaelXF/js-confuser/issues/71)
11
+ - - Import statements to be properly handled
12
+
13
+ - Slight improvements to String Concealing
14
+
15
+ # `1.5.7`
16
+ Countermeasures function fixes
17
+
18
+ This update focuses on fixing Countermeasures bugs
19
+
20
+ The `countermeasures` is custom callback function to invoke when a lock is triggered.
21
+
22
+ - Fixed [#66](https://github.com/MichaelXF/js-confuser/issues/66)
23
+ - - RGF to properly handle the countermeasures function
24
+
25
+ - Added additional code to prevent an infinite loop from occurring
26
+
27
+ - Slight improvements to RGF
28
+
1
29
  # `1.5.6`
2
30
  Website changed and RGF fixes
3
31
 
package/dist/options.js CHANGED
@@ -40,24 +40,24 @@ function validateOptions(options) {
40
40
 
41
41
  if (options.lock) {
42
42
  // Validate browser-lock option
43
- if (typeof options.lock.browserLock !== "undefined") {
43
+ if (options.lock.browserLock && typeof options.lock.browserLock !== "undefined") {
44
44
  (0, _assert.ok)(Array.isArray(options.lock.browserLock), "browserLock must be an array");
45
45
  (0, _assert.ok)(!options.lock.browserLock.find(browserName => !validBrowsers.has(browserName)), 'Invalid browser name. Allowed: "firefox", "chrome", "iexplorer", "edge", "safari", "opera"');
46
46
  } // Validate os-lock option
47
47
 
48
48
 
49
- if (typeof options.lock.osLock !== "undefined") {
49
+ if (options.lock.osLock && typeof options.lock.osLock !== "undefined") {
50
50
  (0, _assert.ok)(Array.isArray(options.lock.osLock), "osLock must be an array");
51
51
  (0, _assert.ok)(!options.lock.osLock.find(osName => !validOses.has(osName)), 'Invalid OS name. Allowed: "windows", "linux", "osx", "ios", "android"');
52
52
  } // Validate domain-lock option
53
53
 
54
54
 
55
- if (typeof options.lock.domainLock !== "undefined") {
55
+ if (options.lock.domainLock && typeof options.lock.domainLock !== "undefined") {
56
56
  (0, _assert.ok)(Array.isArray(options.lock.domainLock), "domainLock must be an array");
57
57
  } // Validate context option
58
58
 
59
59
 
60
- if (typeof options.lock.context !== "undefined") {
60
+ if (options.lock.context && typeof options.lock.context !== "undefined") {
61
61
  (0, _assert.ok)(Array.isArray(options.lock.context), "context must be an array");
62
62
  } // Validate start-date option
63
63
 
@@ -31,6 +31,8 @@ var _expressionObfuscation = _interopRequireDefault(require("./expressionObfusca
31
31
 
32
32
  var _switchCaseObfuscation = _interopRequireDefault(require("./switchCaseObfuscation"));
33
33
 
34
+ var _stringConcealing = require("../string/stringConcealing");
35
+
34
36
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
37
 
36
38
  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; }
@@ -181,6 +183,14 @@ class ControlFlowFlattening extends _transform.default {
181
183
  illegalFnNames.forEach(illegal => {
182
184
  fnNames.delete(illegal);
183
185
  });
186
+ var importDeclarations = [];
187
+
188
+ for (var stmt of body) {
189
+ if (stmt.type === "ImportDeclaration") {
190
+ importDeclarations.push(stmt);
191
+ }
192
+ }
193
+
184
194
  var fraction = 0.9;
185
195
 
186
196
  if (body.length > 20) {
@@ -237,7 +247,7 @@ class ControlFlowFlattening extends _transform.default {
237
247
  body: [...currentBody]
238
248
  });
239
249
  (0, _traverse.walk)(currentBody, [], (o, p) => {
240
- if (o.type == "Literal" && typeof o.value == "string" && !o.regex && Math.random() / (Object.keys(stringBank).length / 2 + 1) > 0.5) {
250
+ if (o.type == "Literal" && typeof o.value == "string" && !(0, _stringConcealing.isModuleSource)(o, p) && !o.regex && Math.random() / (Object.keys(stringBank).length / 2 + 1) > 0.5) {
241
251
  needsStringBankVar = true;
242
252
 
243
253
  if (!stringBankByLabels[currentLabel]) {
@@ -260,7 +270,7 @@ class ControlFlowFlattening extends _transform.default {
260
270
  };
261
271
 
262
272
  body.forEach((stmt, i) => {
263
- if (functionDeclarations.has(stmt)) {
273
+ if (functionDeclarations.has(stmt) || stmt.type === "ImportDeclaration") {
264
274
  return;
265
275
  }
266
276
 
@@ -708,6 +718,10 @@ class ControlFlowFlattening extends _transform.default {
708
718
  var discriminant = (0, _template.default)("".concat(stateVars.join("+"))).single().expression;
709
719
  body.length = 0;
710
720
 
721
+ for (var importDeclaration of importDeclarations) {
722
+ body.push(importDeclaration);
723
+ }
724
+
711
725
  if (functionDeclarations.size) {
712
726
  functionDeclarations.forEach(x => {
713
727
  if (!x.id || illegalFnNames.has(x.id.name)) {
@@ -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
  }));
@@ -148,7 +148,7 @@ class Integrity extends _transform.default {
148
148
  }
149
149
 
150
150
  return () => {
151
- object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode();
151
+ object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(object, parents);
152
152
 
153
153
  object.$eval = () => {
154
154
  var functionName = this.generateIdentifier();
@@ -178,7 +178,11 @@ class Integrity extends _transform.default {
178
178
  ifStatement.alternate = (0, _gen.BlockStatement)(object.__hiddenCountermeasures);
179
179
  }
180
180
 
181
- object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]);
181
+ object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]); // Make sure the countermeasures activation variable is present
182
+
183
+ if (this.lock.counterMeasuresActivated) {
184
+ object.body.body.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.lock.counterMeasuresActivated)));
185
+ }
182
186
 
183
187
  if (object.type == "ArrowFunctionExpression") {
184
188
  object.type = "FunctionExpression";
@@ -43,6 +43,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
43
43
  * Applies browser & date locks.
44
44
  */
45
45
  class Lock extends _transform.default {
46
+ /**
47
+ * This is a boolean variable injected into the source code determining wether the countermeasures function has been called.
48
+ * This is used to prevent infinite loops from happening
49
+ */
46
50
  constructor(o) {
47
51
  super(o, _order.ObfuscateOrder.Lock); // Removed feature
48
52
  // if (this.options.lock.startDate && this.options.lock.endDate) {
@@ -55,6 +59,8 @@ class Lock extends _transform.default {
55
59
 
56
60
  _defineProperty(this, "iosDetectFn", void 0);
57
61
 
62
+ _defineProperty(this, "counterMeasuresActivated", void 0);
63
+
58
64
  _defineProperty(this, "made", void 0);
59
65
 
60
66
  if (this.options.lock.integrity) {
@@ -70,34 +76,29 @@ class Lock extends _transform.default {
70
76
 
71
77
  apply(tree) {
72
78
  if (typeof this.options.lock.countermeasures === "string" && (0, _compare.isValidIdentifier)(this.options.lock.countermeasures)) {
73
- var defined = new Set();
74
79
  (0, _traverse.default)(tree, (object, parents) => {
75
- if (object.type == "Identifier") {
80
+ if (object.type == "Identifier" && object.name === this.options.lock.countermeasures) {
76
81
  var info = (0, _identifiers.getIdentifierInfo)(object, parents);
77
82
 
78
83
  if (info.spec.isDefined) {
79
- defined.add(object.name);
80
-
81
- if (object.name === this.options.lock.countermeasures) {
82
- if (this.counterMeasuresNode) {
83
- throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
84
- } else {
85
- var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
86
-
87
- if (definingContext != tree) {
88
- throw new Error("Countermeasures function must be defined at the global level");
89
- }
84
+ if (this.counterMeasuresNode) {
85
+ throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
86
+ } else {
87
+ var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
90
88
 
91
- var chain = [object, parents];
89
+ if (definingContext != tree) {
90
+ throw new Error("Countermeasures function must be defined at the global level");
91
+ }
92
92
 
93
- if (info.isFunctionDeclaration) {
94
- chain = [parents[0], parents.slice(1)];
95
- } else if (info.isVariableDeclaration) {
96
- chain = [parents[1], parents.slice(2)];
97
- }
93
+ var chain = [object, parents];
98
94
 
99
- this.counterMeasuresNode = chain;
95
+ if (info.isFunctionDeclaration) {
96
+ chain = [parents[0], parents.slice(1)];
97
+ } else if (info.isVariableDeclaration) {
98
+ chain = [parents[1], parents.slice(2)];
100
99
  }
100
+
101
+ this.counterMeasuresNode = chain;
101
102
  }
102
103
  }
103
104
  }
@@ -111,7 +112,7 @@ class Lock extends _transform.default {
111
112
  super.apply(tree);
112
113
  }
113
114
 
114
- getCounterMeasuresCode() {
115
+ getCounterMeasuresCode(object, parents) {
115
116
  var opt = this.options.lock.countermeasures;
116
117
 
117
118
  if (opt === false) {
@@ -120,8 +121,13 @@ class Lock extends _transform.default {
120
121
 
121
122
 
122
123
  if (typeof opt === "string") {
123
- // Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
124
- return [(0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _template.default)(opt).single().expression, []))];
124
+ if (!this.counterMeasuresActivated) {
125
+ this.counterMeasuresActivated = this.getPlaceholder();
126
+ (0, _insert.prepend)(parents[parents.length - 1] || object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.counterMeasuresActivated)));
127
+ } // Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
128
+
129
+
130
+ return [(0, _gen.ExpressionStatement)((0, _gen.LogicalExpression)("||", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.SequenceExpression)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.Literal)(true)), (0, _gen.CallExpression)((0, _template.default)(opt).single().expression, [])])))];
125
131
  }
126
132
 
127
133
  var type = (0, _random.choice)(["crash", "exit"]);
@@ -239,7 +245,7 @@ class Lock extends _transform.default {
239
245
  // A very simple mechanism inspired from https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/src/custom-code-helpers/self-defending/templates/SelfDefendingNoEvalTemplate.ts
240
246
  // regExp checks for a newline, formatters add these
241
247
  var callExpression = (0, _template.default)("\n (\n function(){\n // Breaks JSNice.org, beautifier.io\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n return test()\n }\n\n return namedFunction();\n }\n )()\n ").single().expression;
242
- nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode() || [], null));
248
+ nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode(object, parents) || [], null));
243
249
  break;
244
250
 
245
251
  case "nativeFunction":
@@ -270,23 +276,24 @@ class Lock extends _transform.default {
270
276
  test = (0, _template.default)("".concat(fn, ".toString().split(\"{ [native code] }\").length <= 1")).single().expression;
271
277
  }
272
278
 
273
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
279
+ nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
274
280
  }
275
281
 
276
282
  break;
277
283
 
278
284
  case "startDate":
279
285
  test = (0, _gen.BinaryExpression)("<", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.startDate)));
280
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
286
+ nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
281
287
  break;
282
288
 
283
289
  case "endDate":
284
290
  test = (0, _gen.BinaryExpression)(">", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.endDate)));
285
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
291
+ nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
286
292
  break;
287
293
 
288
294
  case "context":
289
- var prop = (0, _random.choice)(this.options.lock.context); // Todo: Alternative to `this`
295
+ var prop = (0, _random.choice)(this.options.lock.context);
296
+ var code = this.getCounterMeasuresCode(object, parents) || []; // Todo: Alternative to `this`
290
297
 
291
298
  if (!this.globalVar) {
292
299
  offset = 1;
@@ -295,12 +302,13 @@ class Lock extends _transform.default {
295
302
  }
296
303
 
297
304
  test = (0, _gen.UnaryExpression)("!", (0, _gen.MemberExpression)((0, _gen.Identifier)(this.globalVar), (0, _gen.Literal)(prop), true));
298
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
305
+ nodes.push((0, _gen.IfStatement)(test, code, null));
299
306
  break;
300
307
 
301
308
  case "osLock":
302
309
  var navigatorUserAgent = (0, _template.default)("window.navigator.userAgent.toLowerCase()").single().expression;
303
310
  (0, _assert.ok)(this.options.lock.osLock);
311
+ var code = this.getCounterMeasuresCode(object, parents) || [];
304
312
  this.options.lock.osLock.forEach(osName => {
305
313
  var agentMatcher = {
306
314
  windows: "Win",
@@ -338,7 +346,7 @@ class Lock extends _transform.default {
338
346
  });
339
347
  test = (0, _gen.UnaryExpression)("!", { ...test
340
348
  });
341
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
349
+ nodes.push((0, _gen.IfStatement)(test, code, null));
342
350
  break;
343
351
 
344
352
  case "browserLock":
@@ -360,7 +368,7 @@ class Lock extends _transform.default {
360
368
  });
361
369
  test = (0, _gen.UnaryExpression)("!", { ...test
362
370
  });
363
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
371
+ nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
364
372
  break;
365
373
 
366
374
  case "domainLock":
@@ -392,7 +400,7 @@ class Lock extends _transform.default {
392
400
  test = (0, _gen.LogicalExpression)("||", (0, _gen.BinaryExpression)("==", (0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)("location")), (0, _gen.Literal)("undefined")), test);
393
401
  }
394
402
 
395
- nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
403
+ nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
396
404
  }
397
405
 
398
406
  break;
@@ -17,8 +17,6 @@ var _identifiers = require("../../util/identifiers");
17
17
 
18
18
  var _label = _interopRequireDefault(require("../label"));
19
19
 
20
- var _antiDestructuring = _interopRequireDefault(require("../es5/antiDestructuring"));
21
-
22
20
  var _compare = require("../../util/compare");
23
21
 
24
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -179,11 +177,6 @@ class Preparation extends _transform.default {
179
177
  this.before.push(new _label.default(o));
180
178
  this.before.push(new ExplicitIdentifiers(o));
181
179
  this.before.push(new ExplicitDeclarations(o));
182
-
183
- if (this.options.es5) {
184
- this.before.push(new _antiDestructuring.default(o));
185
- } // this.before.push(new NameConflicts(o));
186
-
187
180
  }
188
181
 
189
182
  match() {
@@ -75,6 +75,8 @@ class RGF extends _transform.default {
75
75
  var definingNodes = new Map();
76
76
  (0, _traverse.walk)(contextObject, contextParents, (object, parents) => {
77
77
  if (object !== contextObject && (0, _insert.isFunction)(object) && !object.$requiresEval && !object.async && !object.generator && (0, _insert.getVarContext)(parents[0], parents.slice(1)) === contextObject) {
78
+ var _this$options$lock;
79
+
78
80
  // Discard getter/setter methods
79
81
  if (parents[0].type === "Property" && parents[0].value === object) {
80
82
  if (parents[0].method || parents[0].kind === "get" || parents[0].kind === "set") {
@@ -85,12 +87,36 @@ class RGF extends _transform.default {
85
87
 
86
88
  if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
87
89
  return;
90
+ } // Avoid applying to the countermeasures function
91
+
92
+
93
+ if (typeof ((_this$options$lock = this.options.lock) === null || _this$options$lock === void 0 ? void 0 : _this$options$lock.countermeasures) === "string") {
94
+ // function countermeasures(){...}
95
+ if (object.type === "FunctionDeclaration" && object.id.type === "Identifier" && object.id.name === this.options.lock.countermeasures) {
96
+ return;
97
+ } // var countermeasures = function(){...}
98
+
99
+
100
+ if (parents[0].type === "VariableDeclarator" && parents[0].init === object && parents[0].id.type === "Identifier" && parents[0].id.name === this.options.lock.countermeasures) {
101
+ return;
102
+ }
88
103
  }
89
104
 
90
105
  var defined = new Set(),
91
106
  referenced = new Set();
92
107
  var isBound = false;
93
- (0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
108
+ /**
109
+ * The fnTraverses serves two important purposes
110
+ *
111
+ * - Identify all the variables referenced and defined here
112
+ * - Identify is the 'this' keyword is used anywhere
113
+ *
114
+ * @param o
115
+ * @param p
116
+ * @returns
117
+ */
118
+
119
+ const fnTraverser = (o, p) => {
94
120
  if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
95
121
  var info = (0, _identifiers.getIdentifierInfo)(o, p);
96
122
 
@@ -98,7 +124,7 @@ class RGF extends _transform.default {
98
124
  return;
99
125
  }
100
126
 
101
- if (info.spec.isDefined) {
127
+ if (info.spec.isDefined && (0, _insert.getDefiningContext)(o, p) === object) {
102
128
  defined.add(o.name);
103
129
  } else {
104
130
  referenced.add(o.name);
@@ -108,7 +134,10 @@ class RGF extends _transform.default {
108
134
  if (o.type == "ThisExpression" || o.type == "Super") {
109
135
  isBound = true;
110
136
  }
111
- });
137
+ };
138
+
139
+ (0, _traverse.walk)(object.params, [object, ...parents], fnTraverser);
140
+ (0, _traverse.walk)(object.body, [object, ...parents], fnTraverser);
112
141
 
113
142
  if (!isBound) {
114
143
  var _object$id;
@@ -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.ThisExpression)(), (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.ThisExpression)(), (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