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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
199
|
-
return
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
286
|
-
|
|
287
|
-
input(
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
});
|