js-confuser 1.7.1 → 1.7.2
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/CHANGELOG.md +38 -0
- package/README.md +12 -27
- package/dist/compiler.js +2 -8
- package/dist/constants.js +17 -10
- package/dist/index.js +7 -30
- package/dist/obfuscator.js +15 -62
- package/dist/options.js +21 -38
- package/dist/order.js +4 -7
- package/dist/parser.js +5 -13
- package/dist/precedence.js +6 -8
- package/dist/presets.js +4 -6
- package/dist/probability.js +13 -24
- package/dist/templates/bufferToString.js +100 -5
- package/dist/templates/crash.js +51 -9
- package/dist/templates/es5.js +125 -6
- package/dist/templates/functionLength.js +24 -6
- package/dist/templates/globals.js +9 -0
- package/dist/templates/template.js +71 -30
- package/dist/transforms/antiTooling.js +26 -22
- package/dist/transforms/calculator.js +18 -54
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
- package/dist/transforms/deadCode.js +528 -27
- package/dist/transforms/dispatcher.js +106 -110
- package/dist/transforms/es5/antiClass.js +70 -44
- package/dist/transforms/es5/antiDestructuring.js +14 -38
- package/dist/transforms/es5/antiES6Object.js +39 -48
- package/dist/transforms/es5/antiSpreadOperator.js +5 -14
- package/dist/transforms/es5/antiTemplate.js +10 -19
- package/dist/transforms/es5/es5.js +7 -40
- package/dist/transforms/extraction/classExtraction.js +83 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
- package/dist/transforms/extraction/objectExtraction.js +24 -56
- package/dist/transforms/finalizer.js +6 -20
- package/dist/transforms/flatten.js +51 -99
- package/dist/transforms/identifier/globalAnalysis.js +8 -26
- package/dist/transforms/identifier/globalConcealing.js +35 -54
- package/dist/transforms/identifier/movedDeclarations.js +66 -38
- package/dist/transforms/identifier/renameVariables.js +29 -68
- package/dist/transforms/identifier/variableAnalysis.js +21 -48
- package/dist/transforms/lock/antiDebug.js +20 -25
- package/dist/transforms/lock/integrity.js +48 -47
- package/dist/transforms/lock/lock.js +62 -113
- package/dist/transforms/minify.js +77 -108
- package/dist/transforms/opaquePredicates.js +11 -48
- package/dist/transforms/preparation.js +17 -50
- package/dist/transforms/renameLabels.js +5 -22
- package/dist/transforms/rgf.js +93 -69
- package/dist/transforms/shuffle.js +41 -46
- package/dist/transforms/stack.js +35 -98
- package/dist/transforms/string/encoding.js +73 -27
- package/dist/transforms/string/stringCompression.js +44 -68
- package/dist/transforms/string/stringConcealing.js +125 -134
- package/dist/transforms/string/stringEncoding.js +6 -26
- package/dist/transforms/string/stringSplitting.js +5 -30
- package/dist/transforms/transform.js +50 -100
- package/dist/traverse.js +11 -18
- package/dist/util/compare.js +27 -29
- package/dist/util/gen.js +32 -86
- package/dist/util/guard.js +0 -1
- package/dist/util/identifiers.js +9 -72
- package/dist/util/insert.js +27 -77
- package/dist/util/math.js +0 -3
- package/dist/util/object.js +3 -7
- package/dist/util/random.js +5 -36
- package/dist/util/scope.js +6 -3
- package/package.json +3 -3
- package/src/constants.ts +12 -0
- package/src/options.ts +13 -0
- package/src/order.ts +2 -2
- package/src/templates/bufferToString.ts +49 -11
- package/src/templates/functionLength.ts +21 -3
- package/src/templates/globals.ts +3 -0
- package/src/templates/template.ts +85 -25
- package/src/transforms/antiTooling.ts +33 -11
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
- package/src/transforms/deadCode.ts +0 -16
- package/src/transforms/dispatcher.ts +91 -69
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/extraction/classExtraction.ts +168 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
- package/src/transforms/extraction/objectExtraction.ts +4 -15
- package/src/transforms/flatten.ts +20 -5
- package/src/transforms/identifier/globalConcealing.ts +29 -65
- package/src/transforms/identifier/movedDeclarations.ts +90 -24
- package/src/transforms/minify.ts +27 -12
- package/src/transforms/rgf.ts +94 -5
- package/src/transforms/stack.ts +12 -3
- package/src/transforms/string/encoding.ts +85 -51
- package/src/transforms/string/stringCompression.ts +5 -8
- package/src/transforms/string/stringConcealing.ts +139 -113
- package/src/transforms/string/stringEncoding.ts +1 -2
- package/src/transforms/string/stringSplitting.ts +1 -2
- package/src/transforms/transform.ts +30 -1
- package/src/util/compare.ts +39 -5
- package/src/util/gen.ts +10 -3
- package/src/util/insert.ts +17 -0
- package/src/util/scope.ts +14 -2
- package/test/code/Cash.test.ts +10 -4
- package/test/code/StrictMode.src.js +65 -0
- package/test/code/StrictMode.test.js +37 -0
- package/test/compare.test.ts +62 -2
- package/test/options.test.ts +111 -55
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
- package/test/transforms/dispatcher.test.ts +55 -0
- package/test/transforms/extraction/classExtraction.test.ts +86 -0
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
- package/test/transforms/extraction/objectExtraction.test.ts +2 -0
- package/test/transforms/identifier/globalConcealing.test.ts +19 -0
- package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
- package/test/transforms/minify.test.ts +37 -0
- package/test/transforms/rgf.test.ts +50 -0
- package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
- package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
- package/dist/transforms/eval.js +0 -84
- package/dist/transforms/hexadecimalNumbers.js +0 -63
- package/dist/transforms/hideInitializingCode.js +0 -270
- package/dist/transforms/identifier/nameRecycling.js +0 -218
- package/dist/transforms/label.js +0 -67
- package/dist/transforms/preparation/nameConflicts.js +0 -116
- package/dist/transforms/preparation/preparation.js +0 -188
|
@@ -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:
|
|
15
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
10
16
|
);
|
|
11
17
|
|
|
12
|
-
expect(output).toContain("
|
|
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:
|
|
34
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
29
35
|
);
|
|
30
36
|
|
|
31
|
-
expect(output).toContain("
|
|
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:
|
|
53
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
48
54
|
);
|
|
49
55
|
|
|
50
|
-
expect(output).toContain("
|
|
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:
|
|
72
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
67
73
|
);
|
|
68
74
|
|
|
69
|
-
expect(output).toContain("
|
|
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:
|
|
92
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
87
93
|
);
|
|
88
94
|
|
|
89
|
-
expect(output).toContain("
|
|
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:
|
|
112
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
107
113
|
);
|
|
108
114
|
|
|
109
|
-
expect(output).toContain("
|
|
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:
|
|
136
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
131
137
|
);
|
|
132
138
|
|
|
133
|
-
expect(output).toContain("
|
|
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:
|
|
153
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
148
154
|
);
|
|
149
155
|
|
|
150
|
-
expect(output).toContain("
|
|
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:
|
|
170
|
+
{ target: "node", controlFlowFlattening: fakeEnabled }
|
|
165
171
|
);
|
|
166
172
|
|
|
167
|
-
expect(output).toContain(
|
|
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
|
});
|
|
@@ -51,3 +51,22 @@ 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
|
+
});
|
|
@@ -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
|
+
});
|
|
@@ -211,6 +211,16 @@ test("Variant #11: Shorten 'undefined' to 'void 0'", async () => {
|
|
|
211
211
|
});
|
|
212
212
|
|
|
213
213
|
expect(output2).toContain("var x={[void 0]:1}");
|
|
214
|
+
|
|
215
|
+
var output3 = await JsConfuser(
|
|
216
|
+
`try { var undefined; (undefined) = true } catch(e) {}`,
|
|
217
|
+
{
|
|
218
|
+
target: "node",
|
|
219
|
+
minify: true,
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
eval(output3);
|
|
214
224
|
});
|
|
215
225
|
|
|
216
226
|
test("Variant #11: Shorten 'Infinity' to 1/0", async () => {
|
|
@@ -536,3 +546,30 @@ test("Variant #27: Preserve function.length property", async () => {
|
|
|
536
546
|
|
|
537
547
|
expect(TEST_OUTPUT).toStrictEqual(6);
|
|
538
548
|
});
|
|
549
|
+
|
|
550
|
+
// https://github.com/MichaelXF/js-confuser/issues/125
|
|
551
|
+
test("Variant #28: Don't break destructuring assignment", async () => {
|
|
552
|
+
var output = await JsConfuser(
|
|
553
|
+
`
|
|
554
|
+
let objectSlice = [];
|
|
555
|
+
objectSlice.push({
|
|
556
|
+
a: 1,
|
|
557
|
+
b: 2,
|
|
558
|
+
c: 3,
|
|
559
|
+
})
|
|
560
|
+
for (let {
|
|
561
|
+
a,
|
|
562
|
+
b,
|
|
563
|
+
c
|
|
564
|
+
} of objectSlice) {
|
|
565
|
+
TEST_OUTPUT = a + b + c;
|
|
566
|
+
}
|
|
567
|
+
`,
|
|
568
|
+
{ target: "node", minify: true }
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
var TEST_OUTPUT;
|
|
572
|
+
eval(output);
|
|
573
|
+
|
|
574
|
+
expect(TEST_OUTPUT).toStrictEqual(6);
|
|
575
|
+
});
|
|
@@ -326,3 +326,53 @@ test("Variant #10: Configurable by custom function option", async () => {
|
|
|
326
326
|
expect(TEST_OUTPUT_1).toStrictEqual(false);
|
|
327
327
|
expect(TEST_OUTPUT_2).toStrictEqual(true);
|
|
328
328
|
});
|
|
329
|
+
|
|
330
|
+
test("Variant #11: Function containing function should both be changed", async function () {
|
|
331
|
+
var output = await JsConfuser(
|
|
332
|
+
`
|
|
333
|
+
function FunctionA(){
|
|
334
|
+
function FunctionB(){
|
|
335
|
+
var bVar = 10;
|
|
336
|
+
return bVar
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
var bFn = FunctionB;
|
|
340
|
+
var aVar = bFn();
|
|
341
|
+
return aVar + 1
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
TEST_OUTPUT = FunctionA();
|
|
345
|
+
`,
|
|
346
|
+
{ target: "node", rgf: true }
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
// 2 means one Function changed, 3 means two Functions changed
|
|
350
|
+
expect(output.split("new Function").length).toStrictEqual(3);
|
|
351
|
+
|
|
352
|
+
var TEST_OUTPUT;
|
|
353
|
+
eval(output);
|
|
354
|
+
|
|
355
|
+
expect(TEST_OUTPUT).toStrictEqual(11);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
test("Variant #12: Preserve Function.length", async function () {
|
|
359
|
+
var output = await JsConfuser(
|
|
360
|
+
`
|
|
361
|
+
function myFunction(a,b,c,d = ""){ // Function.length = 3
|
|
362
|
+
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
myFunction()
|
|
366
|
+
TEST_OUTPUT = myFunction.length
|
|
367
|
+
`,
|
|
368
|
+
{
|
|
369
|
+
target: "node",
|
|
370
|
+
rgf: true,
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
var TEST_OUTPUT;
|
|
375
|
+
eval(output);
|
|
376
|
+
|
|
377
|
+
expect(TEST_OUTPUT).toStrictEqual(3);
|
|
378
|
+
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _gen = require("../../util/gen");
|
|
9
|
-
|
|
10
|
-
var _transform = _interopRequireDefault(require("../transform"));
|
|
11
|
-
|
|
12
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
|
-
class ChoiceFlowObfuscation extends _transform.default {
|
|
15
|
-
constructor(o) {
|
|
16
|
-
super(o);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
match(object, parents) {
|
|
20
|
-
return object.type == "IfStatement";
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
transform(object, parents) {
|
|
24
|
-
return () => {
|
|
25
|
-
var body = parents[0];
|
|
26
|
-
var element = object;
|
|
27
|
-
|
|
28
|
-
if (parents[0].type == "LabeledStatement") {
|
|
29
|
-
body = parents[1];
|
|
30
|
-
element = parents[0];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
var before = [];
|
|
34
|
-
var isNested = parents[0].type == "IfStatement" && parents[0].alternate === object;
|
|
35
|
-
|
|
36
|
-
if (!isNested && (!Array.isArray(body) || body.indexOf(element) === -1)) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var result = this.getPlaceholder();
|
|
41
|
-
before.push((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(result)));
|
|
42
|
-
var yesBody = object.consequent ? object.consequent.type == "BlockStatement" ? [...object.consequent.body] : [object.consequent] : [];
|
|
43
|
-
yesBody.unshift((0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(result), (0, _gen.Literal)(1))));
|
|
44
|
-
var noBody = object.alternate ? object.alternate.type == "BlockStatement" ? [...object.alternate.body] : [object.alternate] : [];
|
|
45
|
-
noBody.unshift((0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(result), (0, _gen.Literal)(1))));
|
|
46
|
-
var elseTest = (0, _gen.UnaryExpression)("!", (0, _gen.Identifier)(result));
|
|
47
|
-
var newObject = (0, _gen.TryStatement)([(0, _gen.IfStatement)({ ...object.test
|
|
48
|
-
}, [(0, _gen.ThrowStatement)((0, _gen.Identifier)(result))])], (0, _gen.CatchClause)((0, _gen.Identifier)(this.getPlaceholder()), yesBody), [(0, _gen.IfStatement)(elseTest, noBody)]);
|
|
49
|
-
|
|
50
|
-
if (isNested) {
|
|
51
|
-
this.replace(object, (0, _gen.BlockStatement)([...before, { ...newObject
|
|
52
|
-
}]));
|
|
53
|
-
} else {
|
|
54
|
-
body.splice(body.indexOf(element), 0, ...before);
|
|
55
|
-
this.replace(object, newObject);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
exports.default = ChoiceFlowObfuscation;
|