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
package/src/util/insert.ts
CHANGED
|
@@ -3,6 +3,12 @@ import { getBlock, isBlock } from "../traverse";
|
|
|
3
3
|
import { Node } from "./gen";
|
|
4
4
|
import { getIdentifierInfo, validateChain } from "./identifiers";
|
|
5
5
|
|
|
6
|
+
export function isClass(object: Node): boolean {
|
|
7
|
+
return (
|
|
8
|
+
object.type === "ClassDeclaration" || object.type === "ClassExpression"
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
/**
|
|
7
13
|
* - `FunctionDeclaration`
|
|
8
14
|
* - `FunctionExpression`
|
|
@@ -18,6 +24,17 @@ export function isFunction(object: Node): boolean {
|
|
|
18
24
|
].includes(object && object.type);
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
export function isStrictModeFunction(object: Node): boolean {
|
|
28
|
+
ok(isFunction(object));
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
object.body.type === "BlockStatement" &&
|
|
32
|
+
object.body.body[0] &&
|
|
33
|
+
object.body.body[0].type === "ExpressionStatement" &&
|
|
34
|
+
object.body.body[0].directive === "use strict"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
/**
|
|
22
39
|
* The function context where the object is.
|
|
23
40
|
*
|
package/src/util/random.ts
CHANGED
|
@@ -63,7 +63,7 @@ export function splitIntoChunks(str: string, size: number) {
|
|
|
63
63
|
ok(Math.floor(size) === size, "size must be integer");
|
|
64
64
|
|
|
65
65
|
const numChunks = Math.ceil(str.length / size);
|
|
66
|
-
const chunks = new Array(numChunks);
|
|
66
|
+
const chunks: string[] = new Array(numChunks);
|
|
67
67
|
|
|
68
68
|
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
|
|
69
69
|
chunks[i] = str.substr(o, size);
|
|
@@ -139,3 +139,83 @@ export function alphabeticalGenerator(index: number) {
|
|
|
139
139
|
}
|
|
140
140
|
return name;
|
|
141
141
|
}
|
|
142
|
+
|
|
143
|
+
export function createZeroWidthGenerator() {
|
|
144
|
+
var keywords = [
|
|
145
|
+
"if",
|
|
146
|
+
"in",
|
|
147
|
+
"for",
|
|
148
|
+
"let",
|
|
149
|
+
"new",
|
|
150
|
+
"try",
|
|
151
|
+
"var",
|
|
152
|
+
"case",
|
|
153
|
+
"else",
|
|
154
|
+
"null",
|
|
155
|
+
"break",
|
|
156
|
+
"catch",
|
|
157
|
+
"class",
|
|
158
|
+
"const",
|
|
159
|
+
"super",
|
|
160
|
+
"throw",
|
|
161
|
+
"while",
|
|
162
|
+
"yield",
|
|
163
|
+
"delete",
|
|
164
|
+
"export",
|
|
165
|
+
"import",
|
|
166
|
+
"public",
|
|
167
|
+
"return",
|
|
168
|
+
"switch",
|
|
169
|
+
"default",
|
|
170
|
+
"finally",
|
|
171
|
+
"private",
|
|
172
|
+
"continue",
|
|
173
|
+
"debugger",
|
|
174
|
+
"function",
|
|
175
|
+
"arguments",
|
|
176
|
+
"protected",
|
|
177
|
+
"instanceof",
|
|
178
|
+
"await",
|
|
179
|
+
"async",
|
|
180
|
+
|
|
181
|
+
// new key words and other fun stuff :P
|
|
182
|
+
"NaN",
|
|
183
|
+
"undefined",
|
|
184
|
+
"true",
|
|
185
|
+
"false",
|
|
186
|
+
"typeof",
|
|
187
|
+
"this",
|
|
188
|
+
"static",
|
|
189
|
+
"void",
|
|
190
|
+
"of",
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
var maxSize = 0;
|
|
194
|
+
var currentKeyWordsArray: string[] = [];
|
|
195
|
+
|
|
196
|
+
function generateArray() {
|
|
197
|
+
var result = keywords
|
|
198
|
+
.map(
|
|
199
|
+
(keyWord) =>
|
|
200
|
+
keyWord + "\u200C".repeat(Math.max(maxSize - keyWord.length, 1))
|
|
201
|
+
)
|
|
202
|
+
.filter((craftedVariableName) => craftedVariableName.length == maxSize);
|
|
203
|
+
|
|
204
|
+
if (!result.length) {
|
|
205
|
+
++maxSize;
|
|
206
|
+
return generateArray();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return shuffle(result);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getNextVariable(): string {
|
|
213
|
+
if (!currentKeyWordsArray.length) {
|
|
214
|
+
++maxSize;
|
|
215
|
+
currentKeyWordsArray = generateArray();
|
|
216
|
+
}
|
|
217
|
+
return currentKeyWordsArray.pop();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { generate: getNextVariable };
|
|
221
|
+
}
|
package/src/util/scope.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
+
import { ok } from "assert";
|
|
1
2
|
import { isBlock } from "../traverse";
|
|
3
|
+
import { Node } from "./gen";
|
|
2
4
|
|
|
3
|
-
export function isLexicalScope(object) {
|
|
5
|
+
export function isLexicalScope(object: Node) {
|
|
4
6
|
return isBlock(object) || object.type == "SwitchCase";
|
|
5
7
|
}
|
|
6
8
|
|
|
7
|
-
export function getLexicalScope(object, parents) {
|
|
9
|
+
export function getLexicalScope(object: Node, parents: Node[]): Node {
|
|
8
10
|
return [object, ...parents].find((node) => isLexicalScope(node));
|
|
9
11
|
}
|
|
12
|
+
|
|
13
|
+
export function getLexicalScopeBody(object: Node): Node[] {
|
|
14
|
+
ok(isLexicalScope(object));
|
|
15
|
+
|
|
16
|
+
return isBlock(object)
|
|
17
|
+
? object.body
|
|
18
|
+
: object.type === "SwitchCase"
|
|
19
|
+
? object.consequent
|
|
20
|
+
: ok("Unhandled case");
|
|
21
|
+
}
|
package/test/code/Cash.test.ts
CHANGED
|
@@ -6,7 +6,7 @@ var CASH_JS = readFileSync(join(__dirname, "./Cash.src.js"), "utf-8");
|
|
|
6
6
|
|
|
7
7
|
test("Variant #1: Cash.js on High Preset (Strict Mode)", async () => {
|
|
8
8
|
var output = await JsConfuser(CASH_JS, {
|
|
9
|
-
target: "
|
|
9
|
+
target: "node",
|
|
10
10
|
preset: "high",
|
|
11
11
|
});
|
|
12
12
|
|
|
@@ -32,12 +32,101 @@ test("Variant #1: Cash.js on High Preset (Strict Mode)", async () => {
|
|
|
32
32
|
$: false,
|
|
33
33
|
} as any;
|
|
34
34
|
window.window = window;
|
|
35
|
+
global.window = window;
|
|
36
|
+
for (var key in window) {
|
|
37
|
+
global[key] = window[key];
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
try {
|
|
41
|
+
eval(output);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
console.error(e);
|
|
44
|
+
writeFileSync("dev.output.js", output, {
|
|
45
|
+
encoding: "utf-8",
|
|
46
|
+
});
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
expect(true).toStrictEqual(false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
expect(window).toHaveProperty("cash");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("Variant #2: Cash.js on High Preset + Integrity + Self Defending + RGF + Tamper Protection", async () => {
|
|
55
|
+
// Make the required document variables for initialization
|
|
56
|
+
var document = {
|
|
57
|
+
documentElement: {},
|
|
58
|
+
createElement: () => {
|
|
59
|
+
return { style: {} };
|
|
60
|
+
},
|
|
61
|
+
} as any as Document;
|
|
62
|
+
var window = {
|
|
63
|
+
document,
|
|
64
|
+
Array,
|
|
65
|
+
Object,
|
|
66
|
+
Symbol,
|
|
67
|
+
Number,
|
|
68
|
+
parseInt,
|
|
69
|
+
JSON,
|
|
70
|
+
setTimeout,
|
|
71
|
+
encodeURIComponent,
|
|
72
|
+
RegExp,
|
|
73
|
+
String,
|
|
74
|
+
$: false,
|
|
75
|
+
} as any;
|
|
76
|
+
window.window = window;
|
|
77
|
+
global.window = window;
|
|
78
|
+
for (var key in window) {
|
|
79
|
+
global[key] = window[key];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var output = await JsConfuser(CASH_JS, {
|
|
83
|
+
target: "node",
|
|
84
|
+
preset: "high",
|
|
85
|
+
rgf: true,
|
|
86
|
+
lock: {
|
|
87
|
+
integrity: true,
|
|
88
|
+
selfDefending: true,
|
|
89
|
+
tamperProtection: true,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// new Function() runs in non-strict mode
|
|
95
|
+
new Function(output)();
|
|
96
|
+
} catch (e) {
|
|
97
|
+
var helperCode = `var document = {
|
|
98
|
+
documentElement: {},
|
|
99
|
+
createElement: () => {
|
|
100
|
+
return { style: {} };
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
var window = {
|
|
104
|
+
document,
|
|
105
|
+
Array,
|
|
106
|
+
Object,
|
|
107
|
+
Symbol,
|
|
108
|
+
Number,
|
|
109
|
+
parseInt,
|
|
110
|
+
JSON,
|
|
111
|
+
setTimeout,
|
|
112
|
+
encodeURIComponent,
|
|
113
|
+
RegExp,
|
|
114
|
+
String,
|
|
115
|
+
$: false,
|
|
116
|
+
};
|
|
117
|
+
window.window = window;
|
|
118
|
+
global.window = window;
|
|
119
|
+
for (var key in window) {
|
|
120
|
+
global[key] = window[key];
|
|
121
|
+
}`;
|
|
122
|
+
|
|
123
|
+
console.error(e);
|
|
124
|
+
writeFileSync("dev.output.js", helperCode + "\n" + output, {
|
|
125
|
+
encoding: "utf-8",
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
expect(true).toStrictEqual(false);
|
|
129
|
+
}
|
|
41
130
|
|
|
42
131
|
expect(window).toHaveProperty("cash");
|
|
43
132
|
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function TestStrictMode() {
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
var isStrictMode = () => {
|
|
7
|
+
try {
|
|
8
|
+
undefined = true;
|
|
9
|
+
} catch (E) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// filler code to make transformations more likely to affect this function
|
|
16
|
+
var x, y, z;
|
|
17
|
+
var string1 = "Hello World";
|
|
18
|
+
var string2 = "use strict";
|
|
19
|
+
|
|
20
|
+
var chars = string2.split("");
|
|
21
|
+
var count = 0;
|
|
22
|
+
for (var char of chars) {
|
|
23
|
+
count++;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
expect(count).toStrictEqual(10);
|
|
27
|
+
|
|
28
|
+
// This function should be in strict mode
|
|
29
|
+
expect(isStrictMode()).toStrictEqual(true);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var isStrictMode = () => {
|
|
33
|
+
try {
|
|
34
|
+
undefined = true;
|
|
35
|
+
} catch (E) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Global level should be in strict mode
|
|
42
|
+
expect(isStrictMode()).toStrictEqual(true);
|
|
43
|
+
TestStrictMode();
|
|
44
|
+
|
|
45
|
+
// Direct vs. Indirect eval usage
|
|
46
|
+
var evalString = `
|
|
47
|
+
var isStrictMode = () => {
|
|
48
|
+
try {
|
|
49
|
+
undefined = true;
|
|
50
|
+
} catch (E) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
isStrictMode();`;
|
|
57
|
+
|
|
58
|
+
// Direct eval -> Preserve global strict-mode
|
|
59
|
+
var directEvalResult = eval(evalString);
|
|
60
|
+
expect(directEvalResult).toStrictEqual(true);
|
|
61
|
+
|
|
62
|
+
// Indirect eval -> Does not inherit context strict-mode
|
|
63
|
+
var _eval_ = eval;
|
|
64
|
+
var indirectEvalResult = _eval_(evalString);
|
|
65
|
+
expect(indirectEvalResult).toStrictEqual(false);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import JsConfuser from "../../src/index";
|
|
4
|
+
|
|
5
|
+
var StrictMode_JS = readFileSync(
|
|
6
|
+
join(__dirname, "./StrictMode.src.js"),
|
|
7
|
+
"utf-8"
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
test("Variant #1: StrictMode on High Preset", async () => {
|
|
11
|
+
var output = await JsConfuser(StrictMode_JS, {
|
|
12
|
+
target: "node",
|
|
13
|
+
preset: "high",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
//writeFileSync("./dev.output.js", output);
|
|
17
|
+
|
|
18
|
+
eval(output);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("Variant #2: StrictMode on 2x High Preset", async () => {
|
|
22
|
+
var output = await JsConfuser(StrictMode_JS, {
|
|
23
|
+
target: "node",
|
|
24
|
+
preset: "high",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
//writeFileSync("./dev.output1.js", output);
|
|
28
|
+
|
|
29
|
+
var output2 = await JsConfuser(output, {
|
|
30
|
+
target: "node",
|
|
31
|
+
preset: "high",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
//writeFileSync("./dev.output2.js", output2);
|
|
35
|
+
|
|
36
|
+
eval(output2);
|
|
37
|
+
});
|
package/test/compare.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Template from "../src/templates/template";
|
|
1
2
|
import { isIndependent } from "../src/util/compare";
|
|
2
3
|
import {
|
|
3
4
|
ArrayExpression,
|
|
@@ -17,9 +18,9 @@ describe("isIndependent", () => {
|
|
|
17
18
|
).toStrictEqual(false);
|
|
18
19
|
});
|
|
19
20
|
|
|
20
|
-
it("should return true for reserved identifiers (
|
|
21
|
+
it("should return true for reserved identifiers (undefined, NaN, etc)", () => {
|
|
21
22
|
expect(
|
|
22
|
-
isIndependent(Identifier("
|
|
23
|
+
isIndependent(Identifier("undefined"), [{ type: "Program" }])
|
|
23
24
|
).toStrictEqual(true);
|
|
24
25
|
});
|
|
25
26
|
|
|
@@ -41,4 +42,63 @@ describe("isIndependent", () => {
|
|
|
41
42
|
it("should return false for everything else", () => {
|
|
42
43
|
expect(isIndependent(FunctionExpression([], []), [])).toStrictEqual(false);
|
|
43
44
|
});
|
|
45
|
+
|
|
46
|
+
it("various cases", () => {
|
|
47
|
+
expect(
|
|
48
|
+
isIndependent(
|
|
49
|
+
new Template(`({
|
|
50
|
+
x: 1,
|
|
51
|
+
y: 2,
|
|
52
|
+
z: 3,
|
|
53
|
+
})`).single().expression,
|
|
54
|
+
[]
|
|
55
|
+
)
|
|
56
|
+
).toStrictEqual(true);
|
|
57
|
+
|
|
58
|
+
expect(
|
|
59
|
+
isIndependent(
|
|
60
|
+
new Template(`({
|
|
61
|
+
x: 1,
|
|
62
|
+
y: 2,
|
|
63
|
+
z: [3,4,5,6,7,"My String",undefined,null,NaN],
|
|
64
|
+
})`).single().expression,
|
|
65
|
+
[]
|
|
66
|
+
)
|
|
67
|
+
).toStrictEqual(true);
|
|
68
|
+
|
|
69
|
+
expect(
|
|
70
|
+
isIndependent(
|
|
71
|
+
new Template(`({
|
|
72
|
+
x: 1,
|
|
73
|
+
y: 2,
|
|
74
|
+
z: 3,
|
|
75
|
+
_: function(){return value}
|
|
76
|
+
})`).single().expression,
|
|
77
|
+
[]
|
|
78
|
+
)
|
|
79
|
+
).toStrictEqual(false);
|
|
80
|
+
|
|
81
|
+
expect(
|
|
82
|
+
isIndependent(
|
|
83
|
+
new Template(`({
|
|
84
|
+
x: 1,
|
|
85
|
+
y: 2,
|
|
86
|
+
z: 3,
|
|
87
|
+
_: [value]
|
|
88
|
+
})`).single().expression,
|
|
89
|
+
[]
|
|
90
|
+
)
|
|
91
|
+
).toStrictEqual(false);
|
|
92
|
+
|
|
93
|
+
expect(
|
|
94
|
+
isIndependent(
|
|
95
|
+
new Template(`([
|
|
96
|
+
{
|
|
97
|
+
x: value
|
|
98
|
+
}
|
|
99
|
+
])`).single().expression,
|
|
100
|
+
[]
|
|
101
|
+
)
|
|
102
|
+
).toStrictEqual(false);
|
|
103
|
+
});
|
|
44
104
|
});
|
package/test/options.test.ts
CHANGED
|
@@ -1,76 +1,150 @@
|
|
|
1
1
|
import JsConfuser from "../src/index";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
describe("options", () => {
|
|
4
|
+
test("Variant #1: Accept percentages", async () => {
|
|
5
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
6
|
+
target: "node",
|
|
7
|
+
renameGlobals: true,
|
|
8
|
+
renameVariables: true,
|
|
9
|
+
stringConcealing: 0.5,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
9
13
|
});
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
test("Variant #2: Accept probability arrays", async () => {
|
|
16
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
17
|
+
target: "node",
|
|
18
|
+
renameVariables: true,
|
|
19
|
+
renameGlobals: true,
|
|
20
|
+
identifierGenerator: ["hexadecimal", "mangled"], // half hexadecimal, half randomized
|
|
21
|
+
});
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
16
|
-
target: "node",
|
|
17
|
-
renameVariables: true,
|
|
18
|
-
renameGlobals: true,
|
|
19
|
-
identifierGenerator: ["hexadecimal", "mangled"], // half hexadecimal, half randomized
|
|
23
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
20
24
|
});
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
test("Variant #3: Accept probability maps", async () => {
|
|
27
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
28
|
+
target: "node",
|
|
29
|
+
renameVariables: true,
|
|
30
|
+
renameGlobals: true,
|
|
31
|
+
identifierGenerator: {
|
|
32
|
+
// 25% each
|
|
33
|
+
hexadecimal: 0.25,
|
|
34
|
+
randomized: 0.25,
|
|
35
|
+
mangled: 0.25,
|
|
36
|
+
number: 0.25,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
27
|
-
target: "node",
|
|
28
|
-
renameVariables: true,
|
|
29
|
-
renameGlobals: true,
|
|
30
|
-
identifierGenerator: {
|
|
31
|
-
// 25% each
|
|
32
|
-
hexadecimal: 0.25,
|
|
33
|
-
randomized: 0.25,
|
|
34
|
-
mangled: 0.25,
|
|
35
|
-
number: 0.25,
|
|
36
|
-
},
|
|
40
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
37
41
|
});
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
test("Variant #4: Work with compact false", async () => {
|
|
44
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
45
|
+
target: "node",
|
|
46
|
+
renameGlobals: true,
|
|
47
|
+
renameVariables: true,
|
|
48
|
+
compact: false,
|
|
49
|
+
});
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
44
|
-
target: "node",
|
|
45
|
-
renameGlobals: true,
|
|
46
|
-
renameVariables: true,
|
|
47
|
-
compact: false,
|
|
51
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
48
52
|
});
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
test("Variant #5: Work with indent set to 2 spaces", async () => {
|
|
55
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
56
|
+
target: "node",
|
|
57
|
+
renameGlobals: true,
|
|
58
|
+
renameVariables: true,
|
|
59
|
+
compact: false,
|
|
60
|
+
indent: 2,
|
|
61
|
+
});
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
55
|
-
target: "node",
|
|
56
|
-
renameGlobals: true,
|
|
57
|
-
renameVariables: true,
|
|
58
|
-
compact: false,
|
|
59
|
-
indent: 2,
|
|
63
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
60
64
|
});
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
test("Variant #6: Work with debugComments enabled", async () => {
|
|
67
|
+
var output = await JsConfuser(`var TEST_VARIABLE;`, {
|
|
68
|
+
target: "node",
|
|
69
|
+
renameGlobals: true,
|
|
70
|
+
renameVariables: true,
|
|
71
|
+
compact: false,
|
|
72
|
+
indent: 2,
|
|
73
|
+
debugComments: true,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(output).not.toContain("TEST_VARIABLE");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("Variant #7: Error on invalid lock option", async () => {
|
|
80
|
+
expect(
|
|
81
|
+
JsConfuser(`var TEST_VARIABLE;`, {
|
|
82
|
+
target: "node",
|
|
83
|
+
lock: "invalid",
|
|
84
|
+
} as any)
|
|
85
|
+
).rejects.toThrow();
|
|
86
|
+
|
|
87
|
+
expect(
|
|
88
|
+
JsConfuser(`var TEST_VARIABLE;`, {
|
|
89
|
+
target: "node",
|
|
90
|
+
lock: {
|
|
91
|
+
invalidProperty: true,
|
|
92
|
+
},
|
|
93
|
+
} as any)
|
|
94
|
+
).rejects.toThrow();
|
|
95
|
+
});
|
|
63
96
|
});
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
98
|
+
describe("options.preserveFunctionLength", () => {
|
|
99
|
+
test("Variant #1: Enabled by default", async () => {
|
|
100
|
+
var output = await JsConfuser(
|
|
101
|
+
`
|
|
102
|
+
function myFunction(a, b, c, d = "") {
|
|
103
|
+
// Function.length = 3
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
TEST_OUTPUT = myFunction.length; // 3
|
|
107
|
+
`,
|
|
108
|
+
{
|
|
109
|
+
target: "node",
|
|
110
|
+
preset: "high",
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
var TEST_OUTPUT;
|
|
115
|
+
eval(output);
|
|
116
|
+
expect(TEST_OUTPUT).toStrictEqual(3);
|
|
73
117
|
});
|
|
74
118
|
|
|
75
|
-
|
|
119
|
+
test("Variant #2: Disabled", async () => {
|
|
120
|
+
var output = await JsConfuser(
|
|
121
|
+
`
|
|
122
|
+
function myFunction(a, b, c, d = "") {
|
|
123
|
+
// Function.length = 3
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
TEST_OUTPUT = myFunction.length; // 3
|
|
127
|
+
`,
|
|
128
|
+
{
|
|
129
|
+
target: "node",
|
|
130
|
+
preset: "high",
|
|
131
|
+
preserveFunctionLength: false,
|
|
132
|
+
|
|
133
|
+
stringEncoding: false,
|
|
134
|
+
stringCompression: false,
|
|
135
|
+
stringConcealing: false,
|
|
136
|
+
stringSplitting: false,
|
|
137
|
+
deadCode: false,
|
|
138
|
+
duplicateLiteralsRemoval: false,
|
|
139
|
+
|
|
140
|
+
rgf: true,
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(output).not.toContain("defineProperty");
|
|
145
|
+
|
|
146
|
+
var TEST_OUTPUT;
|
|
147
|
+
eval(output);
|
|
148
|
+
expect(TEST_OUTPUT).not.toStrictEqual(3);
|
|
149
|
+
});
|
|
76
150
|
});
|