js-confuser 1.7.1 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +1 -1
- package/CHANGELOG.md +73 -0
- package/README.md +32 -31
- package/dist/compiler.js +2 -8
- package/dist/constants.js +22 -10
- package/dist/index.js +15 -30
- package/dist/obfuscator.js +15 -62
- package/dist/options.js +33 -40
- 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 +121 -5
- package/dist/templates/core.js +35 -0
- package/dist/templates/crash.js +22 -11
- 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 +189 -43
- package/dist/transforms/antiTooling.js +26 -22
- package/dist/transforms/calculator.js +19 -55
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +242 -333
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
- package/dist/transforms/deadCode.js +542 -31
- package/dist/transforms/dispatcher.js +112 -112
- 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 +21 -26
- package/dist/transforms/identifier/globalConcealing.js +72 -56
- package/dist/transforms/identifier/movedDeclarations.js +66 -38
- package/dist/transforms/identifier/renameVariables.js +36 -68
- package/dist/transforms/identifier/variableAnalysis.js +21 -48
- package/dist/transforms/lock/antiDebug.js +20 -25
- package/dist/transforms/lock/integrity.js +53 -52
- package/dist/transforms/lock/lock.js +161 -126
- package/dist/transforms/minify.js +77 -108
- package/dist/transforms/opaquePredicates.js +12 -49
- package/dist/transforms/preparation.js +28 -49
- package/dist/transforms/renameLabels.js +5 -22
- package/dist/transforms/rgf.js +125 -72
- package/dist/transforms/shuffle.js +42 -47
- package/dist/transforms/stack.js +41 -98
- package/dist/transforms/string/encoding.js +76 -27
- package/dist/transforms/string/stringCompression.js +75 -68
- package/dist/transforms/string/stringConcealing.js +127 -135
- package/dist/transforms/string/stringEncoding.js +6 -26
- package/dist/transforms/string/stringSplitting.js +5 -30
- package/dist/transforms/transform.js +76 -104
- 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 +5 -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 +31 -36
- package/dist/util/scope.js +6 -3
- package/docs/Countermeasures.md +13 -6
- package/docs/Integrity.md +35 -28
- package/docs/RGF.md +6 -1
- package/docs/RenameVariables.md +116 -0
- package/docs/TamperProtection.md +100 -0
- package/docs/Template.md +117 -0
- package/package.json +3 -3
- package/src/constants.ts +17 -0
- package/src/index.ts +7 -5
- package/src/options.ts +60 -7
- package/src/order.ts +2 -2
- package/src/templates/bufferToString.ts +79 -11
- package/src/templates/core.ts +29 -0
- package/src/templates/crash.ts +6 -38
- package/src/templates/es5.ts +1 -1
- package/src/templates/functionLength.ts +21 -3
- package/src/templates/globals.ts +3 -0
- package/src/templates/template.ts +205 -46
- package/src/transforms/antiTooling.ts +33 -11
- package/src/transforms/calculator.ts +4 -2
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +12 -5
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
- package/src/transforms/deadCode.ts +74 -42
- package/src/transforms/dispatcher.ts +99 -73
- package/src/transforms/es5/antiClass.ts +25 -12
- package/src/transforms/es5/antiDestructuring.ts +1 -1
- package/src/transforms/es5/antiES6Object.ts +2 -2
- package/src/transforms/es5/antiTemplate.ts +1 -1
- package/src/transforms/extraction/classExtraction.ts +168 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +11 -16
- package/src/transforms/extraction/objectExtraction.ts +4 -15
- package/src/transforms/flatten.ts +20 -5
- package/src/transforms/identifier/globalAnalysis.ts +18 -1
- package/src/transforms/identifier/globalConcealing.ts +119 -72
- package/src/transforms/identifier/movedDeclarations.ts +90 -24
- package/src/transforms/identifier/renameVariables.ts +16 -1
- package/src/transforms/lock/antiDebug.ts +2 -2
- package/src/transforms/lock/integrity.ts +13 -11
- package/src/transforms/lock/lock.ts +122 -30
- package/src/transforms/minify.ts +28 -13
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +16 -0
- package/src/transforms/rgf.ts +139 -12
- package/src/transforms/shuffle.ts +3 -3
- package/src/transforms/stack.ts +19 -4
- package/src/transforms/string/encoding.ts +88 -51
- package/src/transforms/string/stringCompression.ts +86 -17
- package/src/transforms/string/stringConcealing.ts +148 -118
- package/src/transforms/string/stringEncoding.ts +1 -2
- package/src/transforms/string/stringSplitting.ts +1 -2
- package/src/transforms/transform.ts +63 -46
- package/src/types.ts +2 -0
- package/src/util/compare.ts +39 -5
- package/src/util/gen.ts +10 -3
- package/src/util/guard.ts +10 -0
- package/src/util/insert.ts +17 -0
- package/src/util/random.ts +81 -1
- package/src/util/scope.ts +14 -2
- package/test/code/Cash.test.ts +94 -5
- 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 +129 -55
- package/test/templates/template.test.ts +211 -1
- 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 +89 -0
- package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
- package/test/transforms/identifier/renameVariables.test.ts +75 -1
- package/test/transforms/lock/tamperProtection.test.ts +336 -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,4 +1,7 @@
|
|
|
1
|
+
import { compileJsSync } from "../../src/compiler";
|
|
2
|
+
import { parseSnippet } from "../../src/parser";
|
|
1
3
|
import Template from "../../src/templates/template";
|
|
4
|
+
import { Literal } from "../../src/util/gen";
|
|
2
5
|
|
|
3
6
|
describe("Template", () => {
|
|
4
7
|
test("Variant #1: Error when invalid code passed in", () => {
|
|
@@ -6,9 +9,216 @@ describe("Template", () => {
|
|
|
6
9
|
console.error = () => {};
|
|
7
10
|
|
|
8
11
|
expect(() => {
|
|
9
|
-
Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
|
|
12
|
+
new Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
|
|
10
13
|
}).toThrow();
|
|
11
14
|
|
|
12
15
|
console.error = _consoleError;
|
|
13
16
|
});
|
|
17
|
+
|
|
18
|
+
test("Variant #2: Error on missing variables", () => {
|
|
19
|
+
var _consoleError = console.error;
|
|
20
|
+
console.error = () => {};
|
|
21
|
+
|
|
22
|
+
expect(() => {
|
|
23
|
+
new Template(`
|
|
24
|
+
function {name}(){
|
|
25
|
+
{global}.property = true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
`).compile({ name: "test" });
|
|
29
|
+
}).toThrow();
|
|
30
|
+
|
|
31
|
+
console.error = _consoleError;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("Variant #3: Basic string interpolation", () => {
|
|
35
|
+
var Base64Template = new Template(`
|
|
36
|
+
function {name}(str){
|
|
37
|
+
return window.btoa(str)
|
|
38
|
+
}`);
|
|
39
|
+
|
|
40
|
+
var functionDeclaration = Base64Template.single({
|
|
41
|
+
name: "decodeBase64",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
45
|
+
expect(functionDeclaration.id.name).toStrictEqual("decodeBase64");
|
|
46
|
+
|
|
47
|
+
// Generated code and check
|
|
48
|
+
var output = compileJsSync(functionDeclaration, {
|
|
49
|
+
target: "node",
|
|
50
|
+
compact: true,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Ensure code has no syntax errors
|
|
54
|
+
eval(output);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("Variant #4: AST subtree insertion", () => {
|
|
58
|
+
var Base64Template = new Template(`
|
|
59
|
+
function {name}(str){
|
|
60
|
+
{getWindow}
|
|
61
|
+
|
|
62
|
+
return {getWindowName}.btoa(str)
|
|
63
|
+
}`);
|
|
64
|
+
|
|
65
|
+
var functionDeclaration = Base64Template.single({
|
|
66
|
+
name: "decodeBase64",
|
|
67
|
+
getWindowName: "newWindow",
|
|
68
|
+
getWindow: parseSnippet("var newWindow = {}").body,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
72
|
+
expect(functionDeclaration.body.body[0].type).toStrictEqual(
|
|
73
|
+
"VariableDeclaration"
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Generated code and check
|
|
77
|
+
var output = compileJsSync(functionDeclaration, {
|
|
78
|
+
target: "node",
|
|
79
|
+
compact: true,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(output).toContain("var newWindow={}");
|
|
83
|
+
expect(output).toContain("return newWindow.btoa(str)");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("Variant #5: AST subtree insertion (callback)", () => {
|
|
87
|
+
var Base64Template = new Template(`
|
|
88
|
+
function {name}(str){
|
|
89
|
+
{getWindow}
|
|
90
|
+
|
|
91
|
+
return {getWindowName}.btoa(str)
|
|
92
|
+
}`);
|
|
93
|
+
|
|
94
|
+
var functionDeclaration = Base64Template.single({
|
|
95
|
+
name: "decodeBase64",
|
|
96
|
+
getWindowName: "newWindow",
|
|
97
|
+
getWindow: () => {
|
|
98
|
+
return parseSnippet("var newWindow = {}").body;
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
103
|
+
expect(functionDeclaration.body.body[0].type).toStrictEqual(
|
|
104
|
+
"VariableDeclaration"
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Generated code and check
|
|
108
|
+
var output = compileJsSync(functionDeclaration, {
|
|
109
|
+
target: "node",
|
|
110
|
+
compact: true,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(output).toContain("var newWindow={}");
|
|
114
|
+
expect(output).toContain("return newWindow.btoa(str)");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("Variant #6: Template subtree insertion", async () => {
|
|
118
|
+
var NewWindowTemplate = new Template(`
|
|
119
|
+
var {NewWindowName} = {};
|
|
120
|
+
`);
|
|
121
|
+
var Base64Template = new Template(`
|
|
122
|
+
function {name}(str){
|
|
123
|
+
{NewWindowTemplate}
|
|
124
|
+
|
|
125
|
+
return {NewWindowName}.btoa(str)
|
|
126
|
+
}`);
|
|
127
|
+
|
|
128
|
+
var functionDeclaration = Base64Template.single({
|
|
129
|
+
name: "atob",
|
|
130
|
+
NewWindowTemplate: NewWindowTemplate,
|
|
131
|
+
NewWindowName: "newWindow",
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
135
|
+
expect(functionDeclaration.body.body[0].type).toStrictEqual(
|
|
136
|
+
"VariableDeclaration"
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Generated code and check
|
|
140
|
+
var output = compileJsSync(functionDeclaration, {
|
|
141
|
+
target: "node",
|
|
142
|
+
compact: true,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expect(output).toContain("var newWindow={}");
|
|
146
|
+
expect(output).toContain("return newWindow.btoa(str)");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("Variant #7: Template subtree insertion (callback)", async () => {
|
|
150
|
+
var NewWindowTemplate = new Template(`
|
|
151
|
+
var {NewWindowName} = {};
|
|
152
|
+
`);
|
|
153
|
+
var Base64Template = new Template(`
|
|
154
|
+
function {name}(str){
|
|
155
|
+
{NewWindowTemplate}
|
|
156
|
+
|
|
157
|
+
return {NewWindowName}.btoa(str)
|
|
158
|
+
}`);
|
|
159
|
+
|
|
160
|
+
var functionDeclaration = Base64Template.single({
|
|
161
|
+
name: "atob",
|
|
162
|
+
NewWindowTemplate: () => NewWindowTemplate,
|
|
163
|
+
NewWindowName: "newWindow",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
167
|
+
expect(functionDeclaration.body.body[0].type).toStrictEqual(
|
|
168
|
+
"VariableDeclaration"
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Generated code and check
|
|
172
|
+
var output = compileJsSync(functionDeclaration, {
|
|
173
|
+
target: "node",
|
|
174
|
+
compact: true,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
expect(output).toContain("var newWindow={}");
|
|
178
|
+
expect(output).toContain("return newWindow.btoa(str)");
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("Variant #8: AST string replacement with Literal node", async () => {
|
|
182
|
+
var Base64Template = new Template(`
|
|
183
|
+
function {name}(str){
|
|
184
|
+
return window[{property}](str)
|
|
185
|
+
}`);
|
|
186
|
+
|
|
187
|
+
var functionDeclaration = Base64Template.single({
|
|
188
|
+
name: "decodeBase64",
|
|
189
|
+
property: Literal("atob"),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
193
|
+
|
|
194
|
+
// Generated code and check
|
|
195
|
+
var output = compileJsSync(functionDeclaration, {
|
|
196
|
+
target: "node",
|
|
197
|
+
compact: true,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(output).toContain("return window['atob'](str)");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("Variant #9: AST string replacement with Literal node (callback)", async () => {
|
|
204
|
+
var Base64Template = new Template(`
|
|
205
|
+
function {name}(str){
|
|
206
|
+
return window[{property}](str)
|
|
207
|
+
}`);
|
|
208
|
+
|
|
209
|
+
var functionDeclaration = Base64Template.single({
|
|
210
|
+
name: "decodeBase64",
|
|
211
|
+
property: () => Literal("atob"),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(functionDeclaration.type).toStrictEqual("FunctionDeclaration");
|
|
215
|
+
|
|
216
|
+
// Generated code and check
|
|
217
|
+
var output = compileJsSync(functionDeclaration, {
|
|
218
|
+
target: "node",
|
|
219
|
+
compact: true,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
expect(output).toContain("return window['atob'](str)");
|
|
223
|
+
});
|
|
14
224
|
});
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import { criticalFunctionTag } from "../../../src/constants";
|
|
1
2
|
import JsConfuser from "../../../src/index";
|
|
2
3
|
|
|
4
|
+
// Enable Control Flow Flattening's 'Expression Obfuscation' but skips all CFF switch transformations
|
|
5
|
+
function fakeEnabled() {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
test("Variant #1: Join expressions in a sequence expression", async () => {
|
|
4
10
|
var output = await JsConfuser(
|
|
5
11
|
`
|
|
6
12
|
TEST_OUTPUT=0;
|
|
7
13
|
TEST_OUTPUT++;
|
|
8
14
|
`,
|
|
9
|
-
{ target: "node", controlFlowFlattening:
|
|
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,92 @@ test("Variant #3: Properly hide in default parameter, function expression", asyn
|
|
|
51
51
|
|
|
52
52
|
expect(TEST_OUTPUT).toStrictEqual(true);
|
|
53
53
|
});
|
|
54
|
+
|
|
55
|
+
// https://github.com/MichaelXF/js-confuser/issues/131
|
|
56
|
+
test("Variant #4: Don't change __dirname", async function () {
|
|
57
|
+
var code = `
|
|
58
|
+
TEST_OUTPUT = __dirname;
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
var output = await JsConfuser(code, {
|
|
62
|
+
target: "node",
|
|
63
|
+
globalConcealing: true,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
expect(output).toContain("__dirname");
|
|
67
|
+
|
|
68
|
+
var TEST_OUTPUT;
|
|
69
|
+
eval(output);
|
|
70
|
+
|
|
71
|
+
expect(typeof TEST_OUTPUT).toStrictEqual("string");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("Variant #5: Hide 'global' var, even if properties are modified", async () => {
|
|
75
|
+
var output = await JsConfuser(
|
|
76
|
+
`
|
|
77
|
+
TEST_GLOBAL_VARIANT_5_OUTPUT = global.TEST_GLOBAL_VARIANT_5_INPUT * 2;
|
|
78
|
+
`,
|
|
79
|
+
{ target: "node", globalConcealing: true }
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Input should get transformed
|
|
83
|
+
expect(output).not.toContain("global['TEST_GLOBAL_VARIANT_5_INPUT");
|
|
84
|
+
|
|
85
|
+
// TEST_GLOBAL_VARIANT_5_OUTPUT should stay the same
|
|
86
|
+
expect(output).not.toContain("global['TEST_GLOBAL_VARIANT_5_OUTPUT");
|
|
87
|
+
|
|
88
|
+
(global as any).TEST_GLOBAL_VARIANT_5_INPUT = 50;
|
|
89
|
+
(global as any).TEST_GLOBAL_VARIANT_5_OUTPUT = 100;
|
|
90
|
+
|
|
91
|
+
eval(output);
|
|
92
|
+
|
|
93
|
+
expect((global as any).TEST_GLOBAL_VARIANT_5_OUTPUT).toStrictEqual(100);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("Variant #6: Preserve __JS_CONFUSER_VAR__", async () => {
|
|
97
|
+
// Covers both defined and undefined case
|
|
98
|
+
var output = await JsConfuser(
|
|
99
|
+
`
|
|
100
|
+
var TEST_VARIABLE
|
|
101
|
+
TEST_OUTPUT = [__JS_CONFUSER_VAR__(TEST_OUTER_VARIABLE), __JS_CONFUSER_VAR__(TEST_VARIABLE)];
|
|
102
|
+
`,
|
|
103
|
+
{
|
|
104
|
+
target: "node",
|
|
105
|
+
globalConcealing: true,
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
expect(output).not.toContain("__JS_CONFUSER_VAR__");
|
|
110
|
+
|
|
111
|
+
var TEST_OUTPUT;
|
|
112
|
+
eval(output);
|
|
113
|
+
|
|
114
|
+
expect(TEST_OUTPUT).toStrictEqual(["TEST_OUTER_VARIABLE", "TEST_VARIABLE"]);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("Variant #7: Custom callback option", async () => {
|
|
118
|
+
var namesCollected: string[] = [];
|
|
119
|
+
|
|
120
|
+
var output = await JsConfuser(
|
|
121
|
+
`
|
|
122
|
+
expect(true).toStrictEqual(true);
|
|
123
|
+
|
|
124
|
+
TEST_OUTPUT = true;
|
|
125
|
+
`,
|
|
126
|
+
{
|
|
127
|
+
target: "node",
|
|
128
|
+
globalConcealing: (name) => {
|
|
129
|
+
namesCollected.push(name);
|
|
130
|
+
return false;
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect(namesCollected).toContain("expect");
|
|
136
|
+
expect(namesCollected).not.toContain("TEST_OUTPUT");
|
|
137
|
+
|
|
138
|
+
var TEST_OUTPUT;
|
|
139
|
+
eval(output);
|
|
140
|
+
|
|
141
|
+
expect(TEST_OUTPUT).toStrictEqual(true);
|
|
142
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { predictableFunctionTag } from "../../../src/constants";
|
|
1
2
|
import JsConfuser from "../../../src/index";
|
|
2
3
|
|
|
3
4
|
test("Variant #1: Move variable 'y' to top", async () => {
|
|
@@ -212,3 +213,63 @@ test("Variant #9: Defined variable without an initializer", async () => {
|
|
|
212
213
|
eval(output2);
|
|
213
214
|
expect(TEST_OUTPUT).toStrictEqual(3);
|
|
214
215
|
});
|
|
216
|
+
|
|
217
|
+
test("Variant #10: Move parameters to predictable function", async () => {
|
|
218
|
+
var code = `
|
|
219
|
+
function testFunction${predictableFunctionTag}_FN(){
|
|
220
|
+
var values = [10,20,35,"40", null]
|
|
221
|
+
var parseIntKey = "parseInt"
|
|
222
|
+
var output = 0
|
|
223
|
+
var utils = {
|
|
224
|
+
get parser${predictableFunctionTag}(){
|
|
225
|
+
var fn = (value)=>{
|
|
226
|
+
return global[parseIntKey](value)
|
|
227
|
+
}
|
|
228
|
+
return fn
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
set setter_fn${predictableFunctionTag}(newValue){
|
|
232
|
+
var fakeVar
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
class FakeClass {
|
|
237
|
+
constructor(){
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
get fakeGet${predictableFunctionTag}(){
|
|
241
|
+
var fakeVar
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for(var value of values) {
|
|
246
|
+
switch(value){
|
|
247
|
+
case null:
|
|
248
|
+
break;
|
|
249
|
+
|
|
250
|
+
default:
|
|
251
|
+
var stringifiedValue = "" + value
|
|
252
|
+
var parsedValue = utils.parser${predictableFunctionTag}(stringifiedValue)
|
|
253
|
+
output += parsedValue;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return output
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
TEST_OUTPUT = testFunction${predictableFunctionTag}_FN()
|
|
262
|
+
`;
|
|
263
|
+
|
|
264
|
+
var output = await JsConfuser(code, {
|
|
265
|
+
target: "node",
|
|
266
|
+
movedDeclarations: true,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
expect(output).toContain("_FN(values");
|
|
270
|
+
|
|
271
|
+
var TEST_OUTPUT;
|
|
272
|
+
eval(output);
|
|
273
|
+
|
|
274
|
+
expect(TEST_OUTPUT).toStrictEqual(105);
|
|
275
|
+
});
|