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,4 +1,7 @@
1
+ import { compileJsSync } from "../../src/compiler";
2
+ import { parseSnippet } from "../../src/parser";
1
3
  import Template from "../../src/templates/template";
4
+ import { Literal } from "../../src/util/gen";
2
5
 
3
6
  describe("Template", () => {
4
7
  test("Variant #1: Error when invalid code passed in", () => {
@@ -6,9 +9,216 @@ describe("Template", () => {
6
9
  console.error = () => {};
7
10
 
8
11
  expect(() => {
9
- Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
12
+ new Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
10
13
  }).toThrow();
11
14
 
12
15
  console.error = _consoleError;
13
16
  });
17
+
18
+ test("Variant #2: Error on missing variables", () => {
19
+ var _consoleError = console.error;
20
+ console.error = () => {};
21
+
22
+ expect(() => {
23
+ new Template(`
24
+ function {name}(){
25
+ {global}.property = true;
26
+ }
27
+
28
+ `).compile({ name: "test" });
29
+ }).toThrow();
30
+
31
+ console.error = _consoleError;
32
+ });
33
+
34
+ test("Variant #3: Basic string interpolation", () => {
35
+ var Base64Template = new Template(`
36
+ function {name}(str){
37
+ return window.btoa(str)
38
+ }`);
39
+
40
+ var functionDeclaration = Base64Template.single({
41
+ name: "decodeBase64",
42
+ });
43
+
44
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
45
+ expect(functionDeclaration.id.name).toStrictEqual("decodeBase64");
46
+
47
+ // Generated code and check
48
+ var output = compileJsSync(functionDeclaration, {
49
+ target: "node",
50
+ compact: true,
51
+ });
52
+
53
+ // Ensure code has no syntax errors
54
+ eval(output);
55
+ });
56
+
57
+ test("Variant #4: AST subtree insertion", () => {
58
+ var Base64Template = new Template(`
59
+ function {name}(str){
60
+ {getWindow}
61
+
62
+ return {getWindowName}.btoa(str)
63
+ }`);
64
+
65
+ var functionDeclaration = Base64Template.single({
66
+ name: "decodeBase64",
67
+ getWindowName: "newWindow",
68
+ getWindow: parseSnippet("var newWindow = {}").body,
69
+ });
70
+
71
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
72
+ expect(functionDeclaration.body.body[0].type).toStrictEqual(
73
+ "VariableDeclaration"
74
+ );
75
+
76
+ // Generated code and check
77
+ var output = compileJsSync(functionDeclaration, {
78
+ target: "node",
79
+ compact: true,
80
+ });
81
+
82
+ expect(output).toContain("var newWindow={}");
83
+ expect(output).toContain("return newWindow.btoa(str)");
84
+ });
85
+
86
+ test("Variant #5: AST subtree insertion (callback)", () => {
87
+ var Base64Template = new Template(`
88
+ function {name}(str){
89
+ {getWindow}
90
+
91
+ return {getWindowName}.btoa(str)
92
+ }`);
93
+
94
+ var functionDeclaration = Base64Template.single({
95
+ name: "decodeBase64",
96
+ getWindowName: "newWindow",
97
+ getWindow: () => {
98
+ return parseSnippet("var newWindow = {}").body;
99
+ },
100
+ });
101
+
102
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
103
+ expect(functionDeclaration.body.body[0].type).toStrictEqual(
104
+ "VariableDeclaration"
105
+ );
106
+
107
+ // Generated code and check
108
+ var output = compileJsSync(functionDeclaration, {
109
+ target: "node",
110
+ compact: true,
111
+ });
112
+
113
+ expect(output).toContain("var newWindow={}");
114
+ expect(output).toContain("return newWindow.btoa(str)");
115
+ });
116
+
117
+ test("Variant #6: Template subtree insertion", async () => {
118
+ var NewWindowTemplate = new Template(`
119
+ var {NewWindowName} = {};
120
+ `);
121
+ var Base64Template = new Template(`
122
+ function {name}(str){
123
+ {NewWindowTemplate}
124
+
125
+ return {NewWindowName}.btoa(str)
126
+ }`);
127
+
128
+ var functionDeclaration = Base64Template.single({
129
+ name: "atob",
130
+ NewWindowTemplate: NewWindowTemplate,
131
+ NewWindowName: "newWindow",
132
+ });
133
+
134
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
135
+ expect(functionDeclaration.body.body[0].type).toStrictEqual(
136
+ "VariableDeclaration"
137
+ );
138
+
139
+ // Generated code and check
140
+ var output = compileJsSync(functionDeclaration, {
141
+ target: "node",
142
+ compact: true,
143
+ });
144
+
145
+ expect(output).toContain("var newWindow={}");
146
+ expect(output).toContain("return newWindow.btoa(str)");
147
+ });
148
+
149
+ test("Variant #7: Template subtree insertion (callback)", async () => {
150
+ var NewWindowTemplate = new Template(`
151
+ var {NewWindowName} = {};
152
+ `);
153
+ var Base64Template = new Template(`
154
+ function {name}(str){
155
+ {NewWindowTemplate}
156
+
157
+ return {NewWindowName}.btoa(str)
158
+ }`);
159
+
160
+ var functionDeclaration = Base64Template.single({
161
+ name: "atob",
162
+ NewWindowTemplate: () => NewWindowTemplate,
163
+ NewWindowName: "newWindow",
164
+ });
165
+
166
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
167
+ expect(functionDeclaration.body.body[0].type).toStrictEqual(
168
+ "VariableDeclaration"
169
+ );
170
+
171
+ // Generated code and check
172
+ var output = compileJsSync(functionDeclaration, {
173
+ target: "node",
174
+ compact: true,
175
+ });
176
+
177
+ expect(output).toContain("var newWindow={}");
178
+ expect(output).toContain("return newWindow.btoa(str)");
179
+ });
180
+
181
+ test("Variant #8: AST string replacement with Literal node", async () => {
182
+ var Base64Template = new Template(`
183
+ function {name}(str){
184
+ return window[{property}](str)
185
+ }`);
186
+
187
+ var functionDeclaration = Base64Template.single({
188
+ name: "decodeBase64",
189
+ property: Literal("atob"),
190
+ });
191
+
192
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
193
+
194
+ // Generated code and check
195
+ var output = compileJsSync(functionDeclaration, {
196
+ target: "node",
197
+ compact: true,
198
+ });
199
+
200
+ expect(output).toContain("return window['atob'](str)");
201
+ });
202
+
203
+ test("Variant #9: AST string replacement with Literal node (callback)", async () => {
204
+ var Base64Template = new Template(`
205
+ function {name}(str){
206
+ return window[{property}](str)
207
+ }`);
208
+
209
+ var functionDeclaration = Base64Template.single({
210
+ name: "decodeBase64",
211
+ property: () => Literal("atob"),
212
+ });
213
+
214
+ expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
215
+
216
+ // Generated code and check
217
+ var output = compileJsSync(functionDeclaration, {
218
+ target: "node",
219
+ compact: true,
220
+ });
221
+
222
+ expect(output).toContain("return window['atob'](str)");
223
+ });
14
224
  });
@@ -1,15 +1,21 @@
1
+ import { criticalFunctionTag } from "../../../src/constants";
1
2
  import JsConfuser from "../../../src/index";
2
3
 
4
+ // Enable Control Flow Flattening's 'Expression Obfuscation' but skips all CFF switch transformations
5
+ function fakeEnabled() {
6
+ return false;
7
+ }
8
+
3
9
  test("Variant #1: Join expressions in a sequence expression", async () => {
4
10
  var output = await JsConfuser(
5
11
  `
6
12
  TEST_OUTPUT=0;
7
13
  TEST_OUTPUT++;
8
14
  `,
9
- { target: "node", controlFlowFlattening: true }
15
+ { target: "node", controlFlowFlattening: fakeEnabled }
10
16
  );
11
17
 
12
- expect(output).toContain("(TEST_OUTPUT=0,TEST_OUTPUT++");
18
+ expect(output).toContain("TEST_OUTPUT=0,TEST_OUTPUT++");
13
19
 
14
20
  var TEST_OUTPUT;
15
21
  eval(output);
@@ -25,10 +31,10 @@ test("Variant #2: If Statement", async () => {
25
31
  TEST_OUTPUT++;
26
32
  }
27
33
  `,
28
- { target: "node", controlFlowFlattening: true }
34
+ { target: "node", controlFlowFlattening: fakeEnabled }
29
35
  );
30
36
 
31
- expect(output).toContain("if(TEST_OUTPUT=0,true)");
37
+ expect(output).toContain("TEST_OUTPUT=0,true");
32
38
 
33
39
  var TEST_OUTPUT;
34
40
  eval(output);
@@ -44,10 +50,10 @@ test("Variant #3: ForStatement (Variable Declaration initializer)", async () =>
44
50
  TEST_OUTPUT++;
45
51
  }
46
52
  `,
47
- { target: "node", controlFlowFlattening: true }
53
+ { target: "node", controlFlowFlattening: fakeEnabled }
48
54
  );
49
55
 
50
- expect(output).toContain("for(var i=(TEST_OUTPUT=0,0)");
56
+ expect(output).toContain("TEST_OUTPUT=0,0");
51
57
 
52
58
  var TEST_OUTPUT;
53
59
  eval(output);
@@ -63,10 +69,10 @@ test("Variant #4: ForStatement (Assignment expression initializer)", async () =>
63
69
  TEST_OUTPUT++;
64
70
  }
65
71
  `,
66
- { target: "node", controlFlowFlattening: true }
72
+ { target: "node", controlFlowFlattening: fakeEnabled }
67
73
  );
68
74
 
69
- expect(output).toContain("for(i=(TEST_OUTPUT=0,0)");
75
+ expect(output).toContain("TEST_OUTPUT=0,0");
70
76
 
71
77
  var TEST_OUTPUT, i;
72
78
  eval(output);
@@ -83,10 +89,10 @@ test("Variant #5: Return statement", async () => {
83
89
  }
84
90
  fn();
85
91
  `,
86
- { target: "node", controlFlowFlattening: true }
92
+ { target: "node", controlFlowFlattening: fakeEnabled }
87
93
  );
88
94
 
89
- expect(output).toContain("return TEST_OUTPUT=10,'Value'}");
95
+ expect(output).toContain("TEST_OUTPUT=10,'Value'");
90
96
 
91
97
  var TEST_OUTPUT;
92
98
  eval(output);
@@ -103,10 +109,10 @@ test("Variant #6: Return statement (no argument)", async () => {
103
109
  }
104
110
  fn();
105
111
  `,
106
- { target: "node", controlFlowFlattening: true }
112
+ { target: "node", controlFlowFlattening: fakeEnabled }
107
113
  );
108
114
 
109
- expect(output).toContain("return TEST_OUTPUT=10,undefined}");
115
+ expect(output).toContain("TEST_OUTPUT=10,undefined");
110
116
 
111
117
  var TEST_OUTPUT;
112
118
  eval(output);
@@ -127,10 +133,10 @@ test("Variant #7: Throw statement", async () => {
127
133
 
128
134
  }
129
135
  `,
130
- { target: "node", controlFlowFlattening: true }
136
+ { target: "node", controlFlowFlattening: fakeEnabled }
131
137
  );
132
138
 
133
- expect(output).toContain("throw TEST_OUTPUT='Correct Value',new Error");
139
+ expect(output).toContain("TEST_OUTPUT='Correct Value',new Error");
134
140
 
135
141
  var TEST_OUTPUT;
136
142
  eval(output);
@@ -144,10 +150,10 @@ test("Variant #8: Variable declaration", async () => {
144
150
  TEST_OUTPUT = "Correct Value";
145
151
  var x = 1, y = 2;
146
152
  `,
147
- { target: "node", controlFlowFlattening: true }
153
+ { target: "node", controlFlowFlattening: fakeEnabled }
148
154
  );
149
155
 
150
- expect(output).toContain("var x=(TEST_OUTPUT='Correct Value',1)");
156
+ expect(output).toContain("(TEST_OUTPUT='Correct Value'");
151
157
 
152
158
  var TEST_OUTPUT;
153
159
  eval(output);
@@ -161,13 +167,26 @@ test("Variant #9: Variable declaration (no initializer)", async () => {
161
167
  TEST_OUTPUT = "Correct Value";
162
168
  var x,y;
163
169
  `,
164
- { target: "node", controlFlowFlattening: true }
170
+ { target: "node", controlFlowFlattening: fakeEnabled }
165
171
  );
166
172
 
167
- expect(output).toContain("var x=(TEST_OUTPUT='Correct Value',undefined)");
173
+ expect(output).toContain(`(TEST_OUTPUT='Correct Value',undefined)`);
168
174
 
169
175
  var TEST_OUTPUT;
170
176
  eval(output);
171
177
 
172
178
  expect(TEST_OUTPUT).toStrictEqual("Correct Value");
173
179
  });
180
+
181
+ test("Variant #10: Use function call", async () => {
182
+ var output = await JsConfuser(
183
+ `
184
+ TEST_OUTPUT = "Correct Value";
185
+ var x,y;
186
+ `,
187
+ { target: "node", controlFlowFlattening: fakeEnabled }
188
+ );
189
+
190
+ expect(output).toContain("function");
191
+ expect(output).toContain(criticalFunctionTag);
192
+ });
@@ -400,3 +400,58 @@ printX();
400
400
 
401
401
  expect(TEST_OUTPUT).toStrictEqual("Correct Value");
402
402
  });
403
+
404
+ test("Variant #18: Preserve function.length property", async () => {
405
+ var output = await JsConfuser(
406
+ `
407
+ function myFunction1(){
408
+ // Function.length = 0
409
+ }
410
+ function myFunction2(a, b, c, d = "") {
411
+ // Function.length = 3
412
+ }
413
+
414
+ myFunction1();
415
+ myFunction2();
416
+ TEST_OUTPUT_1 = myFunction1.length;
417
+ TEST_OUTPUT_2 = myFunction2.length;
418
+
419
+ `,
420
+ { target: "node", dispatcher: true }
421
+ );
422
+
423
+ expect(output).toContain("dispatcher_0");
424
+
425
+ var TEST_OUTPUT_1, TEST_OUTPUT_2;
426
+ eval(output);
427
+
428
+ expect(TEST_OUTPUT_1).toStrictEqual(0);
429
+ expect(TEST_OUTPUT_2).toStrictEqual(3);
430
+ });
431
+
432
+ test("Variant #19: Lexically bound variables", async () => {
433
+ var output = await JsConfuser(
434
+ `
435
+ switch (true) {
436
+ case true:
437
+ let message = "Hello World";
438
+
439
+ function logMessage() {
440
+ TEST_OUTPUT = message;
441
+ }
442
+
443
+ logMessage();
444
+ }
445
+ `,
446
+ {
447
+ target: "node",
448
+ dispatcher: true,
449
+ }
450
+ );
451
+
452
+ var TEST_OUTPUT;
453
+
454
+ eval(output);
455
+
456
+ expect(TEST_OUTPUT).toStrictEqual("Hello World");
457
+ });
@@ -0,0 +1,86 @@
1
+ import JsConfuser from "../../../src/index";
2
+
3
+ // TODO
4
+ test.skip("Variant #1: Extract class methods", async () => {
5
+ var code = `
6
+ function nested() {
7
+ if (true) {
8
+ switch (true) {
9
+ case true:
10
+ let dimension2D = "2D";
11
+
12
+ class Square {
13
+ constructor(size) {
14
+ this.size = size;
15
+ }
16
+
17
+ static fromJSON(json) {
18
+ return new Square(json.size);
19
+ }
20
+
21
+ getArea() {
22
+ return this.size * this.size;
23
+ }
24
+
25
+ get dimensions() {
26
+ return dimension2D;
27
+ }
28
+
29
+ set dimensions(value) {
30
+ if (value !== "2D") {
31
+ throw new Error("Only supports 2D");
32
+ }
33
+ }
34
+ }
35
+
36
+ class Rectangle extends Square {
37
+ constructor(width, length) {
38
+ super(null);
39
+ this.width = width;
40
+ this.length = length;
41
+ }
42
+
43
+ static fromJSON(json) {
44
+ return new Rectangle(json.width, json.height);
45
+ }
46
+
47
+ getArea() {
48
+ return this.width * this.length;
49
+ }
50
+
51
+ myMethod(dim = super.dimensions) {
52
+ console.log(dim);
53
+ }
54
+ }
55
+
56
+ var rectangle = Rectangle.fromJSON({ width: 10, height: 5 });
57
+
58
+ console.log(rectangle.getArea());
59
+ rectangle.myMethod();
60
+
61
+ rectangle.dimensions = "2D"; // Allowed
62
+
63
+ try {
64
+ rectangle.dimensions = "3D"; // Not allowed
65
+ } catch (e) {
66
+ if (e.message.includes("Only supports 2D")) {
67
+ // console.log("Failed to set dimensions");
68
+ TEST_OUTPUT = true;
69
+ }
70
+ }
71
+
72
+ }
73
+ }
74
+ }
75
+
76
+ nested();
77
+
78
+ `;
79
+
80
+ var output = await JsConfuser(code, { target: "node" });
81
+
82
+ var TEST_OUTPUT;
83
+ eval(output);
84
+
85
+ expect(TEST_OUTPUT).toStrictEqual(true);
86
+ });
@@ -184,9 +184,17 @@ test("Variant #9: Undefined as variable name", async () => {
184
184
  `
185
185
  var undefined = 0;
186
186
  var undefined = 1;
187
+
188
+ try {
189
+ (undefined = 0);
190
+ undefined = 1;
191
+ } catch (e) {
192
+ }
187
193
  `,
188
194
  { target: "node", duplicateLiteralsRemoval: true }
189
195
  );
190
196
 
197
+ expect(output).toContain("(undefined=");
198
+
191
199
  eval(output);
192
200
  });
@@ -482,6 +482,8 @@ test("Variant #16: Handle const declarations", async () => {
482
482
  }
483
483
  );
484
484
 
485
+ expect(output).toContain("let");
486
+
485
487
  var TEST_OUTPUT;
486
488
  eval(output);
487
489
 
@@ -51,3 +51,92 @@ test("Variant #3: Properly hide in default parameter, function expression", asyn
51
51
 
52
52
  expect(TEST_OUTPUT).toStrictEqual(true);
53
53
  });
54
+
55
+ // https://github.com/MichaelXF/js-confuser/issues/131
56
+ test("Variant #4: Don't change __dirname", async function () {
57
+ var code = `
58
+ TEST_OUTPUT = __dirname;
59
+ `;
60
+
61
+ var output = await JsConfuser(code, {
62
+ target: "node",
63
+ globalConcealing: true,
64
+ });
65
+
66
+ expect(output).toContain("__dirname");
67
+
68
+ var TEST_OUTPUT;
69
+ eval(output);
70
+
71
+ expect(typeof TEST_OUTPUT).toStrictEqual("string");
72
+ });
73
+
74
+ test("Variant #5: Hide 'global' var, even if properties are modified", async () => {
75
+ var output = await JsConfuser(
76
+ `
77
+ TEST_GLOBAL_VARIANT_5_OUTPUT = global.TEST_GLOBAL_VARIANT_5_INPUT * 2;
78
+ `,
79
+ { target: "node", globalConcealing: true }
80
+ );
81
+
82
+ // Input should get transformed
83
+ expect(output).not.toContain("global['TEST_GLOBAL_VARIANT_5_INPUT");
84
+
85
+ // TEST_GLOBAL_VARIANT_5_OUTPUT should stay the same
86
+ expect(output).not.toContain("global['TEST_GLOBAL_VARIANT_5_OUTPUT");
87
+
88
+ (global as any).TEST_GLOBAL_VARIANT_5_INPUT = 50;
89
+ (global as any).TEST_GLOBAL_VARIANT_5_OUTPUT = 100;
90
+
91
+ eval(output);
92
+
93
+ expect((global as any).TEST_GLOBAL_VARIANT_5_OUTPUT).toStrictEqual(100);
94
+ });
95
+
96
+ test("Variant #6: Preserve __JS_CONFUSER_VAR__", async () => {
97
+ // Covers both defined and undefined case
98
+ var output = await JsConfuser(
99
+ `
100
+ var TEST_VARIABLE
101
+ TEST_OUTPUT = [__JS_CONFUSER_VAR__(TEST_OUTER_VARIABLE), __JS_CONFUSER_VAR__(TEST_VARIABLE)];
102
+ `,
103
+ {
104
+ target: "node",
105
+ globalConcealing: true,
106
+ }
107
+ );
108
+
109
+ expect(output).not.toContain("__JS_CONFUSER_VAR__");
110
+
111
+ var TEST_OUTPUT;
112
+ eval(output);
113
+
114
+ expect(TEST_OUTPUT).toStrictEqual(["TEST_OUTER_VARIABLE", "TEST_VARIABLE"]);
115
+ });
116
+
117
+ test("Variant #7: Custom callback option", async () => {
118
+ var namesCollected: string[] = [];
119
+
120
+ var output = await JsConfuser(
121
+ `
122
+ expect(true).toStrictEqual(true);
123
+
124
+ TEST_OUTPUT = true;
125
+ `,
126
+ {
127
+ target: "node",
128
+ globalConcealing: (name) => {
129
+ namesCollected.push(name);
130
+ return false;
131
+ },
132
+ }
133
+ );
134
+
135
+ expect(namesCollected).toContain("expect");
136
+ expect(namesCollected).not.toContain("TEST_OUTPUT");
137
+
138
+ var TEST_OUTPUT;
139
+ eval(output);
140
+
141
+ expect(TEST_OUTPUT).toStrictEqual(true);
142
+ });
@@ -1,3 +1,4 @@
1
+ import { predictableFunctionTag } from "../../../src/constants";
1
2
  import JsConfuser from "../../../src/index";
2
3
 
3
4
  test("Variant #1: Move variable 'y' to top", async () => {
@@ -212,3 +213,63 @@ test("Variant #9: Defined variable without an initializer", async () => {
212
213
  eval(output2);
213
214
  expect(TEST_OUTPUT).toStrictEqual(3);
214
215
  });
216
+
217
+ test("Variant #10: Move parameters to predictable function", async () => {
218
+ var code = `
219
+ function testFunction${predictableFunctionTag}_FN(){
220
+ var values = [10,20,35,"40", null]
221
+ var parseIntKey = "parseInt"
222
+ var output = 0
223
+ var utils = {
224
+ get parser${predictableFunctionTag}(){
225
+ var fn = (value)=>{
226
+ return global[parseIntKey](value)
227
+ }
228
+ return fn
229
+ },
230
+
231
+ set setter_fn${predictableFunctionTag}(newValue){
232
+ var fakeVar
233
+ }
234
+ }
235
+
236
+ class FakeClass {
237
+ constructor(){
238
+ }
239
+
240
+ get fakeGet${predictableFunctionTag}(){
241
+ var fakeVar
242
+ }
243
+ }
244
+
245
+ for(var value of values) {
246
+ switch(value){
247
+ case null:
248
+ break;
249
+
250
+ default:
251
+ var stringifiedValue = "" + value
252
+ var parsedValue = utils.parser${predictableFunctionTag}(stringifiedValue)
253
+ output += parsedValue;
254
+ break;
255
+ }
256
+ }
257
+
258
+ return output
259
+ }
260
+
261
+ TEST_OUTPUT = testFunction${predictableFunctionTag}_FN()
262
+ `;
263
+
264
+ var output = await JsConfuser(code, {
265
+ target: "node",
266
+ movedDeclarations: true,
267
+ });
268
+
269
+ expect(output).toContain("_FN(values");
270
+
271
+ var TEST_OUTPUT;
272
+ eval(output);
273
+
274
+ expect(TEST_OUTPUT).toStrictEqual(105);
275
+ });