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.
- package/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import JsConfuser from "../../../src/index";
|
|
2
2
|
|
|
3
|
-
test("Variant #1:
|
|
3
|
+
test("Variant #1: Obfuscate code and still execute in correct order", async () => {
|
|
4
4
|
var code = `
|
|
5
5
|
var array = [];
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ test("Variant #1: Execute in the correct order (ControlFlowFlattening)", async (
|
|
|
15
15
|
array.push(9);
|
|
16
16
|
array.push(10);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
TEST_OUTPUT = array;
|
|
19
19
|
`;
|
|
20
20
|
|
|
21
21
|
var output = await JsConfuser(code, {
|
|
@@ -23,14 +23,17 @@ test("Variant #1: Execute in the correct order (ControlFlowFlattening)", async (
|
|
|
23
23
|
controlFlowFlattening: true,
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
26
|
+
// Ensure Control Flow Flattening applied
|
|
27
|
+
expect(output).toContain("while");
|
|
29
28
|
|
|
29
|
+
// Ensure the output is the exact same
|
|
30
|
+
var TEST_OUTPUT;
|
|
30
31
|
eval(output);
|
|
32
|
+
|
|
33
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
31
34
|
});
|
|
32
35
|
|
|
33
|
-
test("Variant #2: Obfuscate for loops
|
|
36
|
+
test("Variant #2: Obfuscate for loops", async () => {
|
|
34
37
|
var code = `
|
|
35
38
|
var array = [];
|
|
36
39
|
|
|
@@ -38,7 +41,7 @@ test("Variant #2: Obfuscate for loops (ControlFlowObfuscation)", async () => {
|
|
|
38
41
|
array.push(i);
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
TEST_OUTPUT = array;
|
|
42
45
|
`;
|
|
43
46
|
|
|
44
47
|
var output = await JsConfuser(code, {
|
|
@@ -46,16 +49,20 @@ test("Variant #2: Obfuscate for loops (ControlFlowObfuscation)", async () => {
|
|
|
46
49
|
controlFlowFlattening: true,
|
|
47
50
|
});
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
// Ensure Control Flow Flattening applied
|
|
53
|
+
expect(output).toContain("while");
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
// Ensure the for statement got flattened
|
|
56
|
+
expect(output).not.toContain("for");
|
|
57
|
+
|
|
58
|
+
// Ensure the output is the exact same
|
|
59
|
+
var TEST_OUTPUT;
|
|
54
60
|
|
|
55
61
|
eval(output);
|
|
62
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
56
63
|
});
|
|
57
64
|
|
|
58
|
-
test("Variant #3: Obfuscate while loops
|
|
65
|
+
test("Variant #3: Obfuscate while loops", async () => {
|
|
59
66
|
var code = `
|
|
60
67
|
var array = [];
|
|
61
68
|
var i = 1;
|
|
@@ -65,7 +72,7 @@ test("Variant #3: Obfuscate while loops (ControlFlowObfuscation)", async () => {
|
|
|
65
72
|
i++
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
TEST_OUTPUT = array;
|
|
69
76
|
`;
|
|
70
77
|
|
|
71
78
|
var output = await JsConfuser(code, {
|
|
@@ -73,13 +80,14 @@ test("Variant #3: Obfuscate while loops (ControlFlowObfuscation)", async () => {
|
|
|
73
80
|
controlFlowFlattening: true,
|
|
74
81
|
});
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
function input(array) {
|
|
79
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
80
|
-
}
|
|
83
|
+
// Ensure Control Flow Flattening applied
|
|
84
|
+
expect(output).toContain("while");
|
|
81
85
|
|
|
86
|
+
// Ensure the output is the exact same
|
|
87
|
+
var TEST_OUTPUT;
|
|
82
88
|
eval(output);
|
|
89
|
+
|
|
90
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
83
91
|
});
|
|
84
92
|
|
|
85
93
|
test("Variant #4: Work with break statements", async () => {
|
|
@@ -94,7 +102,7 @@ test("Variant #4: Work with break statements", async () => {
|
|
|
94
102
|
TEST_ARRAY.push(i);
|
|
95
103
|
}
|
|
96
104
|
|
|
97
|
-
|
|
105
|
+
TEST_OUTPUT = TEST_ARRAY;
|
|
98
106
|
`;
|
|
99
107
|
|
|
100
108
|
var output = await JsConfuser(code, {
|
|
@@ -102,19 +110,20 @@ test("Variant #4: Work with break statements", async () => {
|
|
|
102
110
|
controlFlowFlattening: true,
|
|
103
111
|
});
|
|
104
112
|
|
|
113
|
+
// Ensure Control Flow Flattening applied
|
|
105
114
|
expect(output).toContain("switch");
|
|
106
115
|
expect(output).toContain("while");
|
|
107
116
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
117
|
+
// Ensure the output is the exact same
|
|
118
|
+
var TEST_OUTPUT;
|
|
111
119
|
|
|
112
120
|
eval(output);
|
|
121
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
113
122
|
});
|
|
114
123
|
|
|
115
|
-
test("Variant #5: Don't obfuscate code with `let` (Lexically bound variables
|
|
124
|
+
test("Variant #5: Don't obfuscate code with `let` (Lexically bound variables)", async () => {
|
|
116
125
|
var code = `
|
|
117
|
-
|
|
126
|
+
let array = [];
|
|
118
127
|
|
|
119
128
|
array.push(1);
|
|
120
129
|
array.push(2);
|
|
@@ -127,7 +136,7 @@ test("Variant #5: Don't obfuscate code with `let` (Lexically bound variables, Co
|
|
|
127
136
|
array.push(9);
|
|
128
137
|
array.push(10);
|
|
129
138
|
|
|
130
|
-
|
|
139
|
+
TEST_OUTPUT = array;
|
|
131
140
|
`;
|
|
132
141
|
|
|
133
142
|
var output = await JsConfuser(code, {
|
|
@@ -135,17 +144,24 @@ test("Variant #5: Don't obfuscate code with `let` (Lexically bound variables, Co
|
|
|
135
144
|
controlFlowFlattening: true,
|
|
136
145
|
});
|
|
137
146
|
|
|
138
|
-
|
|
147
|
+
// Ensure Control Flow Flattening did NOT apply here
|
|
148
|
+
expect(output).not.toContain("while");
|
|
149
|
+
|
|
150
|
+
// Ensure the output is the exact same
|
|
151
|
+
var TEST_OUTPUT;
|
|
152
|
+
eval(output);
|
|
153
|
+
|
|
154
|
+
expect(TEST_OUTPUT).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
139
155
|
});
|
|
140
156
|
|
|
141
|
-
test("Variant #6: Don't obfuscate code with `let` (Lexically bound variables
|
|
157
|
+
test("Variant #6: Don't obfuscate code with `let` (Lexically bound variables)", async () => {
|
|
142
158
|
var code = `
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
var array=[];
|
|
160
|
+
for ( let i =1; i <= 10; i++ ) {
|
|
161
|
+
array.push(i);
|
|
162
|
+
}
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
TEST_OUTPUT = array;
|
|
149
165
|
`;
|
|
150
166
|
|
|
151
167
|
var output = await JsConfuser(code, {
|
|
@@ -153,10 +169,17 @@ test("Variant #6: Don't obfuscate code with `let` (Lexically bound variables, Co
|
|
|
153
169
|
controlFlowFlattening: true,
|
|
154
170
|
});
|
|
155
171
|
|
|
156
|
-
|
|
172
|
+
// Ensure Control Flow Flattening did NOT apply here
|
|
173
|
+
expect(output).not.toContain("while");
|
|
174
|
+
|
|
175
|
+
// Ensure the output is the exact same
|
|
176
|
+
var TEST_OUTPUT;
|
|
177
|
+
eval(output);
|
|
178
|
+
|
|
179
|
+
expect(TEST_OUTPUT).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
157
180
|
});
|
|
158
181
|
|
|
159
|
-
test("Variant #7:
|
|
182
|
+
test("Variant #7: Allow option to be set a percentage threshold", async () => {
|
|
160
183
|
var code = `
|
|
161
184
|
var array = [];
|
|
162
185
|
var i = 1;
|
|
@@ -166,7 +189,7 @@ test("Variant #7: Accept percentages", async () => {
|
|
|
166
189
|
i++
|
|
167
190
|
}
|
|
168
191
|
|
|
169
|
-
|
|
192
|
+
TEST_OUTPUT = array;
|
|
170
193
|
`;
|
|
171
194
|
|
|
172
195
|
var output = await JsConfuser(code, {
|
|
@@ -174,27 +197,48 @@ test("Variant #7: Accept percentages", async () => {
|
|
|
174
197
|
controlFlowFlattening: 0.5,
|
|
175
198
|
});
|
|
176
199
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
function input(array) {
|
|
181
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
182
|
-
}
|
|
200
|
+
// Ensure the output is the exact same
|
|
201
|
+
var TEST_OUTPUT;
|
|
183
202
|
|
|
184
203
|
eval(output);
|
|
204
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
185
205
|
});
|
|
186
206
|
|
|
187
|
-
|
|
207
|
+
test("Variant #8: Work when obfuscated multiple times", async () => {
|
|
188
208
|
var code = `
|
|
189
209
|
var array = [];
|
|
190
|
-
var i = 1;
|
|
191
210
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
211
|
+
switch(true){
|
|
212
|
+
case true: // Always true
|
|
213
|
+
if(true){ // Always true
|
|
214
|
+
var i;
|
|
196
215
|
|
|
197
|
-
|
|
216
|
+
for ( i = 1; i <= 10; i++ ) {
|
|
217
|
+
if(typeof i === "number") { // Always true
|
|
218
|
+
array.push(i);
|
|
219
|
+
|
|
220
|
+
var filler1;
|
|
221
|
+
var filler2;
|
|
222
|
+
var filler3;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
var filler1;
|
|
226
|
+
var filler2;
|
|
227
|
+
var filler3;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var filler1;
|
|
231
|
+
var filler2;
|
|
232
|
+
var filler3;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
var filler1;
|
|
236
|
+
var filler2;
|
|
237
|
+
var filler3;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
TEST_OUTPUT = array;
|
|
198
242
|
`; // [1,2,3,4,5,6,7,8,9,10]
|
|
199
243
|
|
|
200
244
|
var output = await JsConfuser(code, {
|
|
@@ -202,19 +246,19 @@ it("Variant #8: Work when obfuscated multiple times", async () => {
|
|
|
202
246
|
controlFlowFlattening: true,
|
|
203
247
|
});
|
|
204
248
|
|
|
249
|
+
// Ensure Control Flow Flattening applied
|
|
250
|
+
expect(output).toContain("while");
|
|
251
|
+
|
|
205
252
|
var doublyObfuscated = await JsConfuser(output, {
|
|
206
253
|
target: "node",
|
|
207
254
|
controlFlowFlattening: true,
|
|
208
255
|
});
|
|
209
256
|
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
function input(array) {
|
|
214
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
215
|
-
}
|
|
257
|
+
// Ensure the output is the exact same
|
|
258
|
+
var TEST_OUTPUT;
|
|
216
259
|
|
|
217
260
|
eval(doublyObfuscated);
|
|
261
|
+
expect(TEST_OUTPUT).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
218
262
|
});
|
|
219
263
|
|
|
220
264
|
test("Variant #9: Don't entangle floats or NaN", async () => {
|
|
@@ -539,43 +583,36 @@ test("Variant #17: Flatten with infinite for loop and break", async () => {
|
|
|
539
583
|
expect(TEST_ARRAY).toStrictEqual([1, 2, 3, 4, 5]);
|
|
540
584
|
});
|
|
541
585
|
|
|
542
|
-
test("Variant #
|
|
586
|
+
test("Variant #20: Work with redefined functions", async () => {
|
|
543
587
|
var output = await JsConfuser(
|
|
544
588
|
`
|
|
545
|
-
|
|
546
|
-
var x = -1;
|
|
589
|
+
var counter = 0;
|
|
547
590
|
function increment(){
|
|
548
|
-
|
|
549
|
-
return x;
|
|
550
|
-
}
|
|
591
|
+
counter++;
|
|
551
592
|
|
|
552
|
-
|
|
593
|
+
if(counter == 3) {
|
|
594
|
+
increment = () => { counter = "Correct Value" }
|
|
595
|
+
}
|
|
596
|
+
}
|
|
553
597
|
|
|
554
|
-
|
|
598
|
+
increment(); // 1
|
|
599
|
+
increment(); // 2
|
|
600
|
+
increment(); // 3
|
|
555
601
|
|
|
556
|
-
|
|
602
|
+
var originalIncrement = increment;
|
|
603
|
+
increment = ()=>{};
|
|
557
604
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
element3 = increment();
|
|
605
|
+
increment(); // 3
|
|
606
|
+
increment(); // 3
|
|
607
|
+
increment(); // 3
|
|
563
608
|
|
|
564
|
-
|
|
609
|
+
increment = undefined;
|
|
565
610
|
|
|
566
|
-
|
|
611
|
+
increment = typeof increment === "undefined" ? originalIncrement : 0;
|
|
567
612
|
|
|
568
|
-
|
|
569
|
-
element1,
|
|
570
|
-
element2,
|
|
571
|
-
element3,
|
|
572
|
-
]
|
|
613
|
+
increment(); // "Correct Value"
|
|
573
614
|
|
|
574
|
-
|
|
575
|
-
var fillerExpr2;
|
|
576
|
-
var fillerExpr3;
|
|
577
|
-
var fillerExpr4;
|
|
578
|
-
var fillerExpr5;
|
|
615
|
+
TEST_OUTPUT = counter;
|
|
579
616
|
`,
|
|
580
617
|
{
|
|
581
618
|
target: "node",
|
|
@@ -583,38 +620,59 @@ test("Variant #18: Flatten certain functions", async () => {
|
|
|
583
620
|
}
|
|
584
621
|
);
|
|
585
622
|
|
|
586
|
-
|
|
587
|
-
expect(output).
|
|
623
|
+
// Ensure Control Flow Flattening applied
|
|
624
|
+
expect(output).toContain("while");
|
|
588
625
|
|
|
589
|
-
var
|
|
626
|
+
var TEST_OUTPUT;
|
|
590
627
|
|
|
591
628
|
eval(output);
|
|
592
|
-
expect(
|
|
629
|
+
expect(TEST_OUTPUT).toStrictEqual("Correct Value");
|
|
593
630
|
});
|
|
594
631
|
|
|
595
|
-
|
|
632
|
+
// https://github.com/MichaelXF/js-confuser/issues/70
|
|
633
|
+
test("Variant #21: Don't move Import Declarations", async () => {
|
|
596
634
|
var output = await JsConfuser(
|
|
597
635
|
`
|
|
598
|
-
|
|
599
|
-
var
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
636
|
+
import {createHash} from "crypto";
|
|
637
|
+
var inputString = "Hash this string";
|
|
638
|
+
var hashed = createHash("sha256").update(inputString).digest("hex");
|
|
639
|
+
TEST_OUTPUT = hashed;
|
|
640
|
+
`,
|
|
641
|
+
{
|
|
642
|
+
target: "node",
|
|
643
|
+
controlFlowFlattening: true,
|
|
603
644
|
}
|
|
645
|
+
);
|
|
604
646
|
|
|
605
|
-
|
|
647
|
+
// Ensure Control Flow FLattening was applied
|
|
648
|
+
expect(output).toContain("switch");
|
|
606
649
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
increment(),
|
|
610
|
-
increment()
|
|
611
|
-
]
|
|
650
|
+
// Ensure the import declaration wasn't moved
|
|
651
|
+
expect(output.startsWith("import")).toStrictEqual(true);
|
|
612
652
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
653
|
+
// Convert to runnable code
|
|
654
|
+
output = output.replace(
|
|
655
|
+
`import{createHash}from'crypto';`,
|
|
656
|
+
"const {createHash}=require('crypto');"
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
var TEST_OUTPUT = "";
|
|
660
|
+
|
|
661
|
+
eval(output);
|
|
662
|
+
|
|
663
|
+
expect(TEST_OUTPUT).toStrictEqual(
|
|
664
|
+
"1cac63f39fd68d8c531f27b807610fb3d50f0fc3f186995767fb6316e7200a3e"
|
|
665
|
+
);
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// https://github.com/MichaelXF/js-confuser/issues/81
|
|
669
|
+
test("Variant #22: Don't break typeof expression", async () => {
|
|
670
|
+
var output = await JsConfuser(
|
|
671
|
+
`
|
|
672
|
+
TEST_OUTPUT = false;
|
|
673
|
+
if(typeof nonExistentVariable === "undefined") {
|
|
674
|
+
TEST_OUTPUT = true;
|
|
675
|
+
}
|
|
618
676
|
`,
|
|
619
677
|
{
|
|
620
678
|
target: "node",
|
|
@@ -622,65 +680,377 @@ test("Variant #19: Don't flatten non-extractable functions", async () => {
|
|
|
622
680
|
}
|
|
623
681
|
);
|
|
624
682
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
var TEST_ARRAY;
|
|
683
|
+
var TEST_OUTPUT;
|
|
628
684
|
|
|
629
685
|
eval(output);
|
|
630
|
-
|
|
686
|
+
|
|
687
|
+
expect(TEST_OUTPUT).toStrictEqual(true);
|
|
631
688
|
});
|
|
632
689
|
|
|
633
|
-
test("Variant #
|
|
690
|
+
test("Variant #23: Don't break Super calls", async () => {
|
|
634
691
|
var output = await JsConfuser(
|
|
635
692
|
`
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
x++;
|
|
640
|
-
return x;
|
|
693
|
+
class MyClass1 {
|
|
694
|
+
constructor(val){
|
|
695
|
+
this.val = val;
|
|
641
696
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
697
|
+
}
|
|
698
|
+
class MyClass2 extends MyClass1 {
|
|
699
|
+
constructor(){
|
|
700
|
+
super(10);
|
|
701
|
+
|
|
702
|
+
// Ensure ControlFlowFlattening applies here
|
|
703
|
+
var filler1;
|
|
704
|
+
var filler2;
|
|
705
|
+
var filler3;
|
|
646
706
|
}
|
|
707
|
+
}
|
|
647
708
|
|
|
648
|
-
|
|
709
|
+
var myObject = new MyClass2();
|
|
710
|
+
TEST_OUTPUT = myObject.val; // 10
|
|
711
|
+
`,
|
|
712
|
+
{ target: "node", controlFlowFlattening: true }
|
|
713
|
+
);
|
|
649
714
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
increment(),
|
|
653
|
-
increment()
|
|
654
|
-
]
|
|
715
|
+
var TEST_OUTPUT;
|
|
716
|
+
eval(output);
|
|
655
717
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
{
|
|
663
|
-
|
|
664
|
-
|
|
718
|
+
expect(TEST_OUTPUT).toStrictEqual(10);
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
test("Variant #24: Nested function-calls with labeled breaks/continues", async () => {
|
|
722
|
+
var code = `
|
|
723
|
+
function myFunction(){
|
|
724
|
+
function x( STOP_VALUE ){
|
|
725
|
+
function y(){
|
|
726
|
+
function dead(){
|
|
727
|
+
var STOP_VALUE = 3;
|
|
728
|
+
}
|
|
729
|
+
function z(){
|
|
730
|
+
a: for(var i = 0; i < 10; i++) {
|
|
731
|
+
if (i == STOP_VALUE) {
|
|
732
|
+
var counter = 0;
|
|
733
|
+
b: for ( var j = 0; j < 10; j++ ) {
|
|
734
|
+
if(j == 4) {
|
|
735
|
+
counter -= 50;
|
|
736
|
+
continue b;
|
|
737
|
+
}
|
|
738
|
+
counter++;
|
|
739
|
+
if(j == 8) {
|
|
740
|
+
break a;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
var filler1;
|
|
747
|
+
var filler2;
|
|
748
|
+
var filler3;
|
|
749
|
+
return i + j + counter;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
var filler1;
|
|
753
|
+
var filler2;
|
|
754
|
+
var filler3;
|
|
755
|
+
return z();
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
var filler1;
|
|
759
|
+
var filler2;
|
|
760
|
+
var filler3;
|
|
761
|
+
return y();
|
|
665
762
|
}
|
|
763
|
+
|
|
764
|
+
var filler1;
|
|
765
|
+
var filler2;
|
|
766
|
+
var filler3;
|
|
767
|
+
return x( 1 );
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
var x = myFunction();
|
|
771
|
+
|
|
772
|
+
TEST_OUTPUT = x;`;
|
|
773
|
+
|
|
774
|
+
var output = await JsConfuser(code, {
|
|
775
|
+
target: "node",
|
|
776
|
+
controlFlowFlattening: true,
|
|
777
|
+
renameVariables: true,
|
|
778
|
+
identifierGenerator: "mangled",
|
|
779
|
+
stack: true,
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
var TEST_OUTPUT;
|
|
783
|
+
eval(output);
|
|
784
|
+
|
|
785
|
+
expect(TEST_OUTPUT).toStrictEqual(-33);
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
test("Variant #25: Don't break call expressions to bound functions", async () => {
|
|
789
|
+
var code = `
|
|
790
|
+
var array = [];
|
|
791
|
+
array.push(1);
|
|
792
|
+
array.push(2);
|
|
793
|
+
array.push(3);
|
|
794
|
+
array.push(4);
|
|
795
|
+
array.push(5);
|
|
796
|
+
|
|
797
|
+
TEST_OUTPUT = array;
|
|
798
|
+
`;
|
|
799
|
+
|
|
800
|
+
var output = await JsConfuser(code, {
|
|
801
|
+
target: "node",
|
|
802
|
+
controlFlowFlattening: true,
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
// Ensure Control Flow Flattening applied
|
|
806
|
+
expect(output).toContain("while");
|
|
807
|
+
|
|
808
|
+
var TEST_OUTPUT;
|
|
809
|
+
eval(output);
|
|
810
|
+
|
|
811
|
+
expect(TEST_OUTPUT).toStrictEqual([1, 2, 3, 4, 5]);
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
test("Variant #26: Add opaque predicates and still work", async () => {
|
|
815
|
+
var output = await JsConfuser(
|
|
816
|
+
`
|
|
817
|
+
TEST_OUTPUT = [];
|
|
818
|
+
if(true) TEST_OUTPUT.push(1);
|
|
819
|
+
else TEST_OUTPUT.push("Incorrect If Statement")
|
|
820
|
+
|
|
821
|
+
switch(true){
|
|
822
|
+
case true: TEST_OUTPUT.push(2); break;
|
|
823
|
+
default:
|
|
824
|
+
TEST_OUTPUT.push("Incorrect Switch")
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
TEST_OUTPUT.push( true ? 3 : "Incorrect Conditional Statement" );
|
|
828
|
+
`,
|
|
829
|
+
{ target: "node", controlFlowFlattening: true }
|
|
666
830
|
);
|
|
667
831
|
|
|
668
|
-
expect(output).
|
|
832
|
+
expect(output).toContain("while");
|
|
833
|
+
var TEST_OUTPUT = [];
|
|
669
834
|
|
|
670
|
-
|
|
835
|
+
eval(output);
|
|
671
836
|
|
|
837
|
+
expect(TEST_OUTPUT).toStrictEqual([1, 2, 3]);
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
test("Variant #27: Work on async/generator functions", async () => {
|
|
841
|
+
var output = await JsConfuser(
|
|
842
|
+
`
|
|
843
|
+
"use strict";
|
|
844
|
+
async function myAsyncFunction(){
|
|
845
|
+
await (1);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
function* myGeneratorFunction(){
|
|
849
|
+
yield "Correct Value";
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
var x = myAsyncFunction();
|
|
853
|
+
var generatorObject = myGeneratorFunction();
|
|
854
|
+
|
|
855
|
+
TEST_OUTPUT = generatorObject.next().value;
|
|
856
|
+
|
|
857
|
+
var fillerVar1;
|
|
858
|
+
var fillerVar2;
|
|
859
|
+
var fillerVar3;
|
|
860
|
+
`,
|
|
861
|
+
{ target: "node", controlFlowFlattening: true }
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
// Ensure Control Flow Flattening applied
|
|
865
|
+
expect(output).toContain("while");
|
|
866
|
+
|
|
867
|
+
var TEST_OUTPUT;
|
|
672
868
|
eval(output);
|
|
673
|
-
|
|
869
|
+
|
|
870
|
+
expect(TEST_OUTPUT).toStrictEqual("Correct Value");
|
|
674
871
|
});
|
|
675
872
|
|
|
676
|
-
|
|
677
|
-
|
|
873
|
+
test("Variant #28: Don't break update expressions", async () => {
|
|
874
|
+
var code = `
|
|
875
|
+
var counter = 0;
|
|
876
|
+
|
|
877
|
+
counter++; // 1
|
|
878
|
+
counter++; // 2
|
|
879
|
+
counter++; // 3
|
|
880
|
+
counter++; // 4
|
|
881
|
+
counter++; // 5
|
|
882
|
+
counter++; // 6
|
|
883
|
+
counter++; // 7
|
|
884
|
+
counter++; // 8
|
|
885
|
+
counter++; // 9
|
|
886
|
+
counter++; // 10
|
|
887
|
+
|
|
888
|
+
TEST_OUTPUT = counter;
|
|
889
|
+
`;
|
|
890
|
+
|
|
891
|
+
var output = await JsConfuser(code, {
|
|
892
|
+
target: "node",
|
|
893
|
+
controlFlowFlattening: true,
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
// Ensure Control Flow Flattening applied
|
|
897
|
+
expect(output).toContain("while");
|
|
898
|
+
|
|
899
|
+
var TEST_OUTPUT;
|
|
900
|
+
eval(output);
|
|
901
|
+
|
|
902
|
+
expect(TEST_OUTPUT).toStrictEqual(10);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
test("Variant #29: Nested labeled break and continue statements with RGF enabled", async () => {
|
|
906
|
+
var code = `
|
|
907
|
+
function labeledBreaksAndContinues() {
|
|
908
|
+
var flag = true;
|
|
909
|
+
|
|
910
|
+
label_1: for (var i = 0; i < 20; i++) {
|
|
911
|
+
b: switch (i) {
|
|
912
|
+
case 15:
|
|
913
|
+
c: do {
|
|
914
|
+
if (i !== 15) {
|
|
915
|
+
break c;
|
|
916
|
+
}
|
|
917
|
+
flag = true;
|
|
918
|
+
|
|
919
|
+
break label_1;
|
|
920
|
+
|
|
921
|
+
var fillerVar1;
|
|
922
|
+
var fillerVar2;
|
|
923
|
+
var fillerVar3;
|
|
924
|
+
} while (i == 15);
|
|
925
|
+
|
|
926
|
+
break;
|
|
927
|
+
|
|
928
|
+
case 10:
|
|
929
|
+
continue label_1;
|
|
930
|
+
|
|
931
|
+
default:
|
|
932
|
+
flag = false;
|
|
933
|
+
break b;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
var fillerVar1;
|
|
937
|
+
var fillerVar2;
|
|
938
|
+
var fillerVar3;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
var fillerVar1;
|
|
942
|
+
var fillerVar2;
|
|
943
|
+
var fillerVar3;
|
|
944
|
+
|
|
945
|
+
if (flag) {
|
|
946
|
+
return i;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
var fillerVar1;
|
|
951
|
+
var fillerVar2;
|
|
952
|
+
var fillerVar3;
|
|
953
|
+
|
|
954
|
+
TEST_OUTPUT = labeledBreaksAndContinues();
|
|
955
|
+
`; // This complex code produces the value of 15
|
|
956
|
+
|
|
957
|
+
var output = await JsConfuser(code, {
|
|
958
|
+
target: "node",
|
|
959
|
+
controlFlowFlattening: true,
|
|
960
|
+
rgf: true,
|
|
961
|
+
renameVariables: true,
|
|
962
|
+
identifierGenerator: "mangled",
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
// Run the code
|
|
966
|
+
var TEST_OUTPUT;
|
|
967
|
+
eval(output);
|
|
968
|
+
|
|
969
|
+
expect(TEST_OUTPUT).toStrictEqual(15);
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
test("Variant #30: Obfuscate switch statements", async () => {
|
|
678
973
|
var output = await JsConfuser(
|
|
679
974
|
`
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
975
|
+
switch("DON'T CHANGE ME"){} // Empty switch for testing
|
|
976
|
+
|
|
977
|
+
switch(true){
|
|
978
|
+
case 0:
|
|
979
|
+
TEST_OUTPUT = "Incorrect Value (1)";
|
|
980
|
+
break
|
|
981
|
+
|
|
982
|
+
case true:
|
|
983
|
+
TEST_OUTPUT = "First Correct Value";
|
|
984
|
+
break;
|
|
985
|
+
|
|
986
|
+
case 1:
|
|
987
|
+
case 2:
|
|
988
|
+
case 3:
|
|
989
|
+
case false:
|
|
990
|
+
TEST_OUTPUT = "Incorrect Value (2)";
|
|
991
|
+
break;
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
switch(TEST_OUTPUT){
|
|
995
|
+
case true:
|
|
996
|
+
TEST_OUTPUT = "Incorrect Value (3)";
|
|
997
|
+
break;
|
|
998
|
+
|
|
999
|
+
case false:
|
|
1000
|
+
TEST_OUTPUT = "Incorrect Value (4)";
|
|
1001
|
+
break;
|
|
1002
|
+
|
|
1003
|
+
default:
|
|
1004
|
+
TEST_OUTPUT = "Second Correct Value";
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
switch(true){
|
|
1008
|
+
case false:
|
|
1009
|
+
throw new Error();
|
|
1010
|
+
break;
|
|
1011
|
+
|
|
1012
|
+
default:
|
|
1013
|
+
TEST_OUTPUT = "Incorrect Value";
|
|
1014
|
+
|
|
1015
|
+
case true:
|
|
1016
|
+
TEST_OUTPUT = "Third Correct Value";
|
|
1017
|
+
// Fall-through test
|
|
1018
|
+
case 10:
|
|
1019
|
+
TEST_OUTPUT = "Fourth Correct Value";
|
|
1020
|
+
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
switch(true){
|
|
1024
|
+
default:
|
|
1025
|
+
throw new Error("NO");
|
|
1026
|
+
break;
|
|
1027
|
+
case true:
|
|
1028
|
+
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
var hitDefault = false;
|
|
1033
|
+
|
|
1034
|
+
switch(true){
|
|
1035
|
+
case 1:
|
|
1036
|
+
case 2:
|
|
1037
|
+
|
|
1038
|
+
default:
|
|
1039
|
+
hitDefault = true;
|
|
1040
|
+
break;
|
|
1041
|
+
|
|
1042
|
+
case 3:
|
|
1043
|
+
case 4:
|
|
1044
|
+
break;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
if(!hitDefault) {
|
|
1048
|
+
throw new Error("Did not hit default case");
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
var filler1;
|
|
1052
|
+
var filler2;
|
|
1053
|
+
var filler3;
|
|
684
1054
|
`,
|
|
685
1055
|
{
|
|
686
1056
|
target: "node",
|
|
@@ -688,45 +1058,217 @@ test("Variant #21: Don't move Import Declarations", async () => {
|
|
|
688
1058
|
}
|
|
689
1059
|
);
|
|
690
1060
|
|
|
691
|
-
// Ensure Control Flow
|
|
692
|
-
expect(output).toContain("
|
|
1061
|
+
// Ensure Control Flow Flattening applied
|
|
1062
|
+
expect(output).toContain("while");
|
|
693
1063
|
|
|
694
|
-
// Ensure
|
|
695
|
-
expect(output.
|
|
1064
|
+
// Ensure switch-statements got changed
|
|
1065
|
+
expect(output).not.toContain("switch(true)");
|
|
1066
|
+
expect(output).not.toContain("switch(TEST_OUTPUT)");
|
|
696
1067
|
|
|
697
|
-
|
|
698
|
-
output
|
|
699
|
-
|
|
700
|
-
|
|
1068
|
+
var TEST_OUTPUT;
|
|
1069
|
+
eval(output);
|
|
1070
|
+
|
|
1071
|
+
expect(TEST_OUTPUT).toStrictEqual("Fourth Correct Value");
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
test("Variant #31: Don't break nested function calls", async () => {
|
|
1075
|
+
var output = await JsConfuser(
|
|
1076
|
+
`
|
|
1077
|
+
var i;
|
|
1078
|
+
var counter = 0;
|
|
1079
|
+
for(i = 0; i < 10;) {
|
|
1080
|
+
function logger(x){
|
|
1081
|
+
counter++;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
logger("Hello World");
|
|
1085
|
+
i++
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
TEST_OUTPUT = counter;
|
|
1089
|
+
`,
|
|
1090
|
+
{ target: "node", controlFlowFlattening: true }
|
|
701
1091
|
);
|
|
702
1092
|
|
|
703
|
-
|
|
1093
|
+
expect(output).toContain("while");
|
|
704
1094
|
|
|
1095
|
+
var TEST_OUTPUT;
|
|
705
1096
|
eval(output);
|
|
706
1097
|
|
|
707
|
-
expect(TEST_OUTPUT).toStrictEqual(
|
|
708
|
-
|
|
1098
|
+
expect(TEST_OUTPUT).toStrictEqual(10);
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
test("Variant #32: Don't break same name function calls", async () => {
|
|
1102
|
+
var output = await JsConfuser(
|
|
1103
|
+
`
|
|
1104
|
+
var counter = 0;
|
|
1105
|
+
|
|
1106
|
+
function a(){
|
|
1107
|
+
// Outer a called
|
|
1108
|
+
counter *= 2;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
var i;
|
|
1112
|
+
|
|
1113
|
+
for(i = 0; i < 10;) {
|
|
1114
|
+
function a(){
|
|
1115
|
+
// Inner a called
|
|
1116
|
+
counter += 1;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
a(); // Inner a
|
|
1120
|
+
i++;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
a(); // Inner a, Outer a got renamed
|
|
1124
|
+
|
|
1125
|
+
TEST_OUTPUT = counter;
|
|
1126
|
+
`,
|
|
1127
|
+
{ target: "node", controlFlowFlattening: true }
|
|
709
1128
|
);
|
|
1129
|
+
|
|
1130
|
+
expect(output).toContain("while");
|
|
1131
|
+
|
|
1132
|
+
var TEST_OUTPUT;
|
|
1133
|
+
eval(output);
|
|
1134
|
+
|
|
1135
|
+
expect(TEST_OUTPUT).toStrictEqual(11);
|
|
710
1136
|
});
|
|
711
1137
|
|
|
712
|
-
|
|
713
|
-
test("Variant #22: Don't break typeof expression", async () => {
|
|
1138
|
+
test("Variant #33: Don't break same name function declarations that are not ran", async () => {
|
|
714
1139
|
var output = await JsConfuser(
|
|
715
1140
|
`
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
1141
|
+
var counter = 0;
|
|
1142
|
+
|
|
1143
|
+
function a(){
|
|
1144
|
+
// Outer a called
|
|
1145
|
+
counter += 1;
|
|
719
1146
|
}
|
|
720
|
-
|
|
721
|
-
{
|
|
722
|
-
|
|
723
|
-
|
|
1147
|
+
|
|
1148
|
+
for(var i = 0; i < 10;) {
|
|
1149
|
+
if(false){
|
|
1150
|
+
function a(){
|
|
1151
|
+
// Inner a called
|
|
1152
|
+
counter = 0;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
a(); // Outer a
|
|
1158
|
+
i++;
|
|
724
1159
|
}
|
|
1160
|
+
|
|
1161
|
+
a(); // Outer a
|
|
1162
|
+
|
|
1163
|
+
TEST_OUTPUT = counter;
|
|
1164
|
+
`,
|
|
1165
|
+
{ target: "node", controlFlowFlattening: true }
|
|
725
1166
|
);
|
|
726
1167
|
|
|
1168
|
+
expect(output).toContain("while");
|
|
1169
|
+
|
|
1170
|
+
var TEST_OUTPUT;
|
|
1171
|
+
eval(output);
|
|
1172
|
+
|
|
1173
|
+
expect(TEST_OUTPUT).toStrictEqual(11);
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
test("Variant #34: Flatten If, For, While, Do-while, and Switch statements multiple times", async () => {
|
|
1177
|
+
var code = `
|
|
1178
|
+
var counter = -1;
|
|
1179
|
+
|
|
1180
|
+
function incrementCounter(){
|
|
1181
|
+
counter++;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
if(false) {
|
|
1185
|
+
|
|
1186
|
+
} else {
|
|
1187
|
+
counter = 0;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
if(true){
|
|
1191
|
+
for(var i = 0; i < 10; i++) {
|
|
1192
|
+
switch(i){
|
|
1193
|
+
default:
|
|
1194
|
+
i++;
|
|
1195
|
+
break;
|
|
1196
|
+
|
|
1197
|
+
case 6:
|
|
1198
|
+
if(false){
|
|
1199
|
+
function incrementCounter(){
|
|
1200
|
+
throw new Error("Fake counter function");
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
while(i != 10) {
|
|
1205
|
+
incrementCounter();
|
|
1206
|
+
if(counter > 10) break;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
do {
|
|
1210
|
+
counter--;
|
|
1211
|
+
} while (counter > 5)
|
|
1212
|
+
// Fall-through
|
|
1213
|
+
case 8:
|
|
1214
|
+
counter *= 2;
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
} else {
|
|
1219
|
+
counter = "Incorrect Value";
|
|
1220
|
+
}
|
|
1221
|
+
if(false){
|
|
1222
|
+
counter = "Incorrect Value";
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
TEST_OUTPUT = counter;
|
|
1226
|
+
`;
|
|
1227
|
+
|
|
1228
|
+
var firstObfuscation = await JsConfuser(code, {
|
|
1229
|
+
target: "node",
|
|
1230
|
+
controlFlowFlattening: true,
|
|
1231
|
+
});
|
|
1232
|
+
var secondObfuscation = await JsConfuser(firstObfuscation, {
|
|
1233
|
+
target: "node",
|
|
1234
|
+
controlFlowFlattening: true,
|
|
1235
|
+
});
|
|
1236
|
+
|
|
727
1237
|
var TEST_OUTPUT;
|
|
1238
|
+
eval(secondObfuscation);
|
|
1239
|
+
|
|
1240
|
+
expect(TEST_OUTPUT).toStrictEqual(10);
|
|
1241
|
+
});
|
|
1242
|
+
|
|
1243
|
+
test("Variant #35: Redefined function declaration + variable declaration", async () => {
|
|
1244
|
+
var code = `
|
|
1245
|
+
function push(str){
|
|
1246
|
+
TEST_OUTPUT.push(str);
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
x();
|
|
1250
|
+
|
|
1251
|
+
var x = ()=>push("Top x");
|
|
1252
|
+
|
|
1253
|
+
x()
|
|
1254
|
+
|
|
1255
|
+
function x(){ push("Bottom x") }
|
|
728
1256
|
|
|
1257
|
+
if(true){
|
|
1258
|
+
|
|
1259
|
+
x();
|
|
1260
|
+
|
|
1261
|
+
function x(){ push("Nested x") }
|
|
1262
|
+
}
|
|
1263
|
+
`;
|
|
1264
|
+
|
|
1265
|
+
var output = await JsConfuser(code, {
|
|
1266
|
+
target: "node",
|
|
1267
|
+
controlFlowFlattening: true,
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
var TEST_OUTPUT = [];
|
|
729
1271
|
eval(output);
|
|
730
1272
|
|
|
731
|
-
expect(TEST_OUTPUT).toStrictEqual(
|
|
1273
|
+
expect(TEST_OUTPUT).toStrictEqual(["Bottom x", "Top x", "Nested x"]);
|
|
732
1274
|
});
|