js-confuser 1.7.1 → 1.7.3

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 (153) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/CHANGELOG.md +73 -0
  3. package/README.md +32 -31
  4. package/dist/compiler.js +2 -8
  5. package/dist/constants.js +22 -10
  6. package/dist/index.js +15 -30
  7. package/dist/obfuscator.js +15 -62
  8. package/dist/options.js +33 -40
  9. package/dist/order.js +4 -7
  10. package/dist/parser.js +5 -13
  11. package/dist/precedence.js +6 -8
  12. package/dist/presets.js +4 -6
  13. package/dist/probability.js +13 -24
  14. package/dist/templates/bufferToString.js +121 -5
  15. package/dist/templates/core.js +35 -0
  16. package/dist/templates/crash.js +22 -11
  17. package/dist/templates/es5.js +125 -6
  18. package/dist/templates/functionLength.js +24 -6
  19. package/dist/templates/globals.js +9 -0
  20. package/dist/templates/template.js +189 -43
  21. package/dist/transforms/antiTooling.js +26 -22
  22. package/dist/transforms/calculator.js +19 -55
  23. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +242 -333
  24. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  25. package/dist/transforms/deadCode.js +542 -31
  26. package/dist/transforms/dispatcher.js +112 -112
  27. package/dist/transforms/es5/antiClass.js +70 -44
  28. package/dist/transforms/es5/antiDestructuring.js +14 -38
  29. package/dist/transforms/es5/antiES6Object.js +39 -48
  30. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  31. package/dist/transforms/es5/antiTemplate.js +10 -19
  32. package/dist/transforms/es5/es5.js +7 -40
  33. package/dist/transforms/extraction/classExtraction.js +83 -0
  34. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  35. package/dist/transforms/extraction/objectExtraction.js +24 -56
  36. package/dist/transforms/finalizer.js +6 -20
  37. package/dist/transforms/flatten.js +51 -99
  38. package/dist/transforms/identifier/globalAnalysis.js +21 -26
  39. package/dist/transforms/identifier/globalConcealing.js +72 -56
  40. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  41. package/dist/transforms/identifier/renameVariables.js +36 -68
  42. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  43. package/dist/transforms/lock/antiDebug.js +20 -25
  44. package/dist/transforms/lock/integrity.js +53 -52
  45. package/dist/transforms/lock/lock.js +161 -126
  46. package/dist/transforms/minify.js +77 -108
  47. package/dist/transforms/opaquePredicates.js +12 -49
  48. package/dist/transforms/preparation.js +28 -49
  49. package/dist/transforms/renameLabels.js +5 -22
  50. package/dist/transforms/rgf.js +125 -72
  51. package/dist/transforms/shuffle.js +42 -47
  52. package/dist/transforms/stack.js +41 -98
  53. package/dist/transforms/string/encoding.js +76 -27
  54. package/dist/transforms/string/stringCompression.js +75 -68
  55. package/dist/transforms/string/stringConcealing.js +127 -135
  56. package/dist/transforms/string/stringEncoding.js +6 -26
  57. package/dist/transforms/string/stringSplitting.js +5 -30
  58. package/dist/transforms/transform.js +76 -104
  59. package/dist/traverse.js +11 -18
  60. package/dist/util/compare.js +27 -29
  61. package/dist/util/gen.js +32 -86
  62. package/dist/util/guard.js +5 -1
  63. package/dist/util/identifiers.js +9 -72
  64. package/dist/util/insert.js +27 -77
  65. package/dist/util/math.js +0 -3
  66. package/dist/util/object.js +3 -7
  67. package/dist/util/random.js +31 -36
  68. package/dist/util/scope.js +6 -3
  69. package/docs/Countermeasures.md +13 -6
  70. package/docs/Integrity.md +35 -28
  71. package/docs/RGF.md +6 -1
  72. package/docs/RenameVariables.md +116 -0
  73. package/docs/TamperProtection.md +100 -0
  74. package/docs/Template.md +117 -0
  75. package/package.json +3 -3
  76. package/src/constants.ts +17 -0
  77. package/src/index.ts +7 -5
  78. package/src/options.ts +60 -7
  79. package/src/order.ts +2 -2
  80. package/src/templates/bufferToString.ts +79 -11
  81. package/src/templates/core.ts +29 -0
  82. package/src/templates/crash.ts +6 -38
  83. package/src/templates/es5.ts +1 -1
  84. package/src/templates/functionLength.ts +21 -3
  85. package/src/templates/globals.ts +3 -0
  86. package/src/templates/template.ts +205 -46
  87. package/src/transforms/antiTooling.ts +33 -11
  88. package/src/transforms/calculator.ts +4 -2
  89. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +12 -5
  90. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  91. package/src/transforms/deadCode.ts +74 -42
  92. package/src/transforms/dispatcher.ts +99 -73
  93. package/src/transforms/es5/antiClass.ts +25 -12
  94. package/src/transforms/es5/antiDestructuring.ts +1 -1
  95. package/src/transforms/es5/antiES6Object.ts +2 -2
  96. package/src/transforms/es5/antiTemplate.ts +1 -1
  97. package/src/transforms/extraction/classExtraction.ts +168 -0
  98. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +11 -16
  99. package/src/transforms/extraction/objectExtraction.ts +4 -15
  100. package/src/transforms/flatten.ts +20 -5
  101. package/src/transforms/identifier/globalAnalysis.ts +18 -1
  102. package/src/transforms/identifier/globalConcealing.ts +119 -72
  103. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  104. package/src/transforms/identifier/renameVariables.ts +16 -1
  105. package/src/transforms/lock/antiDebug.ts +2 -2
  106. package/src/transforms/lock/integrity.ts +13 -11
  107. package/src/transforms/lock/lock.ts +122 -30
  108. package/src/transforms/minify.ts +28 -13
  109. package/src/transforms/opaquePredicates.ts +2 -2
  110. package/src/transforms/preparation.ts +16 -0
  111. package/src/transforms/rgf.ts +139 -12
  112. package/src/transforms/shuffle.ts +3 -3
  113. package/src/transforms/stack.ts +19 -4
  114. package/src/transforms/string/encoding.ts +88 -51
  115. package/src/transforms/string/stringCompression.ts +86 -17
  116. package/src/transforms/string/stringConcealing.ts +148 -118
  117. package/src/transforms/string/stringEncoding.ts +1 -2
  118. package/src/transforms/string/stringSplitting.ts +1 -2
  119. package/src/transforms/transform.ts +63 -46
  120. package/src/types.ts +2 -0
  121. package/src/util/compare.ts +39 -5
  122. package/src/util/gen.ts +10 -3
  123. package/src/util/guard.ts +10 -0
  124. package/src/util/insert.ts +17 -0
  125. package/src/util/random.ts +81 -1
  126. package/src/util/scope.ts +14 -2
  127. package/test/code/Cash.test.ts +94 -5
  128. package/test/code/StrictMode.src.js +65 -0
  129. package/test/code/StrictMode.test.js +37 -0
  130. package/test/compare.test.ts +62 -2
  131. package/test/options.test.ts +129 -55
  132. package/test/templates/template.test.ts +211 -1
  133. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  134. package/test/transforms/dispatcher.test.ts +55 -0
  135. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  136. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  137. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  138. package/test/transforms/identifier/globalConcealing.test.ts +89 -0
  139. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  140. package/test/transforms/identifier/renameVariables.test.ts +75 -1
  141. package/test/transforms/lock/tamperProtection.test.ts +336 -0
  142. package/test/transforms/minify.test.ts +37 -0
  143. package/test/transforms/rgf.test.ts +50 -0
  144. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  145. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  146. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  147. package/dist/transforms/eval.js +0 -84
  148. package/dist/transforms/hexadecimalNumbers.js +0 -63
  149. package/dist/transforms/hideInitializingCode.js +0 -270
  150. package/dist/transforms/identifier/nameRecycling.js +0 -218
  151. package/dist/transforms/label.js +0 -67
  152. package/dist/transforms/preparation/nameConflicts.js +0 -116
  153. package/dist/transforms/preparation/preparation.js +0 -188
@@ -34,14 +34,20 @@ import {
34
34
  isVarContext,
35
35
  prepend,
36
36
  append,
37
+ computeFunctionLength,
38
+ isFunction,
37
39
  } from "../util/insert";
38
40
  import Transform from "./transform";
39
41
  import { isInsideType } from "../util/compare";
40
42
  import { choice, shuffle } from "../util/random";
41
43
  import { ComputeProbabilityMap } from "../probability";
42
- import { reservedIdentifiers } from "../constants";
44
+ import { predictableFunctionTag, reservedIdentifiers } from "../constants";
43
45
  import { ObfuscateOrder } from "../order";
44
46
  import Template from "../templates/template";
47
+ import { FunctionLengthTemplate } from "../templates/functionLength";
48
+ import { ObjectDefineProperty } from "../templates/globals";
49
+ import { getLexicalScope } from "../util/scope";
50
+ import { isJSConfuserVar } from "../util/guard";
45
51
 
46
52
  /**
47
53
  * A Dispatcher processes function calls. All the function declarations are brought into a dictionary.
@@ -72,12 +78,30 @@ export default class Dispatcher extends Transform {
72
78
  isDebug = false;
73
79
  count: number;
74
80
 
81
+ functionLengthName: string;
82
+
75
83
  constructor(o) {
76
84
  super(o, ObfuscateOrder.Dispatcher);
77
85
 
78
86
  this.count = 0;
79
87
  }
80
88
 
89
+ apply(tree: Node): void {
90
+ super.apply(tree);
91
+
92
+ if (this.options.preserveFunctionLength && this.functionLengthName) {
93
+ prepend(
94
+ tree,
95
+ FunctionLengthTemplate.single({
96
+ name: this.functionLengthName,
97
+ ObjectDefineProperty: this.createInitVariable(ObjectDefineProperty, [
98
+ tree,
99
+ ]),
100
+ })
101
+ );
102
+ }
103
+ }
104
+
81
105
  match(object: Node, parents: Node[]) {
82
106
  if (isInsideType("AwaitExpression", object, parents)) {
83
107
  return false;
@@ -86,8 +110,8 @@ export default class Dispatcher extends Transform {
86
110
  return (
87
111
  isVarContext(object) &&
88
112
  object.type !== "ArrowFunctionExpression" &&
89
- !object.$dispatcherSkip &&
90
- !parents.find((x) => x.$dispatcherSkip)
113
+ !object.$multiTransformSkip &&
114
+ !parents.find((x) => x.$multiTransformSkip)
91
115
  );
92
116
  }
93
117
 
@@ -113,6 +137,8 @@ export default class Dispatcher extends Transform {
113
137
  ? object
114
138
  : getVarContext(object, parents);
115
139
 
140
+ var lexicalScope = isFunction(context) ? context.body : context;
141
+
116
142
  walk(object, parents, (o: Node, p: Node[]) => {
117
143
  if (object == o) {
118
144
  // Fix 1
@@ -133,11 +159,20 @@ export default class Dispatcher extends Transform {
133
159
  o.async ||
134
160
  o.generator ||
135
161
  p.find(
136
- (x) => x.$dispatcherSkip || x.type == "MethodDefinition"
162
+ (x) => x.$multiTransformSkip || x.type == "MethodDefinition"
137
163
  ) ||
138
164
  o.body.type != "BlockStatement"
139
165
  ) {
140
166
  illegalFnNames.add(name);
167
+ return;
168
+ }
169
+
170
+ // Must defined in the same block as the current function being scanned
171
+ // Solves 'let' and 'class' declaration issue
172
+ var ls = getLexicalScope(o, p);
173
+ if (ls !== lexicalScope) {
174
+ illegalFnNames.add(name);
175
+ return;
141
176
  }
142
177
 
143
178
  // If dupe, no routing
@@ -181,6 +216,9 @@ export default class Dispatcher extends Transform {
181
216
  if (!info.spec.isReferenced) {
182
217
  return;
183
218
  }
219
+ if (isJSConfuserVar(p)) {
220
+ illegalFnNames.add(o.name);
221
+ }
184
222
  if (info.spec.isDefined) {
185
223
  if (info.isFunctionDeclaration) {
186
224
  if (
@@ -217,11 +255,18 @@ export default class Dispatcher extends Transform {
217
255
 
218
256
  // Only make a dispatcher function if it caught any functions
219
257
  if (set.size > 0) {
258
+ if (!this.functionLengthName) {
259
+ this.functionLengthName = this.getPlaceholder();
260
+ }
261
+
220
262
  var payloadArg =
221
263
  this.getPlaceholder() + "_dispatcher_" + this.count + "_payload";
222
264
 
223
265
  var dispatcherFnName =
224
- this.getPlaceholder() + "_dispatcher_" + this.count;
266
+ this.getPlaceholder() +
267
+ "_dispatcher_" +
268
+ this.count +
269
+ predictableFunctionTag;
225
270
 
226
271
  this.log(dispatcherFnName, set);
227
272
  this.count++;
@@ -253,6 +298,8 @@ export default class Dispatcher extends Transform {
253
298
  expression: false,
254
299
  type: "FunctionExpression",
255
300
  id: null,
301
+ params: [],
302
+ [predictableFunctionTag]: true,
256
303
  };
257
304
  this.addComment(functionExpression, name);
258
305
 
@@ -272,48 +319,6 @@ export default class Dispatcher extends Transform {
272
319
  );
273
320
 
274
321
  prepend(def.body, variableDeclaration);
275
-
276
- // replace params with random identifiers
277
- var args = [0, 1, 2].map((x) => this.getPlaceholder());
278
- functionExpression.params = args.map((x) => Identifier(x));
279
-
280
- var deadCode = choice(["fakeReturn", "ifStatement"]);
281
-
282
- switch (deadCode) {
283
- case "fakeReturn":
284
- // Dead code...
285
- var ifStatement = IfStatement(
286
- UnaryExpression("!", Identifier(args[0])),
287
- [
288
- ReturnStatement(
289
- CallExpression(Identifier(args[1]), [
290
- ThisExpression(),
291
- Identifier(args[2]),
292
- ])
293
- ),
294
- ],
295
- null
296
- );
297
-
298
- body.unshift(ifStatement);
299
- break;
300
-
301
- case "ifStatement":
302
- var test = LogicalExpression(
303
- "||",
304
- Identifier(args[0]),
305
- AssignmentExpression(
306
- "=",
307
- Identifier(args[1]),
308
- CallExpression(Identifier(args[2]), [])
309
- )
310
- );
311
- def.body = BlockStatement([
312
- IfStatement(test, [...body], null),
313
- ReturnStatement(Identifier(args[1])),
314
- ]);
315
- break;
316
- }
317
322
  }
318
323
 
319
324
  // For logging purposes
@@ -380,6 +385,48 @@ export default class Dispatcher extends Transform {
380
385
  null
381
386
  ),
382
387
 
388
+ VariableDeclaration(
389
+ VariableDeclarator(
390
+ Identifier("lengths"),
391
+ ObjectExpression(
392
+ !this.options.preserveFunctionLength
393
+ ? []
394
+ : shuffledKeys
395
+ .map((name) => {
396
+ var [def, defParents] = functionDeclarations[name];
397
+
398
+ return {
399
+ key: newFnNames[name],
400
+ value: computeFunctionLength(def.params),
401
+ };
402
+ })
403
+ .filter((item) => item.value !== 0)
404
+ .map((item) =>
405
+ Property(Literal(item.key), Literal(item.value))
406
+ )
407
+ )
408
+ )
409
+ ),
410
+
411
+ new Template(`
412
+ function makeFn${predictableFunctionTag}(){
413
+ var fn = function(...args){
414
+ ${payloadArg} = args;
415
+ return ${mapName}[${x}].call(this)
416
+ }, a = lengths[${x}]
417
+
418
+ ${
419
+ this.options.preserveFunctionLength
420
+ ? `if(a){
421
+ return ${this.functionLengthName}(fn, a)
422
+ }`
423
+ : ""
424
+ }
425
+
426
+ return fn
427
+ }
428
+ `).single(),
429
+
383
430
  // Arg to get a function reference
384
431
  IfStatement(
385
432
  BinaryExpression("==", Identifier(y), Literal(expectedGet)),
@@ -403,30 +450,9 @@ export default class Dispatcher extends Transform {
403
450
  Identifier(x),
404
451
  true
405
452
  ),
406
- FunctionExpression(
407
- [RestElement(Identifier(getterArgName))],
408
- [
409
- // Arg setter
410
- ExpressionStatement(
411
- AssignmentExpression(
412
- "=",
413
- Identifier(payloadArg),
414
- Identifier(getterArgName)
415
- )
416
- ),
417
-
418
- // Call fn & return
419
- ReturnStatement(
420
- CallExpression(
421
- MemberExpression(
422
- getAccessor(),
423
- Identifier("call"),
424
- false
425
- ),
426
- [ThisExpression(), Literal(gen.generate())]
427
- )
428
- ),
429
- ]
453
+ CallExpression(
454
+ Identifier(`makeFn${predictableFunctionTag}`),
455
+ []
430
456
  )
431
457
  )
432
458
  )
@@ -439,7 +465,7 @@ export default class Dispatcher extends Transform {
439
465
  AssignmentExpression(
440
466
  "=",
441
467
  Identifier(returnProp),
442
- CallExpression(getAccessor(), [Literal(gen.generate())])
468
+ CallExpression(getAccessor(), [])
443
469
  )
444
470
  ),
445
471
  ]
@@ -603,7 +629,7 @@ export default class Dispatcher extends Transform {
603
629
  VariableDeclaration(
604
630
  VariableDeclarator(
605
631
  Identifier(cacheName),
606
- Template(`Object.create(null)`).single().expression
632
+ new Template(`Object.create(null)`).single().expression
607
633
  )
608
634
  )
609
635
  );
@@ -46,8 +46,10 @@ export default class AntiClass extends Transform {
46
46
  var thisName = "this" + this.getPlaceholder();
47
47
 
48
48
  // self this
49
- virtualBody.push(Template(`var ${thisName} = this;`).single());
50
- virtualBody.push(Template(`${thisName}["constructor"] = null;`).single());
49
+ virtualBody.push(new Template(`var ${thisName} = this;`).single());
50
+ virtualBody.push(
51
+ new Template(`${thisName}["constructor"] = null;`).single()
52
+ );
51
53
  var superArguments;
52
54
  var superBody = [];
53
55
 
@@ -60,14 +62,14 @@ export default class AntiClass extends Transform {
60
62
 
61
63
  // getters/setters
62
64
  virtualBody.push(
63
- Template(
65
+ new Template(
64
66
  `var ${virtualDescriptorsName} = {getters: {}, setters: {}}`
65
67
  ).single()
66
68
  );
67
69
 
68
70
  // getters/setters
69
71
  staticBody.push(
70
- Template(
72
+ new Template(
71
73
  `var ${staticDescriptorsName} = {getters: {}, setters: {}}`
72
74
  ).single()
73
75
  );
@@ -94,8 +96,17 @@ export default class AntiClass extends Transform {
94
96
  first.expression.type == "CallExpression"
95
97
  ) {
96
98
  if (first.expression.callee.type == "Super") {
99
+ /// super(...args)
97
100
  superArguments = first.expression.arguments;
98
101
  value.body.body.shift();
102
+ } else if (
103
+ // F(super(...args))
104
+ first.expression.arguments[0] &&
105
+ first.expression.arguments[0].type === "CallExpression" &&
106
+ first.expression.arguments[0].callee.type === "Super"
107
+ ) {
108
+ superArguments = first.expression.arguments[0].arguments;
109
+ first.expression.arguments[0] = Identifier("undefined");
99
110
  }
100
111
  }
101
112
 
@@ -160,7 +171,7 @@ export default class AntiClass extends Transform {
160
171
  });
161
172
 
162
173
  virtualBody.push(
163
- Template(`
174
+ new Template(`
164
175
  [...Object.keys(${virtualDescriptorsName}.getters), ...Object.keys(${virtualDescriptorsName}.setters)].forEach(key=>{
165
176
 
166
177
  if( !${thisName}.hasOwnProperty(key) ) {
@@ -179,7 +190,7 @@ export default class AntiClass extends Transform {
179
190
  );
180
191
 
181
192
  staticBody.push(
182
- Template(`
193
+ new Template(`
183
194
  [...Object.keys(${staticDescriptorsName}.getters), ...Object.keys(${staticDescriptorsName}.setters)].forEach(key=>{
184
195
 
185
196
  if( !${virtualName}.hasOwnProperty(key) ) {
@@ -198,11 +209,11 @@ export default class AntiClass extends Transform {
198
209
  );
199
210
 
200
211
  if (superName) {
201
- ok(superArguments, "Super class with no super arguments");
212
+ ok(superArguments, "Failed to find super() arguments");
202
213
 
203
214
  // save the super state
204
215
  virtualBody.unshift(
205
- Template(
216
+ new Template(
206
217
  `
207
218
  Object.keys(this).forEach(key=>{
208
219
  var descriptor = Object.getOwnPropertyDescriptor(this, key);
@@ -224,17 +235,17 @@ export default class AntiClass extends Transform {
224
235
  )
225
236
  );
226
237
 
227
- virtualBody.unshift(Template(`var ${superName} = {}`).single());
238
+ virtualBody.unshift(new Template(`var ${superName} = {}`).single());
228
239
  }
229
240
 
230
241
  virtualBody.push(
231
- Template(
242
+ new Template(
232
243
  `if(!this["constructor"]){this["constructor"] = ()=>{}};`
233
244
  ).single()
234
245
  );
235
246
  if (object.id && object.id.name) {
236
247
  virtualBody.push(
237
- Template(`Object.defineProperty(this["constructor"], 'name', {
248
+ new Template(`Object.defineProperty(this["constructor"], 'name', {
238
249
  writable: true,
239
250
  configurable: true,
240
251
  value: '${object.id.name}'
@@ -242,7 +253,9 @@ export default class AntiClass extends Transform {
242
253
  );
243
254
  }
244
255
 
245
- virtualBody.push(Template(`this["constructor"](...arguments)`).single());
256
+ virtualBody.push(
257
+ new Template(`this["constructor"](...arguments)`).single()
258
+ );
246
259
 
247
260
  var virtualFunction = FunctionExpression([], virtualBody);
248
261
 
@@ -126,7 +126,7 @@ class AntiDestructuringParameters extends Transform {
126
126
  VariableDeclaration(
127
127
  VariableDeclarator(
128
128
  arrayPattern,
129
- Template(`Array.prototype.slice.call(arguments)`).single()
129
+ new Template(`Array.prototype.slice.call(arguments)`).single()
130
130
  .expression
131
131
  )
132
132
  )
@@ -14,7 +14,7 @@ import { prepend } from "../../util/insert";
14
14
  import { getBlock } from "../../traverse";
15
15
  import Template from "../../templates/template";
16
16
 
17
- var HelperFunctions = Template(
17
+ var HelperFunctions = new Template(
18
18
  `
19
19
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
20
20
 
@@ -187,7 +187,7 @@ export default class AntiES6Object extends Transform {
187
187
 
188
188
  prepend(
189
189
  parents[parents.length - 1] || block,
190
- Template(`
190
+ new Template(`
191
191
  function {name}(base, computedProps, getters, setters){
192
192
 
193
193
  for ( var i = 0; i < computedProps.length; i++ ) {
@@ -71,7 +71,7 @@ export default class AntiTemplate extends Transform {
71
71
 
72
72
  prepend(
73
73
  parents[parents.length - 1],
74
- Template(`
74
+ new Template(`
75
75
  function {name}(arr, raw){
76
76
  arr.raw = raw;
77
77
  return arr;
@@ -0,0 +1,168 @@
1
+ import { ok } from "assert";
2
+ import { ExitCallback, getBlock, walk } from "../../traverse";
3
+ import {
4
+ CallExpression,
5
+ FunctionDeclaration,
6
+ FunctionExpression,
7
+ Identifier,
8
+ Literal,
9
+ MemberExpression,
10
+ MethodDefinition,
11
+ Node,
12
+ ReturnStatement,
13
+ Super,
14
+ ThisExpression,
15
+ } from "../../util/gen";
16
+ import { isStringLiteral } from "../../util/guard";
17
+ import { isClass, prepend } from "../../util/insert";
18
+ import { getLexicalScope } from "../../util/scope";
19
+ import Transform from "../transform";
20
+
21
+ export default class ClassExtraction extends Transform {
22
+ constructor(o) {
23
+ super(o);
24
+ }
25
+
26
+ match(object: Node, parents: Node[]): boolean {
27
+ return (
28
+ object.type === "ClassDeclaration" || object.type === "ClassExpression"
29
+ );
30
+ }
31
+
32
+ extractKeyString(property: Node): string | null {
33
+ if (property.key.type === "Identifier" && !property.key.computed) {
34
+ return property.key.name;
35
+ }
36
+
37
+ if (isStringLiteral(property.key)) {
38
+ return property.key.value;
39
+ }
40
+
41
+ return null;
42
+ }
43
+
44
+ transform(object: Node, parents: Node[]): void | ExitCallback {
45
+ return () => {
46
+ var classBody = object.body;
47
+ var className = object.id?.type === "Identifier" && object.id?.name;
48
+
49
+ if (!className) className = this.getPlaceholder();
50
+
51
+ var lexicalScope = getLexicalScope(object, parents);
52
+
53
+ var superMethodName: string;
54
+
55
+ for (var methodDefinition of classBody.body) {
56
+ if (
57
+ methodDefinition.type === "MethodDefinition" &&
58
+ methodDefinition.value.type === "FunctionExpression"
59
+ ) {
60
+ // Don't change constructors calling super()
61
+ if (methodDefinition.kind === "constructor" && object.superClass)
62
+ continue;
63
+
64
+ var functionExpression: Node = methodDefinition.value;
65
+
66
+ var fnName =
67
+ className +
68
+ "_" +
69
+ methodDefinition.kind +
70
+ "_" +
71
+ this.extractKeyString(methodDefinition) || this.getPlaceholder();
72
+
73
+ walk(
74
+ functionExpression,
75
+ [methodDefinition, object, ...parents],
76
+ (o, p) => {
77
+ if (o.type === "Super") {
78
+ var classContext = p.find((node) => isClass(node));
79
+ if (classContext !== object) return;
80
+
81
+ return () => {
82
+ if (!superMethodName) {
83
+ superMethodName =
84
+ this.getGenerator("randomized").generate();
85
+ }
86
+
87
+ var memberExpression = p[0];
88
+ if (memberExpression.type === "CallExpression") {
89
+ throw new Error("Failed to detect super() usage");
90
+ }
91
+ ok(memberExpression.type === "MemberExpression");
92
+
93
+ var propertyArg = memberExpression.computed
94
+ ? memberExpression.property
95
+ : (ok(memberExpression.property.type === "Identifier"),
96
+ Literal(memberExpression.property.name));
97
+
98
+ var getSuperExpression = CallExpression(
99
+ MemberExpression(
100
+ ThisExpression(),
101
+ Literal(superMethodName),
102
+ true
103
+ ),
104
+ [propertyArg]
105
+ );
106
+
107
+ if (p[1].type === "CallExpression" && p[1].callee === p[0]) {
108
+ getSuperExpression = CallExpression(
109
+ MemberExpression(
110
+ getSuperExpression,
111
+ Literal("bind"),
112
+ true
113
+ ),
114
+ [ThisExpression()]
115
+ );
116
+ }
117
+
118
+ this.replace(p[0], getSuperExpression);
119
+ };
120
+ }
121
+ }
122
+ );
123
+
124
+ var originalParams = functionExpression.params;
125
+ var originalBody = functionExpression.body.body;
126
+
127
+ functionExpression.body.body = [
128
+ ReturnStatement(
129
+ CallExpression(
130
+ MemberExpression(Identifier(fnName), Literal("apply"), true),
131
+ [ThisExpression(), Identifier("arguments")]
132
+ )
133
+ ),
134
+ ];
135
+
136
+ functionExpression.params = [];
137
+ if (methodDefinition.kind === "set") {
138
+ functionExpression.params = [Identifier(this.getPlaceholder())];
139
+ }
140
+
141
+ prepend(
142
+ lexicalScope,
143
+ FunctionDeclaration(fnName, [...originalParams], [...originalBody])
144
+ );
145
+ }
146
+ }
147
+
148
+ if (superMethodName) {
149
+ classBody.body.push(
150
+ MethodDefinition(
151
+ Literal(superMethodName),
152
+ FunctionExpression(
153
+ [Identifier("key")],
154
+ [
155
+ ReturnStatement(
156
+ MemberExpression(Super(), Identifier("key"), true)
157
+ ),
158
+ ]
159
+ ),
160
+ "method",
161
+ false,
162
+ true
163
+ )
164
+ );
165
+ }
166
+ };
167
+ }
168
+ }
@@ -12,19 +12,17 @@ import {
12
12
  CallExpression,
13
13
  BinaryExpression,
14
14
  FunctionDeclaration,
15
- ThisExpression,
16
15
  ConditionalExpression,
17
16
  } from "../../util/gen";
18
17
  import { append, clone, prepend } from "../../util/insert";
19
- import { isDirective, isPrimitive } from "../../util/compare";
20
-
18
+ import { isDirective, isModuleSource, isPrimitive } from "../../util/compare";
21
19
  import { ObfuscateOrder } from "../../order";
22
- import { isModuleSource } from "../string/stringConcealing";
23
20
  import { ComputeProbabilityMap } from "../../probability";
24
21
  import { ok } from "assert";
25
22
  import { chance, choice, getRandomInteger } from "../../util/random";
26
23
  import { getBlock } from "../../traverse";
27
24
  import { getIdentifierInfo } from "../../util/identifiers";
25
+ import { predictableFunctionTag } from "../../constants";
28
26
 
29
27
  /**
30
28
  * [Duplicate Literals Removal](https://docs.jscrambler.com/code-integrity/documentation/transformations/duplicate-literals-removal) replaces duplicate literals with a variable name.
@@ -95,10 +93,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
95
93
  VariableDeclaration(
96
94
  VariableDeclarator(
97
95
  this.arrayName,
98
- CallExpression(
99
- MemberExpression(Identifier(getArrayFn), Literal("call"), true),
100
- [ThisExpression()]
101
- )
96
+ CallExpression(Identifier(getArrayFn), [])
102
97
  )
103
98
  )
104
99
  );
@@ -119,7 +114,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
119
114
  ];
120
115
 
121
116
  // The function uses mangling to hide the index being accessed
122
- var mangleCount = getRandomInteger(1, 10);
117
+ var mangleCount = getRandomInteger(1, 5);
123
118
  for (var i = 0; i < mangleCount; i++) {
124
119
  var operator = choice([">", "<"]);
125
120
  var compareValue = choice(indexRangeInclusive);
@@ -170,7 +165,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
170
165
  isPrimitive(object) &&
171
166
  !isDirective(object, parents) &&
172
167
  !isModuleSource(object, parents) &&
173
- !parents.find((x) => x.$dispatcherSkip)
168
+ !parents.find((x) => x.$multiTransformSkip)
174
169
  );
175
170
  }
176
171
 
@@ -188,7 +183,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
188
183
  var root = parents[parents.length - 1];
189
184
  var rootFunctionName = this.getPlaceholder() + "_dLR_0";
190
185
  this.functions.set(root, {
191
- functionName: rootFunctionName,
186
+ functionName: rootFunctionName + predictableFunctionTag,
192
187
  indexShift: getRandomInteger(-100, 100),
193
188
  });
194
189
 
@@ -199,7 +194,10 @@ export default class DuplicateLiteralsRemoval extends Transform {
199
194
  var block = getBlock(object, parents);
200
195
  if (!this.functions.has(block) && chance(50 - this.functions.size)) {
201
196
  var newFunctionName =
202
- this.getPlaceholder() + "_dLR_" + this.functions.size;
197
+ this.getPlaceholder() +
198
+ "_dLR_" +
199
+ this.functions.size +
200
+ predictableFunctionTag;
203
201
 
204
202
  this.functions.set(block, {
205
203
  functionName: newFunctionName,
@@ -224,7 +222,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
224
222
  return () => {
225
223
  if (object.type === "Identifier") {
226
224
  var info = getIdentifierInfo(object, parents);
227
- if (info.isLabel || info.spec.isDefined) return;
225
+ if (info.isLabel || info.spec.isDefined || info.spec.isModified) return;
228
226
  }
229
227
  if (object.regex) {
230
228
  return;
@@ -234,9 +232,6 @@ export default class DuplicateLiteralsRemoval extends Transform {
234
232
  return;
235
233
  }
236
234
 
237
- // HARD CODED LIMIT of 10,000 (after 1,000 elements)
238
- if (this.map.size > 1000 && chance(this.map.size / 100)) return;
239
-
240
235
  if (
241
236
  this.arrayName &&
242
237
  parents[0].object &&