js-confuser 1.5.9 → 1.7.0

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 (143) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +346 -165
  4. package/dist/constants.js +6 -2
  5. package/dist/index.js +9 -21
  6. package/dist/obfuscator.js +19 -31
  7. package/dist/options.js +5 -5
  8. package/dist/order.js +1 -3
  9. package/dist/presets.js +6 -7
  10. package/dist/probability.js +2 -4
  11. package/dist/templates/bufferToString.js +13 -0
  12. package/dist/templates/crash.js +3 -3
  13. package/dist/templates/es5.js +18 -0
  14. package/dist/templates/functionLength.js +16 -0
  15. package/dist/transforms/calculator.js +77 -21
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
  18. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  19. package/dist/transforms/deadCode.js +33 -25
  20. package/dist/transforms/dispatcher.js +8 -4
  21. package/dist/transforms/es5/antiDestructuring.js +2 -0
  22. package/dist/transforms/es5/es5.js +31 -34
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
  24. package/dist/transforms/finalizer.js +82 -0
  25. package/dist/transforms/flatten.js +229 -148
  26. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  27. package/dist/transforms/identifier/globalConcealing.js +10 -83
  28. package/dist/transforms/identifier/movedDeclarations.js +35 -88
  29. package/dist/transforms/identifier/renameVariables.js +124 -59
  30. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  31. package/dist/transforms/lock/lock.js +0 -37
  32. package/dist/transforms/minify.js +60 -57
  33. package/dist/transforms/opaquePredicates.js +1 -1
  34. package/dist/transforms/preparation/preparation.js +2 -2
  35. package/dist/transforms/preparation.js +231 -0
  36. package/dist/transforms/renameLabels.js +1 -1
  37. package/dist/transforms/rgf.js +139 -247
  38. package/dist/transforms/stack.js +128 -26
  39. package/dist/transforms/string/encoding.js +150 -179
  40. package/dist/transforms/string/stringCompression.js +14 -15
  41. package/dist/transforms/string/stringConcealing.js +25 -8
  42. package/dist/transforms/string/stringEncoding.js +13 -24
  43. package/dist/transforms/transform.js +12 -19
  44. package/dist/traverse.js +24 -10
  45. package/dist/util/gen.js +17 -1
  46. package/dist/util/identifiers.js +37 -3
  47. package/dist/util/insert.js +35 -4
  48. package/dist/util/random.js +15 -0
  49. package/docs/ControlFlowFlattening.md +595 -0
  50. package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
  51. package/{Integrity.md → docs/Integrity.md} +2 -2
  52. package/docs/RGF.md +419 -0
  53. package/package.json +5 -5
  54. package/src/constants.ts +3 -0
  55. package/src/index.ts +2 -2
  56. package/src/obfuscator.ts +19 -31
  57. package/src/options.ts +14 -103
  58. package/src/order.ts +1 -5
  59. package/src/presets.ts +6 -7
  60. package/src/probability.ts +2 -3
  61. package/src/templates/bufferToString.ts +68 -0
  62. package/src/templates/crash.ts +15 -19
  63. package/src/templates/es5.ts +131 -0
  64. package/src/templates/functionLength.ts +14 -0
  65. package/src/transforms/calculator.ts +122 -59
  66. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  67. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
  68. package/src/transforms/deadCode.ts +383 -26
  69. package/src/transforms/dispatcher.ts +9 -4
  70. package/src/transforms/es5/antiDestructuring.ts +2 -0
  71. package/src/transforms/es5/es5.ts +32 -77
  72. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
  73. package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
  74. package/src/transforms/flatten.ts +357 -300
  75. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  76. package/src/transforms/identifier/globalConcealing.ts +14 -103
  77. package/src/transforms/identifier/movedDeclarations.ts +49 -102
  78. package/src/transforms/identifier/renameVariables.ts +149 -78
  79. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  80. package/src/transforms/lock/lock.ts +1 -42
  81. package/src/transforms/minify.ts +91 -75
  82. package/src/transforms/opaquePredicates.ts +2 -2
  83. package/src/transforms/preparation.ts +238 -0
  84. package/src/transforms/renameLabels.ts +2 -2
  85. package/src/transforms/rgf.ts +213 -405
  86. package/src/transforms/stack.ts +156 -36
  87. package/src/transforms/string/encoding.ts +115 -212
  88. package/src/transforms/string/stringCompression.ts +27 -18
  89. package/src/transforms/string/stringConcealing.ts +39 -9
  90. package/src/transforms/string/stringEncoding.ts +18 -18
  91. package/src/transforms/transform.ts +21 -23
  92. package/src/traverse.ts +23 -4
  93. package/src/types.ts +2 -1
  94. package/src/util/gen.ts +28 -3
  95. package/src/util/identifiers.ts +43 -2
  96. package/src/util/insert.ts +38 -3
  97. package/src/util/random.ts +13 -0
  98. package/test/code/Cash.test.ts +1 -1
  99. package/test/code/Dynamic.test.ts +12 -10
  100. package/test/code/ES6.src.js +146 -0
  101. package/test/code/ES6.test.ts +28 -2
  102. package/test/index.test.ts +2 -1
  103. package/test/probability.test.ts +44 -0
  104. package/test/templates/template.test.ts +1 -1
  105. package/test/transforms/antiTooling.test.ts +22 -0
  106. package/test/transforms/calculator.test.ts +40 -0
  107. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
  108. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  109. package/test/transforms/deadCode.test.ts +66 -15
  110. package/test/transforms/dispatcher.test.ts +20 -1
  111. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  112. package/test/transforms/flatten.test.ts +399 -86
  113. package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
  114. package/test/transforms/identifier/renameVariables.test.ts +119 -0
  115. package/test/transforms/lock/antiDebug.test.ts +2 -2
  116. package/test/transforms/lock/lock.test.ts +1 -48
  117. package/test/transforms/minify.test.ts +104 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +261 -381
  120. package/test/transforms/stack.test.ts +143 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +82 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/identifiers.test.ts +113 -1
  127. package/test/util/insert.test.ts +57 -3
  128. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  129. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  130. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  131. package/src/transforms/eval.ts +0 -89
  132. package/src/transforms/hideInitializingCode.ts +0 -432
  133. package/src/transforms/identifier/nameRecycling.ts +0 -280
  134. package/src/transforms/label.ts +0 -64
  135. package/src/transforms/preparation/nameConflicts.ts +0 -102
  136. package/src/transforms/preparation/preparation.ts +0 -176
  137. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  138. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  139. package/test/transforms/eval.test.ts +0 -131
  140. package/test/transforms/hideInitializingCode.test.ts +0 -336
  141. package/test/transforms/identifier/nameRecycling.test.ts +0 -205
  142. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  143. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -1,6 +1,6 @@
1
1
  import JsConfuser from "../../src/index";
2
2
 
3
- it("should replace all variables with array indexes (single variable)", async () => {
3
+ test("Variant #1: Replace all variables with array indexes (single variable)", async () => {
4
4
  var output = await JsConfuser(
5
5
  `
6
6
  function TEST_FUNCTION(){
@@ -26,7 +26,7 @@ it("should replace all variables with array indexes (single variable)", async ()
26
26
  expect(value).toStrictEqual(1);
27
27
  });
28
28
 
29
- it("should replace all variables with array indexes (multiple variables)", async () => {
29
+ test("Variant #2: Replace all variables with array indexes (multiple variables)", async () => {
30
30
  var output = await JsConfuser(
31
31
  `
32
32
  function TEST_FUNCTION(){
@@ -53,7 +53,7 @@ it("should replace all variables with array indexes (multiple variables)", async
53
53
  expect(value).toStrictEqual(15);
54
54
  });
55
55
 
56
- it("should replace all variables with array indexes (uninitialized variable are made undefined)", async () => {
56
+ test("Variant #3: Replace all variables with array indexes (uninitialized variable are made undefined)", async () => {
57
57
  var output = await JsConfuser(
58
58
  `
59
59
  function TEST_FUNCTION(){
@@ -79,7 +79,7 @@ it("should replace all variables with array indexes (uninitialized variable are
79
79
  expect(value).toStrictEqual(undefined);
80
80
  });
81
81
 
82
- it("should replace all variables with array indexes (parameters)", async () => {
82
+ test("Variant #4: Replace all variables with array indexes (parameters)", async () => {
83
83
  var output = await JsConfuser(
84
84
  `
85
85
  function TEST_FUNCTION(TEST_VARIABLE_1, TEST_VARIABLE_2){
@@ -105,7 +105,7 @@ it("should replace all variables with array indexes (parameters)", async () => {
105
105
  expect(value).toStrictEqual(75);
106
106
  });
107
107
 
108
- it("should replace all variables with array indexes (nested function)", async () => {
108
+ test("Variant #5: Replace all variables with array indexes (nested function)", async () => {
109
109
  var output = await JsConfuser(
110
110
  `
111
111
  function TEST_FUNCTION(){
@@ -135,7 +135,7 @@ it("should replace all variables with array indexes (nested function)", async ()
135
135
  expect(value).toStrictEqual(65);
136
136
  });
137
137
 
138
- it("should replace all variables with array indexes (nested class)", async () => {
138
+ test("Variant #6: Replace all variables with array indexes (nested class)", async () => {
139
139
  var output = await JsConfuser(
140
140
  `
141
141
  function TEST_FUNCTION(){
@@ -173,7 +173,7 @@ it("should replace all variables with array indexes (nested class)", async () =>
173
173
  expect(value).toStrictEqual("Value");
174
174
  });
175
175
 
176
- it("should only replace variables defined within the function, and not run if any changes can be made", async () => {
176
+ test("Variant #7: Replace variables defined within the function, and not run if any changes can be made", async () => {
177
177
  var output = await JsConfuser(
178
178
  `
179
179
  var TEST_VARIABLE = 0;
@@ -192,11 +192,11 @@ it("should only replace variables defined within the function, and not run if an
192
192
  expect(output).not.toContain("...");
193
193
  });
194
194
 
195
- it("should work even when differing amount of arguments passed in", async () => {
195
+ test("Variant #8: Work even when differing amount of arguments passed in", async () => {
196
196
  var output = await JsConfuser(
197
197
  `
198
- function add3(x, y, z){
199
- return x + y;
198
+ function add3(var_x, var_y, var_z){
199
+ return var_x + var_y;
200
200
  }
201
201
 
202
202
  input(add3(10, 15), add3(10, 15, 30))
@@ -207,7 +207,7 @@ it("should work even when differing amount of arguments passed in", async () =>
207
207
  }
208
208
  );
209
209
 
210
- expect(output).not.toContain("x");
210
+ expect(output).not.toContain("var_x");
211
211
 
212
212
  var value = "never_called",
213
213
  input = (x) => (value = x);
@@ -216,7 +216,7 @@ it("should work even when differing amount of arguments passed in", async () =>
216
216
  expect(value).toStrictEqual(25);
217
217
  });
218
218
 
219
- it("should replace all variables with array indexes (middle indexes use array[index] syntax)", async () => {
219
+ test("Variant #9: Replace all variables with array indexes (middle indexes use array[index] syntax)", async () => {
220
220
  var output = await JsConfuser(
221
221
  `
222
222
  function TEST_FUNCTION(){
@@ -249,7 +249,7 @@ it("should replace all variables with array indexes (middle indexes use array[in
249
249
  expect(value).toStrictEqual("Updated");
250
250
  });
251
251
 
252
- it("should guess execution order correctly (CallExpression, arguments run before callee)", async () => {
252
+ test("Variant #10: Guess execution order correctly (CallExpression, arguments run before callee)", async () => {
253
253
  var output = await JsConfuser(
254
254
  `
255
255
  function TEST_FUNCTION(a,b){
@@ -277,14 +277,14 @@ it("should guess execution order correctly (CallExpression, arguments run before
277
277
  expect(value).toStrictEqual(25);
278
278
  });
279
279
 
280
- it("should guess execution order correctly (AssignmentExpression, right side executes first)", async () => {
280
+ test("Variant #11: Guess execution order correctly (AssignmentExpression, right side executes first)", async () => {
281
281
  var output = await JsConfuser(
282
282
  `
283
283
  function TEST_FUNCTION(a,b){
284
284
 
285
- var C;
286
- C = a + b;
287
- input(C)
285
+ var _C;
286
+ _C = a + b;
287
+ input(_C)
288
288
 
289
289
  }
290
290
 
@@ -296,7 +296,7 @@ it("should guess execution order correctly (AssignmentExpression, right side exe
296
296
  }
297
297
  );
298
298
 
299
- expect(output).not.toContain("C=");
299
+ expect(output).not.toContain("_C=");
300
300
 
301
301
  var value = "never_called",
302
302
  input = (x) => (value = x);
@@ -305,7 +305,7 @@ it("should guess execution order correctly (AssignmentExpression, right side exe
305
305
  expect(value).toStrictEqual(25);
306
306
  });
307
307
 
308
- it("should not entangle floats or NaN", async () => {
308
+ test("Variant #12: Should not entangle floats or NaN", async () => {
309
309
  var output = await JsConfuser(
310
310
  `
311
311
  function TEST_FUNCTION(){
@@ -335,7 +335,7 @@ it("should not entangle floats or NaN", async () => {
335
335
  expect(value).toStrictEqual(25.02);
336
336
  });
337
337
 
338
- it("should correctly entangle property keys", async () => {
338
+ test("Variant #13: Correctly entangle property keys", async () => {
339
339
  var output = await JsConfuser(
340
340
  `
341
341
  function TEST_FUNCTION(){
@@ -382,7 +382,7 @@ it("should correctly entangle property keys", async () => {
382
382
  expect(value).toStrictEqual(10);
383
383
  });
384
384
 
385
- it("should correctly entangle method definition keys", async () => {
385
+ test("Variant #14: Correctly entangle method definition keys", async () => {
386
386
  var output = await JsConfuser(
387
387
  `
388
388
  function TEST_FUNCTION(){
@@ -449,3 +449,125 @@ it("should correctly entangle method definition keys", async () => {
449
449
  eval(output);
450
450
  expect(value).toStrictEqual(10);
451
451
  });
452
+
453
+ test("Variant #15: Function with 'use strict' directive", async () => {
454
+ var output = await JsConfuser(
455
+ `
456
+ function useStrictFunction(){
457
+ 'use strict';
458
+
459
+ function fun(){
460
+ return this;
461
+ }
462
+
463
+ var necessaryDeclarationForStackToApply;
464
+
465
+ TEST_OUTPUT = fun() === undefined; // true
466
+ }
467
+
468
+ useStrictFunction();
469
+ `,
470
+ { target: "node", stack: true }
471
+ );
472
+
473
+ // Stack will not apply to functions with 'use strict' directive
474
+ expect(output).not.toContain("_stack");
475
+
476
+ var TEST_OUTPUT;
477
+ eval(output);
478
+
479
+ expect(TEST_OUTPUT).toStrictEqual(true);
480
+ });
481
+
482
+ test("Variant #16: Function with 'this'", async () => {
483
+ var output = await JsConfuser(
484
+ `
485
+ 'use strict';
486
+ function stackFunction(){
487
+ var necessaryDeclarationForStackToApply;
488
+
489
+ function thisFunctionDeclaration(){
490
+ return this;
491
+ }
492
+
493
+ var thisFunctionExpression1 = function(){
494
+ return this;
495
+ }
496
+
497
+ var thisFunctionExpression2;
498
+
499
+ thisFunctionExpression2 = function(){
500
+ return this;
501
+ }
502
+
503
+ return thisFunctionDeclaration() || thisFunctionExpression1() || thisFunctionExpression2();
504
+ }
505
+
506
+ TEST_OUTPUT = stackFunction() === undefined;
507
+ `,
508
+ { target: "node", stack: true }
509
+ );
510
+
511
+ // Ensure stack applied
512
+ expect(output).toContain("_stack");
513
+
514
+ // Ensure 'thisFunction' was not changed by stack due to using 'this' keyword
515
+ expect(output).toContain("function thisFunction");
516
+
517
+ var TEST_OUTPUT;
518
+ eval(output);
519
+
520
+ expect(TEST_OUTPUT).toStrictEqual(true);
521
+ });
522
+
523
+ // https://github.com/MichaelXF/js-confuser/issues/88
524
+ test("Variant #17: Syncing arguments parameter", async () => {
525
+ var output = await JsConfuser(
526
+ `
527
+ var TEST_OUTPUT;
528
+
529
+ function syncingArguments(parameter) {
530
+ arguments[0] = "Correct Value";
531
+ TEST_OUTPUT = parameter;
532
+ }
533
+
534
+ syncingArguments("Incorrect Value");
535
+ `,
536
+ { target: "node", stack: true }
537
+ );
538
+
539
+ function evalNoStrictMode(evalCode) {
540
+ var fn = new Function(evalCode + ";return TEST_OUTPUT");
541
+ return fn();
542
+ }
543
+
544
+ var TEST_OUTPUT = evalNoStrictMode(output);
545
+
546
+ expect(TEST_OUTPUT).toStrictEqual("Correct Value");
547
+ });
548
+
549
+ test("Variant #18: Preserve function.length property", async () => {
550
+ var output = await JsConfuser(
551
+ `
552
+ function oneParameter(a){
553
+ var _ = 1;
554
+ };
555
+ var twoParameters = function(a,b){
556
+ var _ = 1;
557
+ };
558
+ var myObject = {
559
+ threeParameters(a,b,c){
560
+ var _ = 1;
561
+ }
562
+ }
563
+
564
+ TEST_OUTPUT = oneParameter.length + twoParameters.length + myObject.threeParameters.length;
565
+ `,
566
+ { target: "node", stack: true }
567
+ );
568
+
569
+ var TEST_OUTPUT;
570
+ eval(output);
571
+
572
+ expect(TEST_OUTPUT).toStrictEqual(6);
573
+ });
@@ -79,3 +79,42 @@ it("should not encode constructor key", async () => {
79
79
 
80
80
  expect(TEST_VAR).toStrictEqual(100);
81
81
  });
82
+
83
+ it("should be configurable by custom function option", async () => {
84
+ var code = `
85
+ TEST_OUTPUT_1 = "My String 1";
86
+ TEST_OUTPUT_2 = "My String 2";
87
+ TEST_OUTPUT_3 = "My String 3";
88
+ `;
89
+
90
+ var stringsFound = [];
91
+
92
+ var output = await JsConfuser(code, {
93
+ target: "node",
94
+ stringCompression: (strValue) => {
95
+ stringsFound.push(strValue);
96
+
97
+ // Change all strings but "My String 2"
98
+ return strValue !== "My String 2";
99
+ },
100
+ });
101
+
102
+ // Ensure all strings were found
103
+ expect(stringsFound).toContain("My String 1");
104
+ expect(stringsFound).toContain("My String 2");
105
+ expect(stringsFound).toContain("My String 3");
106
+
107
+ // Ensure the strings got changed (except for "My String 2")
108
+ expect(output).not.toContain("TEST_OUTPUT_1='My String 1'");
109
+ expect(output).toContain("TEST_OUTPUT_2='My String 2'");
110
+ expect(output).not.toContain("TEST_OUTPUT_3='My String 3'");
111
+
112
+ // Make sure the code still works!
113
+ var TEST_OUTPUT_1, TEST_OUTPUT_2, TEST_OUTPUT_3;
114
+
115
+ eval(output);
116
+
117
+ expect(TEST_OUTPUT_1).toStrictEqual("My String 1");
118
+ expect(TEST_OUTPUT_2).toStrictEqual("My String 2");
119
+ expect(TEST_OUTPUT_3).toStrictEqual("My String 3");
120
+ });
@@ -215,3 +215,85 @@ it("should work inside the Class Constructor function", async () => {
215
215
 
216
216
  expect(TEST_OUTPUT).toStrictEqual(true);
217
217
  });
218
+
219
+ it("should be configurable by custom function option", async () => {
220
+ var code = `
221
+ var myVar1 = "My First String";
222
+ var myVar2 = "My Second String";
223
+ var myVar3 = "My Third String";
224
+
225
+ TEST_RESULT = [myVar1, myVar2, myVar3];
226
+ `;
227
+
228
+ var strings = [];
229
+
230
+ var output = await JsConfuser(code, {
231
+ target: "node",
232
+ stringConcealing: (str) => {
233
+ strings.push(str);
234
+
235
+ return str !== "My Second String";
236
+ },
237
+ });
238
+
239
+ // Ensure stringConcealing found all the strings
240
+ expect(strings).toContain("My First String");
241
+ expect(strings).toContain("My Second String");
242
+ expect(strings).toContain("My Third String");
243
+
244
+ // These strings should be encoded
245
+ expect(output).not.toContain("My First String");
246
+ expect(output).not.toContain("My Third String");
247
+
248
+ // This string should NOT be encoded
249
+ expect(output).toContain("My Second String");
250
+
251
+ // Ensure strings get properly decoded
252
+ var TEST_RESULT;
253
+
254
+ eval(output);
255
+ expect(TEST_RESULT).toStrictEqual([
256
+ "My First String",
257
+ "My Second String",
258
+ "My Third String",
259
+ ]);
260
+ });
261
+
262
+ test("Variant #13: Work without TextEncoder or Buffer being defined", async () => {
263
+ var output = await JsConfuser(
264
+ `
265
+ TEST_OUTPUT = [];
266
+ TEST_OUTPUT.push("My First String");
267
+ TEST_OUTPUT.push("My Second String");
268
+ TEST_OUTPUT.push("My Third String");
269
+ TEST_OUTPUT.push("My Fourth String");
270
+ TEST_OUTPUT.push("My Fifth String");
271
+ `,
272
+ { target: "node", stringConcealing: true }
273
+ );
274
+
275
+ // Ensure the strings got changed
276
+ expect(output).not.toContain("My First String");
277
+ expect(output).not.toContain("My Second String");
278
+ expect(output).not.toContain("My Third String");
279
+ expect(output).not.toContain("My Fourth String");
280
+ expect(output).not.toContain("My Fifth String");
281
+
282
+ // Disable TextEncoder and Buffer
283
+ var global = {};
284
+ var window = {};
285
+ var Buffer = undefined;
286
+ var TextEncoder = undefined;
287
+
288
+ // Test the code
289
+ var TEST_OUTPUT;
290
+ eval(output);
291
+
292
+ expect(TEST_OUTPUT).toStrictEqual([
293
+ "My First String",
294
+ "My Second String",
295
+ "My Third String",
296
+ "My Fourth String",
297
+ "My Fifth String",
298
+ ]);
299
+ });
@@ -1,6 +1,6 @@
1
1
  import JsConfuser from "../../../src/index";
2
2
 
3
- it("should encode strings", async () => {
3
+ test("Variant #1: Encode strings", async () => {
4
4
  var code = `var TEST_STRING = "encoded."`;
5
5
 
6
6
  var output = await JsConfuser(code, {
@@ -17,7 +17,7 @@ it("should encode strings", async () => {
17
17
  ).toStrictEqual(true);
18
18
  });
19
19
 
20
- it("should encode strings but still have same result", async () => {
20
+ test("Variant #2: Encode strings AND still have same result", async () => {
21
21
  var code = `input("encoded.")`;
22
22
 
23
23
  var output = await JsConfuser(code, {
@@ -42,3 +42,54 @@ it("should encode strings but still have same result", async () => {
42
42
 
43
43
  expect(value).toStrictEqual("encoded.");
44
44
  });
45
+
46
+ test("Variant #3: Encode object property keys", async () => {
47
+ var code = `TEST_OUTPUT = { myProperty1: true, "myProperty2": true }`;
48
+
49
+ var output = await JsConfuser(code, { target: "node", stringEncoding: true });
50
+
51
+ // Ensure the strings got changed
52
+ expect(output).not.toContain("myProperty1");
53
+ expect(output).not.toContain("myProperty2");
54
+
55
+ // Ensure output is exactly the same
56
+ var TEST_OUTPUT;
57
+ eval(output);
58
+
59
+ expect(TEST_OUTPUT).toStrictEqual({ myProperty1: true, myProperty2: true });
60
+ });
61
+
62
+ test("Variant #4: Encode object destructuring property keys", async () => {
63
+ var code = `({ ["myDestructedKey"]: TEST_OUTPUT } = { myDestructedKey: true })`;
64
+
65
+ var output = await JsConfuser(code, { target: "node", stringEncoding: true });
66
+
67
+ // Ensure the string(s) got changed
68
+ expect(output).not.toContain("myDestructedKey");
69
+
70
+ // Ensure output is exactly the same
71
+ var TEST_OUTPUT;
72
+ eval(output);
73
+
74
+ expect(TEST_OUTPUT).toStrictEqual(true);
75
+ });
76
+
77
+ // This test multiple transformations
78
+ test("Variant #5: Preserve 'use strict' directive", async () => {
79
+ var code = `
80
+ "use strict";
81
+
82
+ var filler1;
83
+ var filler2;
84
+ var filler3;
85
+
86
+ var anotherVar = "use strict";
87
+ `;
88
+
89
+ var output = await JsConfuser(code, {
90
+ target: "node",
91
+ preset: "high",
92
+ });
93
+
94
+ expect(output.startsWith("'use strict'")).toStrictEqual(true);
95
+ });
@@ -0,0 +1,66 @@
1
+ import Obfuscator from "../../src/obfuscator";
2
+ import Transform from "../../src/transforms/transform";
3
+
4
+ describe("Transform class", () => {
5
+ class MyTransformClass extends Transform {
6
+ constructor(o) {
7
+ super(o);
8
+ }
9
+ }
10
+
11
+ const myObfuscator = new Obfuscator({
12
+ target: "node",
13
+ identifierGenerator: "mangled",
14
+ });
15
+ const myTransform = new MyTransformClass(myObfuscator);
16
+
17
+ const tree = {
18
+ type: "Program",
19
+ body: [],
20
+ };
21
+
22
+ test("Variant #1: Not implemented match()", () => {
23
+ expect(() => myTransform.match(tree, [])).toThrow();
24
+ });
25
+
26
+ test("Variant #2: Not implemented transform()", () => {
27
+ expect(() => myTransform.transform(tree, [])).toThrow();
28
+ });
29
+
30
+ test("Variant #3: getGenerator()", () => {
31
+ const generator = myTransform.getGenerator();
32
+
33
+ const generated = new Set<string>();
34
+
35
+ const count = 50;
36
+
37
+ for (var i = 0; i < count; i++) {
38
+ const newName = generator.generate();
39
+ generated.add(newName);
40
+ }
41
+
42
+ // This ensures all generated names are unique!
43
+ expect(generated.size).toStrictEqual(count);
44
+ });
45
+
46
+ test("Variant #4: getGenerator() with overrideMode parameter", () => {
47
+ // number generator
48
+ const generator = myTransform.getGenerator("number");
49
+
50
+ expect(generator.generate()).toStrictEqual("var_1");
51
+ expect(generator.generate()).toStrictEqual("var_2");
52
+ expect(generator.generate()).toStrictEqual("var_3");
53
+
54
+ // hexadecimal generator
55
+ const anotherGenerator = myTransform.getGenerator("hexadecimal");
56
+
57
+ expect(anotherGenerator.generate()).toContain("_0x");
58
+
59
+ // mangled generator
60
+ const yetAnotherGenerator = myTransform.getGenerator("mangled");
61
+
62
+ expect(yetAnotherGenerator.generate()).toStrictEqual("a");
63
+ expect(yetAnotherGenerator.generate()).toStrictEqual("b");
64
+ expect(yetAnotherGenerator.generate()).toStrictEqual("c");
65
+ });
66
+ });
@@ -0,0 +1,139 @@
1
+ import traverse, { assertNoCircular } from "../src/traverse";
2
+ import { Node } from "../src/util/gen";
3
+
4
+ describe("traverse", function () {
5
+ test("Variant #1: Traverse tree", function () {
6
+ var executionOrder = [];
7
+
8
+ var tree: Node = {
9
+ type: "Program",
10
+ start: 0,
11
+ end: 27,
12
+ body: [
13
+ {
14
+ type: "ExpressionStatement",
15
+ start: 0,
16
+ end: 27,
17
+ expression: {
18
+ type: "CallExpression",
19
+ start: 0,
20
+ end: 26,
21
+ callee: {
22
+ type: "MemberExpression",
23
+ start: 0,
24
+ end: 11,
25
+ object: {
26
+ type: "Identifier",
27
+ start: 0,
28
+ end: 7,
29
+ name: "console",
30
+ },
31
+ property: {
32
+ type: "Identifier",
33
+ start: 8,
34
+ end: 11,
35
+ name: "log",
36
+ },
37
+ computed: false,
38
+ optional: false,
39
+ },
40
+ arguments: [
41
+ {
42
+ type: "Literal",
43
+ start: 12,
44
+ end: 25,
45
+ value: "Hello World",
46
+ raw: '"Hello World"',
47
+ },
48
+ ],
49
+ optional: false,
50
+ },
51
+ },
52
+ ],
53
+ sourceType: "module",
54
+ };
55
+
56
+ var literalParents;
57
+
58
+ traverse(tree, (object, parents) => {
59
+ if (object.type) {
60
+ if (object.type === "Literal") {
61
+ literalParents = parents;
62
+ }
63
+
64
+ executionOrder.push("ENTER:" + object.type);
65
+
66
+ return () => {
67
+ executionOrder.push("EXIT:" + object.type);
68
+ };
69
+ }
70
+ });
71
+
72
+ var displayString = executionOrder.join(",");
73
+
74
+ expect(displayString).toStrictEqual(
75
+ "ENTER:Program,ENTER:ExpressionStatement,ENTER:CallExpression,ENTER:MemberExpression,ENTER:Identifier,EXIT:Identifier,ENTER:Identifier,EXIT:Identifier,EXIT:MemberExpression,ENTER:Literal,EXIT:Literal,EXIT:CallExpression,EXIT:ExpressionStatement,EXIT:Program"
76
+ );
77
+
78
+ var displayLiteralParents = literalParents
79
+ .map((x) => (Array.isArray(x) ? "(array)" : x.type))
80
+ .join(",");
81
+ expect(displayLiteralParents).toStrictEqual(
82
+ "(array),CallExpression,ExpressionStatement,(array),Program"
83
+ );
84
+ });
85
+ });
86
+
87
+ describe("assertNoCircular", function () {
88
+ test("Variant #1: Valid tree", function () {
89
+ var tree = {
90
+ a: 1,
91
+ b: 2,
92
+ c: 3,
93
+ d: {
94
+ a: 1,
95
+ b: 2,
96
+ c: 3,
97
+ },
98
+ e: [
99
+ {
100
+ a: 1,
101
+ b: 2,
102
+ c: 3,
103
+ f: {
104
+ a: 1,
105
+ },
106
+ },
107
+ ],
108
+ };
109
+
110
+ expect(() => assertNoCircular(tree)).not.toThrow();
111
+ });
112
+
113
+ test("Variant #2: Invalid tree", function () {
114
+ var circularRef = {};
115
+
116
+ var tree = {
117
+ a: 1,
118
+ b: 2,
119
+ c: circularRef,
120
+ d: {
121
+ a: 1,
122
+ b: 2,
123
+ c: 3,
124
+ },
125
+ e: [
126
+ {
127
+ a: 1,
128
+ b: 2,
129
+ c: 3,
130
+ f: {
131
+ a: circularRef,
132
+ },
133
+ },
134
+ ],
135
+ };
136
+
137
+ expect(() => assertNoCircular(tree)).toThrow();
138
+ });
139
+ });