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
@@ -1,15 +1,20 @@
1
1
  import { compileJsSync } from "../compiler";
2
- import { reservedIdentifiers } from "../constants";
2
+ import { predictableFunctionTag, reservedIdentifiers } from "../constants";
3
3
  import Obfuscator from "../obfuscator";
4
4
  import { ObfuscateOrder } from "../order";
5
5
  import { ComputeProbabilityMap } from "../probability";
6
+ import { FunctionLengthTemplate } from "../templates/functionLength";
7
+ import { ObjectDefineProperty } from "../templates/globals";
8
+ import Template from "../templates/template";
6
9
  import { walk } from "../traverse";
7
10
  import {
8
11
  ArrayExpression,
9
12
  BlockStatement,
10
13
  CallExpression,
14
+ ExpressionStatement,
11
15
  Identifier,
12
16
  Literal,
17
+ LogicalExpression,
13
18
  MemberExpression,
14
19
  NewExpression,
15
20
  Node,
@@ -19,7 +24,11 @@ import {
19
24
  VariableDeclarator,
20
25
  } from "../util/gen";
21
26
  import { getIdentifierInfo } from "../util/identifiers";
22
- import { prepend, getDefiningContext } from "../util/insert";
27
+ import {
28
+ prepend,
29
+ getDefiningContext,
30
+ computeFunctionLength,
31
+ } from "../util/insert";
23
32
  import Integrity from "./lock/integrity";
24
33
  import Transform from "./transform";
25
34
 
@@ -38,6 +47,16 @@ export default class RGF extends Transform {
38
47
  // The name of the array holding all the `new Function` expressions
39
48
  arrayExpressionName: string;
40
49
 
50
+ functionLengthName: string;
51
+
52
+ getFunctionLengthName(parents: Node[]) {
53
+ if (!this.functionLengthName) {
54
+ this.functionLengthName = this.getPlaceholder();
55
+ }
56
+
57
+ return this.functionLengthName;
58
+ }
59
+
41
60
  constructor(o) {
42
61
  super(o, ObfuscateOrder.RGF);
43
62
 
@@ -50,14 +69,54 @@ export default class RGF extends Transform {
50
69
 
51
70
  // Only add the array if there were converted functions
52
71
  if (this.arrayExpressionElements.length > 0) {
72
+ var variableDeclaration = VariableDeclaration(
73
+ VariableDeclarator(
74
+ Identifier(this.arrayExpressionName),
75
+ ArrayExpression(this.arrayExpressionElements)
76
+ )
77
+ );
78
+
79
+ var nodes: Node[] = [variableDeclaration];
80
+
81
+ if (this.options.lock?.tamperProtection) {
82
+ // The name of the variable flag if eval is safe to use
83
+ var tamperProtectionCheckName = this.getPlaceholder() + "_rgfEvalCheck";
84
+
85
+ variableDeclaration.declarations[0].init = LogicalExpression(
86
+ "&&",
87
+ Identifier(tamperProtectionCheckName),
88
+ { ...variableDeclaration.declarations[0].init }
89
+ );
90
+
91
+ nodes.unshift(
92
+ ...new Template(`
93
+ var ${tamperProtectionCheckName} = false;
94
+ eval(${this.jsConfuserVar(tamperProtectionCheckName)} + "=true");
95
+ if(!${tamperProtectionCheckName}) {
96
+ {countermeasures}
97
+ }
98
+ `).compile({
99
+ countermeasures: this.lockTransform.getCounterMeasuresCode(
100
+ tree,
101
+ []
102
+ ),
103
+ })
104
+ );
105
+ }
106
+
107
+ prepend(tree, ...nodes);
108
+ }
109
+
110
+ // The function.length helper function must be placed last
111
+ if (this.functionLengthName) {
53
112
  prepend(
54
113
  tree,
55
- VariableDeclaration(
56
- VariableDeclarator(
57
- Identifier(this.arrayExpressionName),
58
- ArrayExpression(this.arrayExpressionElements)
59
- )
60
- )
114
+ FunctionLengthTemplate.single({
115
+ name: this.functionLengthName,
116
+ ObjectDefineProperty: this.createInitVariable(ObjectDefineProperty, [
117
+ tree,
118
+ ]),
119
+ })
61
120
  );
62
121
  }
63
122
  }
@@ -141,6 +200,7 @@ export default class RGF extends Transform {
141
200
  walk(object, parents, (o, p) => {
142
201
  if (
143
202
  o.type === "Identifier" &&
203
+ o.name !== this.arrayExpressionName &&
144
204
  !reservedIdentifiers.has(o.name) &&
145
205
  !this.options.globalVariables.has(o.name)
146
206
  ) {
@@ -200,6 +260,7 @@ export default class RGF extends Transform {
200
260
  });
201
261
 
202
262
  if (obfuscator.options.lock) {
263
+ obfuscator.options.lock = { ...obfuscator.options.lock };
203
264
  delete obfuscator.options.lock.countermeasures;
204
265
 
205
266
  // Integrity will not recursively apply to RGF'd functions. This is intended.
@@ -226,9 +287,26 @@ export default class RGF extends Transform {
226
287
  generator: false,
227
288
  };
228
289
 
290
+ // The new program will look like this
291
+ // new Function(`
292
+ // var rgf_array = this[0]
293
+ // function greet(message){
294
+ // console.log(message)
295
+ // }
296
+ // return greet.apply(this[1], arguments)
297
+ // `)
298
+ //
299
+ // And called like
300
+ // f.apply([ rgf_array, this ], arguments)
229
301
  var tree = {
230
302
  type: "Program",
231
303
  body: [
304
+ VariableDeclaration(
305
+ VariableDeclarator(
306
+ this.arrayExpressionName,
307
+ MemberExpression(ThisExpression(), Literal(0))
308
+ )
309
+ ),
232
310
  embeddedFunction,
233
311
  ReturnStatement(
234
312
  CallExpression(
@@ -237,7 +315,10 @@ export default class RGF extends Transform {
237
315
  Literal("apply"),
238
316
  true
239
317
  ),
240
- [ThisExpression(), Identifier("arguments")]
318
+ [
319
+ MemberExpression(ThisExpression(), Literal(1)),
320
+ Identifier("arguments"),
321
+ ]
241
322
  )
242
323
  ),
243
324
  ],
@@ -250,10 +331,18 @@ export default class RGF extends Transform {
250
331
  var toString = compileJsSync(tree, obfuscator.options);
251
332
 
252
333
  // new Function(code)
253
- var newFunctionExpression = NewExpression(Identifier("Function"), [
334
+ var newFunctionExpression: Node = NewExpression(Identifier("Function"), [
254
335
  Literal(toString),
255
336
  ]);
256
337
 
338
+ if (this.options.lock?.tamperProtection) {
339
+ // If tamper protection is enabled, wrap the function in an eval
340
+ var randomName = this.getGenerator("randomized").generate();
341
+ newFunctionExpression = CallExpression(Identifier("eval"), [
342
+ Literal(`function ${randomName}(){ ${toString} } ${randomName}`),
343
+ ]);
344
+ }
345
+
257
346
  // The index where this function is placed in the array
258
347
  var newFunctionExpressionIndex = this.arrayExpressionElements.length;
259
348
 
@@ -261,12 +350,14 @@ export default class RGF extends Transform {
261
350
  this.arrayExpressionElements.push(newFunctionExpression);
262
351
 
263
352
  // The member expression to retrieve this function
264
- var memberExpression = MemberExpression(
353
+ var memberExpression: Node = MemberExpression(
265
354
  Identifier(this.arrayExpressionName),
266
355
  Literal(newFunctionExpressionIndex),
267
356
  true
268
357
  );
269
358
 
359
+ var originalFunctionLength = computeFunctionLength(object.params);
360
+
270
361
  // Replace based on type
271
362
 
272
363
  // (1) Function Declaration:
@@ -276,19 +367,55 @@ export default class RGF extends Transform {
276
367
  ReturnStatement(
277
368
  CallExpression(
278
369
  MemberExpression(memberExpression, Literal("apply"), true),
279
- [ThisExpression(), Identifier("arguments")]
370
+ [
371
+ ArrayExpression([
372
+ Identifier(this.arrayExpressionName),
373
+ ThisExpression(),
374
+ ]),
375
+ Identifier("arguments"),
376
+ ]
280
377
  )
281
378
  ),
282
379
  ]);
283
380
 
284
381
  // The parameters are no longer needed ('arguments' is used to capture them)
285
382
  object.params = [];
383
+
384
+ // The function is no longer guaranteed to not have extraneous parameters passed in
385
+ object[predictableFunctionTag] = false;
386
+
387
+ if (
388
+ this.options.preserveFunctionLength &&
389
+ originalFunctionLength !== 0
390
+ ) {
391
+ var body = parents[0] as unknown as Node[];
392
+
393
+ body.splice(
394
+ body.indexOf(object),
395
+ 0,
396
+ ExpressionStatement(
397
+ CallExpression(Identifier(this.getFunctionLengthName(parents)), [
398
+ Identifier(object.id.name),
399
+ Literal(originalFunctionLength),
400
+ ])
401
+ )
402
+ );
403
+ }
286
404
  return;
287
405
  }
288
406
 
289
407
  // (2) Function Expression:
290
408
  // - Replace expression with member expression pointing to new function
291
409
  if (object.type === "FunctionExpression") {
410
+ if (
411
+ this.options.preserveFunctionLength &&
412
+ originalFunctionLength !== 0
413
+ ) {
414
+ memberExpression = CallExpression(
415
+ Identifier(this.getFunctionLengthName(parents)),
416
+ [memberExpression, Literal(originalFunctionLength)]
417
+ );
418
+ }
292
419
  this.replace(object, memberExpression);
293
420
  return;
294
421
  }
@@ -37,7 +37,7 @@ var Hash = function (s) {
37
37
  return ~~String(a).slice(0, 3);
38
38
  };
39
39
 
40
- var HashTemplate = Template(
40
+ var HashTemplate = new Template(
41
41
  `
42
42
  var {name} = function(arr) {
43
43
  var s = arr.map(x=>x+"").join(''), a = 1, c = 0, h, o;
@@ -68,7 +68,7 @@ export default class Shuffle extends Transform {
68
68
  match(object, parents) {
69
69
  return (
70
70
  object.type == "ArrayExpression" &&
71
- !parents.find((x) => x.$dispatcherSkip)
71
+ !parents.find((x) => x.$multiTransformSkip)
72
72
  );
73
73
  }
74
74
 
@@ -168,7 +168,7 @@ export default class Shuffle extends Transform {
168
168
  if (mode !== "hash") {
169
169
  var varPrefix = this.getPlaceholder();
170
170
  code.push(
171
- Template(`
171
+ new Template(`
172
172
  for ( var ${varPrefix}x = 16; ${varPrefix}x%4 === 0; ${varPrefix}x++) {
173
173
  var ${varPrefix}z = 0;
174
174
  ${
@@ -16,6 +16,8 @@ import {
16
16
  RestElement,
17
17
  ReturnStatement,
18
18
  SequenceExpression,
19
+ VariableDeclaration,
20
+ VariableDeclarator,
19
21
  } from "../util/gen";
20
22
  import { getIdentifierInfo } from "../util/identifiers";
21
23
  import {
@@ -32,6 +34,8 @@ import { chance, choice, getRandomInteger } from "../util/random";
32
34
  import Transform from "./transform";
33
35
  import { noRenameVariablePrefix } from "../constants";
34
36
  import { FunctionLengthTemplate } from "../templates/functionLength";
37
+ import { ObjectDefineProperty } from "../templates/globals";
38
+ import { isJSConfuserVar } from "../util/guard";
35
39
 
36
40
  export default class Stack extends Transform {
37
41
  mangledExpressionsMade: number;
@@ -49,7 +53,7 @@ export default class Stack extends Transform {
49
53
  isFunction(object) &&
50
54
  !object.params.find((x) => x.type !== "Identifier") &&
51
55
  object.body.type === "BlockStatement" &&
52
- !parents.find((x) => x.$dispatcherSkip) &&
56
+ !parents.find((x) => x.$multiTransformSkip) &&
53
57
  !object.$requiresEval
54
58
  );
55
59
  }
@@ -144,6 +148,11 @@ export default class Stack extends Transform {
144
148
  illegal.add(o.name);
145
149
  }
146
150
 
151
+ // Ignore __JS_CONFUSER_VAR__()
152
+ if (isJSConfuserVar(p)) {
153
+ illegal.add(o.name);
154
+ }
155
+
147
156
  if (
148
157
  info.isClauseParameter ||
149
158
  info.isFunctionParameter ||
@@ -494,15 +503,21 @@ export default class Stack extends Transform {
494
503
  // Ensure the array is correct length
495
504
  prepend(
496
505
  object.body,
497
- Template(`${stackName}["length"] = ${startingSize}`).single()
506
+ new Template(`${stackName}["length"] = ${startingSize}`).single()
498
507
  );
499
508
 
500
- if (originalFunctionLength !== 0) {
509
+ if (this.options.preserveFunctionLength && originalFunctionLength !== 0) {
501
510
  if (!this.functionLengthName) {
502
511
  this.functionLengthName = this.getPlaceholder();
503
512
  prepend(
504
513
  parents[parents.length - 1] || object,
505
- FunctionLengthTemplate.single({ name: this.functionLengthName })
514
+ FunctionLengthTemplate.single({
515
+ name: this.functionLengthName,
516
+ ObjectDefineProperty: this.createInitVariable(
517
+ ObjectDefineProperty,
518
+ parents
519
+ ),
520
+ })
506
521
  );
507
522
  }
508
523
 
@@ -1,16 +1,48 @@
1
1
  import Template from "../../templates/template";
2
-
3
- const Encoding: {
4
- [encoding_name: string]: {
5
- encode: (s) => string;
6
- decode: (s) => string;
7
- template: ReturnType<typeof Template>;
8
- };
9
- } = {
10
- base91: {
2
+ import { Literal } from "../../util/gen";
3
+ import { choice, shuffle } from "../../util/random";
4
+
5
+ /**
6
+ * Defines an encoding implementation the Obfuscator
7
+ */
8
+ export interface EncodingImplementation {
9
+ identity: string;
10
+
11
+ encode(s: string): string;
12
+ decode(s: string): string;
13
+ template: Template;
14
+ }
15
+
16
+ let _hasAllEncodings = false;
17
+ export function hasAllEncodings() {
18
+ return _hasAllEncodings;
19
+ }
20
+
21
+ export function createEncodingImplementation(): EncodingImplementation {
22
+ if (_hasAllEncodings) {
23
+ return EncodingImplementations[
24
+ choice(Object.keys(EncodingImplementations))
25
+ ];
26
+ }
27
+
28
+ // create base91 encoding
29
+ let strTable =
30
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
31
+
32
+ // shuffle table
33
+ strTable = shuffle(strTable.split("")).join("");
34
+
35
+ let identity = "base91_" + strTable;
36
+
37
+ if (EncodingImplementations.hasOwnProperty(identity)) {
38
+ _hasAllEncodings = true;
39
+ return EncodingImplementations[identity];
40
+ }
41
+
42
+ var encodingImplementation = {
43
+ identity,
11
44
  encode(str) {
12
- const table =
13
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
45
+ const table = strTable;
14
46
 
15
47
  const raw = Buffer.from(str, "utf-8");
16
48
  const len = raw.length;
@@ -45,8 +77,7 @@ const Encoding: {
45
77
  return ret;
46
78
  },
47
79
  decode(str) {
48
- const table =
49
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
80
+ const table = strTable;
50
81
 
51
82
  const raw = "" + (str || "");
52
83
  const len = raw.length;
@@ -80,46 +111,54 @@ const Encoding: {
80
111
 
81
112
  return Buffer.from(ret).toString("utf-8");
82
113
  },
83
- template: Template(`
84
- function {name}(str){
85
- const table =
86
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_\`{|}~"';
87
-
88
- const raw = "" + (str || "");
89
- const len = raw.length;
90
- const ret = [];
91
-
92
- let b = 0;
93
- let n = 0;
94
- let v = -1;
95
-
96
- for (let i = 0; i < len; i++) {
97
- const p = table.indexOf(raw[i]);
98
- if (p === -1) continue;
99
- if (v < 0) {
100
- v = p;
101
- } else {
102
- v += p * 91;
103
- b |= v << n;
104
- n += (v & 8191) > 88 ? 13 : 14;
105
- do {
106
- ret.push(b & 0xff);
107
- b >>= 8;
108
- n -= 8;
109
- } while (n > 7);
110
- v = -1;
114
+ template: new Template(`
115
+ function {__fnName__}(str){
116
+ var table = {__strTable__};
117
+
118
+ var raw = "" + (str || "");
119
+ var len = raw.length;
120
+ var ret = [];
121
+
122
+ var b = 0;
123
+ var n = 0;
124
+ var v = -1;
125
+
126
+ for (var i = 0; i < len; i++) {
127
+ var p = table.indexOf(raw[i]);
128
+ if (p === -1) continue;
129
+ if (v < 0) {
130
+ v = p;
131
+ } else {
132
+ v += p * 91;
133
+ b |= v << n;
134
+ n += (v & 8191) > 88 ? 13 : 14;
135
+ do {
136
+ ret.push(b & 0xff);
137
+ b >>= 8;
138
+ n -= 8;
139
+ } while (n > 7);
140
+ v = -1;
141
+ }
111
142
  }
143
+
144
+ if (v > -1) {
145
+ ret.push((b | (v << n)) & 0xff);
146
+ }
147
+
148
+ return {__bufferToString__}(ret);
112
149
  }
150
+ `).setDefaultVariables({
151
+ __strTable__: Literal(strTable),
152
+ }),
153
+ };
113
154
 
114
- if (v > -1) {
115
- ret.push((b | (v << n)) & 0xff);
116
- }
117
-
118
- return {bufferToString}(ret);
119
- }
120
- `),
121
- },
155
+ EncodingImplementations[identity] = encodingImplementation;
156
+ return encodingImplementation;
157
+ }
122
158
 
159
+ export const EncodingImplementations: {
160
+ [encodingIdentity: string]: EncodingImplementation;
161
+ } = {
123
162
  /* ascii85: { This implementation is flaky and causes decoding errors
124
163
  encode(a) {
125
164
  var b, c, d, e, f, g, h, i, j, k;
@@ -209,5 +248,3 @@ const Encoding: {
209
248
  `),
210
249
  }, */
211
250
  };
212
-
213
- export default Encoding;
@@ -2,22 +2,36 @@ import { ok } from "assert";
2
2
  import { ObfuscateOrder } from "../../order";
3
3
  import { ComputeProbabilityMap } from "../../probability";
4
4
  import Template from "../../templates/template";
5
- import { isDirective } from "../../util/compare";
5
+ import { isDirective, isModuleSource } from "../../util/compare";
6
6
  import {
7
+ AssignmentExpression,
8
+ BinaryExpression,
7
9
  CallExpression,
10
+ ExpressionStatement,
8
11
  FunctionDeclaration,
9
12
  FunctionExpression,
10
13
  Identifier,
14
+ IfStatement,
11
15
  Literal,
12
16
  MemberExpression,
17
+ ObjectExpression,
18
+ Property,
13
19
  ReturnStatement,
14
20
  VariableDeclaration,
15
21
  VariableDeclarator,
16
22
  } from "../../util/gen";
17
23
  import { append, prepend } from "../../util/insert";
18
24
  import Transform from "../transform";
19
- import { isModuleSource } from "./stringConcealing";
20
- import { chance } from "../../util/random";
25
+ import { predictableFunctionTag } from "../../constants";
26
+ import {
27
+ chance,
28
+ choice,
29
+ getRandomFalseExpression,
30
+ getRandomInteger,
31
+ getRandomString,
32
+ splitIntoChunks,
33
+ } from "../../util/random";
34
+
21
35
  function LZ_encode(c) {
22
36
  ok(c);
23
37
  var x = "charCodeAt",
@@ -58,7 +72,7 @@ function LZ_decode(b) {
58
72
  return g.join("");
59
73
  }
60
74
 
61
- const DecodeTemplate = Template(
75
+ const DecodeTemplate = new Template(
62
76
  `function {name}(b){
63
77
  var o,
64
78
  f,
@@ -94,7 +108,7 @@ export default class StringCompression extends Transform {
94
108
  this.map = new Map();
95
109
  this.ignore = new Set();
96
110
  this.string = "";
97
- this.fnName = this.getPlaceholder();
111
+ this.fnName = this.getPlaceholder() + predictableFunctionTag;
98
112
  }
99
113
 
100
114
  apply(tree) {
@@ -107,7 +121,7 @@ export default class StringCompression extends Transform {
107
121
 
108
122
  var split = this.getPlaceholder();
109
123
  var decoder = this.getPlaceholder();
110
- var getStringName = this.getPlaceholder();
124
+ var getStringName = this.getPlaceholder() + predictableFunctionTag; // Returns the string payload
111
125
 
112
126
  var encoded = LZ_encode(this.string);
113
127
  if (LZ_decode(encoded) !== this.string) {
@@ -141,15 +155,72 @@ export default class StringCompression extends Transform {
141
155
  )
142
156
  );
143
157
 
144
- append(
145
- tree,
146
- FunctionDeclaration(
147
- getStringName,
148
- [],
149
- [ReturnStatement(Literal(encoded))]
150
- )
158
+ var keys = new Set<string>();
159
+ var keysToMake = getRandomInteger(4, 14);
160
+ for (var i = 0; i < keysToMake; i++) {
161
+ keys.add(getRandomString(getRandomInteger(4, 14)));
162
+ }
163
+
164
+ var objectExpression = ObjectExpression(
165
+ Array.from(keys).map((key) => {
166
+ return Property(Literal(key), getRandomFalseExpression(), true);
167
+ })
168
+ );
169
+
170
+ // Get string function
171
+ var getStringBody = [];
172
+ var splits = splitIntoChunks(
173
+ encoded,
174
+ Math.floor(encoded.length / getRandomInteger(3, 6))
175
+ );
176
+
177
+ getStringBody.push(
178
+ VariableDeclaration(VariableDeclarator("str", Literal(splits.shift())))
179
+ );
180
+
181
+ getStringBody.push(
182
+ VariableDeclaration(VariableDeclarator("objectToTest", objectExpression))
151
183
  );
152
184
 
185
+ const addIfStatement = (testingFor, literalValueToBeAppended) => {
186
+ getStringBody.push(
187
+ IfStatement(
188
+ BinaryExpression(
189
+ "in",
190
+ Literal(testingFor),
191
+ Identifier("objectToTest")
192
+ ),
193
+ [
194
+ ExpressionStatement(
195
+ AssignmentExpression(
196
+ "+=",
197
+ Identifier("str"),
198
+ Literal(literalValueToBeAppended)
199
+ )
200
+ ),
201
+ ]
202
+ )
203
+ );
204
+ };
205
+
206
+ for (const split of splits) {
207
+ if (chance(50)) {
208
+ var fakeKey;
209
+ do {
210
+ fakeKey = getRandomString(getRandomInteger(4, 14));
211
+ } while (keys.has(fakeKey) || fakeKey in {});
212
+
213
+ addIfStatement(fakeKey, getRandomString(split.length));
214
+ }
215
+
216
+ addIfStatement(choice(Array.from(keys)), split);
217
+ }
218
+
219
+ // Return computed string
220
+ getStringBody.push(ReturnStatement(Identifier("str")));
221
+
222
+ append(tree, FunctionDeclaration(getStringName, [], getStringBody));
223
+
153
224
  append(
154
225
  tree,
155
226
  FunctionDeclaration(
@@ -176,7 +247,8 @@ export default class StringCompression extends Transform {
176
247
  object.value &&
177
248
  object.value.length > 3 &&
178
249
  !isDirective(object, parents) &&
179
- !isModuleSource(object, parents)
250
+ !isModuleSource(object, parents) &&
251
+ !parents.find((x) => x.$multiTransformSkip)
180
252
  );
181
253
  }
182
254
 
@@ -210,9 +282,6 @@ export default class StringCompression extends Transform {
210
282
  return;
211
283
  }
212
284
 
213
- // HARD CODED LIMIT of 10,000 (after 1,000 elements)
214
- if (this.map.size > 1000 && !chance(this.map.size / 100)) return;
215
-
216
285
  var index = this.map.get(object.value);
217
286
 
218
287
  // New string, add it!