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
package/src/transforms/label.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import Transform from "./transform";
|
|
2
|
-
import { Identifier, LabeledStatement } from "../util/gen";
|
|
3
|
-
import { walk } from "../traverse";
|
|
4
|
-
import { clone } from "../util/insert";
|
|
5
|
-
import { isLoop } from "../util/compare";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Ensures every break; statement has a label to point to.
|
|
9
|
-
*
|
|
10
|
-
* This is because Control Flow Flattening adds For Loops which label-less break statements point to the nearest,
|
|
11
|
-
* when they actually need to point to the original statement.
|
|
12
|
-
*/
|
|
13
|
-
export default class Label extends Transform {
|
|
14
|
-
constructor(o) {
|
|
15
|
-
super(o);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
match(object, parents) {
|
|
19
|
-
return (
|
|
20
|
-
isLoop(object) ||
|
|
21
|
-
(object.type == "BlockStatement" &&
|
|
22
|
-
parents[0] &&
|
|
23
|
-
parents[0].type == "LabeledStatement" &&
|
|
24
|
-
parents[0].body === object)
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
transform(object, parents) {
|
|
29
|
-
return () => {
|
|
30
|
-
var currentLabel =
|
|
31
|
-
parents[0].type == "LabeledStatement" && parents[0].label.name;
|
|
32
|
-
|
|
33
|
-
var label = currentLabel || this.getPlaceholder();
|
|
34
|
-
|
|
35
|
-
walk(object, parents, (o, p) => {
|
|
36
|
-
if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
|
|
37
|
-
function isContinuableStatement(x) {
|
|
38
|
-
return isLoop(x) && x.type !== "SwitchStatement";
|
|
39
|
-
}
|
|
40
|
-
function isBreakableStatement(x) {
|
|
41
|
-
return isLoop(x) || (o.label && x.type == "BlockStatement");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
var fn =
|
|
45
|
-
o.type == "ContinueStatement"
|
|
46
|
-
? isContinuableStatement
|
|
47
|
-
: isBreakableStatement;
|
|
48
|
-
|
|
49
|
-
var loop = p.find(fn);
|
|
50
|
-
if (object == loop) {
|
|
51
|
-
if (!o.label) {
|
|
52
|
-
o.label = Identifier(label);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Append label statement as this loop has none
|
|
59
|
-
if (!currentLabel) {
|
|
60
|
-
this.replace(object, LabeledStatement(label, { ...object }));
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { reservedIdentifiers } from "../../constants";
|
|
2
|
-
import { Node } from "../../util/gen";
|
|
3
|
-
import {
|
|
4
|
-
getDefiningIdentifier,
|
|
5
|
-
getIdentifierInfo,
|
|
6
|
-
} from "../../util/identifiers";
|
|
7
|
-
import Transform from "../transform";
|
|
8
|
-
|
|
9
|
-
export class NameMappingAnalysis extends Transform {
|
|
10
|
-
names: Map<string, Set<Node>>;
|
|
11
|
-
|
|
12
|
-
constructor(o) {
|
|
13
|
-
super(o);
|
|
14
|
-
|
|
15
|
-
this.names = new Map();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
match(object, parents) {
|
|
19
|
-
return object.type == "Identifier" && !reservedIdentifiers.has(object.name);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
transform(object, parents) {
|
|
23
|
-
var info = getIdentifierInfo(object, parents);
|
|
24
|
-
|
|
25
|
-
if (info.spec.isReferenced && !info.spec.isDefined) {
|
|
26
|
-
object.$definedAt = getDefiningIdentifier(object, parents);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (info.spec.isDefined) {
|
|
30
|
-
if (!this.names.has(object.name)) {
|
|
31
|
-
this.names.set(object.name, new Set([object]));
|
|
32
|
-
} else {
|
|
33
|
-
this.names.get(object.name).add(object);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Renames variables & removes conflicts.
|
|
41
|
-
*
|
|
42
|
-
* - This helps transformations like `Dispatcher` not replace re-declared identifiers.
|
|
43
|
-
*/
|
|
44
|
-
export default class NameConflicts extends Transform {
|
|
45
|
-
nameMappingAnalysis: NameMappingAnalysis;
|
|
46
|
-
|
|
47
|
-
changes: Map<Node, string>;
|
|
48
|
-
references: Map<Node, Set<Node>>;
|
|
49
|
-
|
|
50
|
-
constructor(o) {
|
|
51
|
-
super(o);
|
|
52
|
-
|
|
53
|
-
this.before.push((this.nameMappingAnalysis = new NameMappingAnalysis(o)));
|
|
54
|
-
this.changes = new Map();
|
|
55
|
-
this.references = new Map();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
match(object, parents) {
|
|
59
|
-
return (
|
|
60
|
-
object.type == "Identifier" &&
|
|
61
|
-
!reservedIdentifiers.has(object.name) &&
|
|
62
|
-
!this.options.globalVariables.has(object.name)
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
transform(object: Node, parents: Node[]) {
|
|
67
|
-
var info = getIdentifierInfo(object, parents);
|
|
68
|
-
|
|
69
|
-
if (info.isMethodDefinition) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (object.$definedAt) {
|
|
74
|
-
object.name = this.changes.get(object.$definedAt[0]) || object.name;
|
|
75
|
-
|
|
76
|
-
if (!this.references.has(object.$definedAt[0])) {
|
|
77
|
-
this.references.set(object.$definedAt[0], new Set([object]));
|
|
78
|
-
} else {
|
|
79
|
-
this.references.get(object.$definedAt[0]).add(object);
|
|
80
|
-
}
|
|
81
|
-
} else if (info.spec.isDefined) {
|
|
82
|
-
var set = this.nameMappingAnalysis.names.get(object.name);
|
|
83
|
-
if (set && set.size > 1) {
|
|
84
|
-
var index = Array.from(set).indexOf(object);
|
|
85
|
-
|
|
86
|
-
var newName = "_".repeat(index) + object.name;
|
|
87
|
-
|
|
88
|
-
if (index > 4 || this.nameMappingAnalysis.names.has(newName)) {
|
|
89
|
-
newName = this.getPlaceholder() + "_" + object.name;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
object.name = newName;
|
|
93
|
-
this.changes.set(object, newName);
|
|
94
|
-
if (this.references.has(object)) {
|
|
95
|
-
this.references.get(object).forEach((ref) => {
|
|
96
|
-
ref.name = newName;
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The file contains all preparation transformations
|
|
3
|
-
*/
|
|
4
|
-
import Transform from "../transform";
|
|
5
|
-
|
|
6
|
-
import { BlockStatement, Literal, ReturnStatement } from "../../util/gen";
|
|
7
|
-
import { ObfuscateOrder } from "../../order";
|
|
8
|
-
import { clone, getFunction } from "../../util/insert";
|
|
9
|
-
import { getIdentifierInfo } from "../../util/identifiers";
|
|
10
|
-
import Label from "../label";
|
|
11
|
-
import { isLoop } from "../../util/compare";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* People use shortcuts and its harder to parse.
|
|
15
|
-
*
|
|
16
|
-
* - `if (a) b()` -> `if (a) { b() }`
|
|
17
|
-
* - Ensures all bodies are `BlockStatement`, not individual expression statements
|
|
18
|
-
*/
|
|
19
|
-
class Block extends Transform {
|
|
20
|
-
constructor(o) {
|
|
21
|
-
super(o);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
match(object, parents) {
|
|
25
|
-
return !Array.isArray(object);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
transform(object, parents) {
|
|
29
|
-
switch (object.type) {
|
|
30
|
-
case "IfStatement":
|
|
31
|
-
if (object.consequent.type != "BlockStatement") {
|
|
32
|
-
object.consequent = BlockStatement([clone(object.consequent)]);
|
|
33
|
-
}
|
|
34
|
-
if (object.alternate && object.alternate.type != "BlockStatement") {
|
|
35
|
-
object.alternate = BlockStatement([clone(object.alternate)]);
|
|
36
|
-
}
|
|
37
|
-
break;
|
|
38
|
-
|
|
39
|
-
case "WhileStatement":
|
|
40
|
-
case "WithStatement":
|
|
41
|
-
case "ForStatement":
|
|
42
|
-
case "ForOfStatement":
|
|
43
|
-
case "ForInStatement":
|
|
44
|
-
if (object.body.type != "BlockStatement") {
|
|
45
|
-
object.body = BlockStatement([clone(object.body)]);
|
|
46
|
-
}
|
|
47
|
-
break;
|
|
48
|
-
|
|
49
|
-
case "ArrowFunctionExpression":
|
|
50
|
-
if (object.body.type !== "BlockStatement" && object.expression) {
|
|
51
|
-
object.body = BlockStatement([ReturnStatement(clone(object.body))]);
|
|
52
|
-
object.expression = false;
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
class ExplicitIdentifiers extends Transform {
|
|
60
|
-
constructor(o) {
|
|
61
|
-
super(o);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
match(object, parents) {
|
|
65
|
-
return object.type == "Identifier";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
transform(object, parents) {
|
|
69
|
-
if (object.name === "eval") {
|
|
70
|
-
var fn = getFunction(object, parents);
|
|
71
|
-
if (fn) {
|
|
72
|
-
fn.$requiresEval = true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
var info = getIdentifierInfo(object, parents);
|
|
77
|
-
if (info.isPropertyKey || info.isAccessor) {
|
|
78
|
-
var propIndex = parents.findIndex(
|
|
79
|
-
(x) => x.type == "MethodDefinition" || x.type == "Property"
|
|
80
|
-
);
|
|
81
|
-
if (propIndex !== -1) {
|
|
82
|
-
if (
|
|
83
|
-
parents[propIndex].type == "MethodDefinition" &&
|
|
84
|
-
parents[propIndex].kind == "constructor"
|
|
85
|
-
) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.log(object.name, "->", `'${object.name}'`);
|
|
91
|
-
|
|
92
|
-
this.replace(object, Literal(object.name));
|
|
93
|
-
parents[0].computed = true;
|
|
94
|
-
parents[0].shorthand = false;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
class ExplicitDeclarations extends Transform {
|
|
100
|
-
constructor(o) {
|
|
101
|
-
super(o);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
match(object, parents) {
|
|
105
|
-
return object.type == "VariableDeclaration";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
transform(object, parents) {
|
|
109
|
-
// for ( var x in ... ) {...}
|
|
110
|
-
var forIndex = parents.findIndex(
|
|
111
|
-
(x) => x.type == "ForInStatement" || x.type == "ForOfStatement"
|
|
112
|
-
);
|
|
113
|
-
if (
|
|
114
|
-
forIndex != -1 &&
|
|
115
|
-
parents[forIndex].left == (parents[forIndex - 1] || object)
|
|
116
|
-
) {
|
|
117
|
-
object.declarations.forEach((x) => {
|
|
118
|
-
x.init = null;
|
|
119
|
-
});
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
var body = parents[0];
|
|
124
|
-
if (isLoop(body) || body.type == "LabeledStatement") {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (body.type == "ExportNamedDeclaration") {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!Array.isArray(body)) {
|
|
133
|
-
this.error(new Error("body is " + body.type));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (object.declarations.length > 1) {
|
|
137
|
-
// Make singular
|
|
138
|
-
|
|
139
|
-
var index = body.indexOf(object);
|
|
140
|
-
if (index == -1) {
|
|
141
|
-
this.error(new Error("index is -1"));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
var after = object.declarations.slice(1);
|
|
145
|
-
|
|
146
|
-
body.splice(
|
|
147
|
-
index + 1,
|
|
148
|
-
0,
|
|
149
|
-
...after.map((x) => {
|
|
150
|
-
return {
|
|
151
|
-
type: "VariableDeclaration",
|
|
152
|
-
declarations: [clone(x)],
|
|
153
|
-
kind: object.kind,
|
|
154
|
-
};
|
|
155
|
-
})
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
object.declarations.length = 1;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export default class Preparation extends Transform {
|
|
164
|
-
constructor(o) {
|
|
165
|
-
super(o, ObfuscateOrder.Preparation);
|
|
166
|
-
|
|
167
|
-
this.before.push(new Block(o));
|
|
168
|
-
this.before.push(new Label(o));
|
|
169
|
-
this.before.push(new ExplicitIdentifiers(o));
|
|
170
|
-
this.before.push(new ExplicitDeclarations(o));
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
match() {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import JsConfuser from "../../../src/index";
|
|
2
|
-
|
|
3
|
-
it("should obfuscate for loops (ControlFlowObfuscation)", async () => {
|
|
4
|
-
var code = `
|
|
5
|
-
var array = [];
|
|
6
|
-
|
|
7
|
-
for ( var i = 1; i <= 10; i++ ) {
|
|
8
|
-
array.push(i);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
input(array);
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
|
-
var output = await JsConfuser(code, {
|
|
15
|
-
target: "browser",
|
|
16
|
-
controlFlowFlattening: true,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
expect(output).toContain("switch");
|
|
20
|
-
|
|
21
|
-
function input(array) {
|
|
22
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
eval(output);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("should obfuscate while loops (ControlFlowObfuscation)", async () => {
|
|
29
|
-
var code = `
|
|
30
|
-
var array = [];
|
|
31
|
-
var i = 1;
|
|
32
|
-
|
|
33
|
-
while ( i <= 10 ) {
|
|
34
|
-
array.push(i);
|
|
35
|
-
i++
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
input(array);
|
|
39
|
-
`;
|
|
40
|
-
|
|
41
|
-
var output = await JsConfuser(code, {
|
|
42
|
-
target: "browser",
|
|
43
|
-
controlFlowFlattening: true,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
expect(output).toContain("switch");
|
|
47
|
-
|
|
48
|
-
function input(array) {
|
|
49
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
eval(output);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("should work with break statements (ControlFlowObfuscation)", async () => {
|
|
56
|
-
var code = `
|
|
57
|
-
|
|
58
|
-
var TEST_ARRAY = [];
|
|
59
|
-
|
|
60
|
-
for ( var i =1; true; i++ ) {
|
|
61
|
-
if ( i == 11 ) {
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
TEST_ARRAY.push(i);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
input(TEST_ARRAY);
|
|
68
|
-
`;
|
|
69
|
-
|
|
70
|
-
var output = await JsConfuser(code, {
|
|
71
|
-
target: "browser",
|
|
72
|
-
controlFlowFlattening: true,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
expect(output).toContain("switch");
|
|
76
|
-
expect(output).toContain("while");
|
|
77
|
-
|
|
78
|
-
function input(array) {
|
|
79
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
eval(output);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("should not obfuscate code with `let` (Lexically bound variables, ControlFlowObfuscation)", async () => {
|
|
86
|
-
var code = `
|
|
87
|
-
var array=[];
|
|
88
|
-
for ( let i =1; i <= 10; i++ ) {
|
|
89
|
-
array.push(i);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
input(array);
|
|
93
|
-
`;
|
|
94
|
-
|
|
95
|
-
var output = await JsConfuser(code, {
|
|
96
|
-
target: "node",
|
|
97
|
-
controlFlowFlattening: true,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
expect(output).not.toContain("switch");
|
|
101
|
-
});
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import JsConfuser from "../../../src/index";
|
|
2
|
-
|
|
3
|
-
it("should obfuscate numbered switch statements (SwitchCaseObfuscation)", async () => {
|
|
4
|
-
var code = `
|
|
5
|
-
var array = [];
|
|
6
|
-
|
|
7
|
-
function runOnce(stateParam){
|
|
8
|
-
switch(stateParam){
|
|
9
|
-
case 1: array.push(1, 2, 3); break;
|
|
10
|
-
case 2: array.push(4, 5, 6); break;
|
|
11
|
-
case 3: array.push(7, 8, 9); break;
|
|
12
|
-
case 4: array.push(10); break;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
runOnce(1);
|
|
17
|
-
runOnce(2);
|
|
18
|
-
runOnce(3);
|
|
19
|
-
runOnce(4);
|
|
20
|
-
|
|
21
|
-
input(array);
|
|
22
|
-
`;
|
|
23
|
-
|
|
24
|
-
var output = await JsConfuser(code, {
|
|
25
|
-
target: "browser",
|
|
26
|
-
controlFlowFlattening: true,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
expect(
|
|
30
|
-
output.includes("case 1:") &&
|
|
31
|
-
output.includes("case 2:") &&
|
|
32
|
-
output.includes("case 3:") &&
|
|
33
|
-
output.includes("case 4:")
|
|
34
|
-
).toStrictEqual(false);
|
|
35
|
-
|
|
36
|
-
function input(array) {
|
|
37
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
eval(output);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("should not obfuscate switch statements with complex discriminants (SwitchCaseObfuscation)", async () => {
|
|
44
|
-
var code = `
|
|
45
|
-
var array = [];
|
|
46
|
-
|
|
47
|
-
function runOnce(stateParam){
|
|
48
|
-
switch(stateParam || 0){
|
|
49
|
-
case 1: array.push(1, 2, 3); break;
|
|
50
|
-
case 2: array.push(4, 5, 6); break;
|
|
51
|
-
case 3: array.push(7, 8, 9); break;
|
|
52
|
-
case 4: array.push(10); break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
runOnce(1);
|
|
57
|
-
runOnce(2);
|
|
58
|
-
runOnce(3);
|
|
59
|
-
runOnce(4);
|
|
60
|
-
|
|
61
|
-
input(array);
|
|
62
|
-
`;
|
|
63
|
-
|
|
64
|
-
var output = await JsConfuser(code, {
|
|
65
|
-
target: "browser",
|
|
66
|
-
controlFlowFlattening: true,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
expect(output).toContain("stateParam||0");
|
|
70
|
-
|
|
71
|
-
function input(array) {
|
|
72
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
eval(output);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// https://github.com/MichaelXF/js-confuser/issues/41
|
|
79
|
-
it("Not apply to switch statements with default cases", async ()=>{
|
|
80
|
-
|
|
81
|
-
var code = `
|
|
82
|
-
var array = [];
|
|
83
|
-
|
|
84
|
-
function runOnce(stateParam){
|
|
85
|
-
switch(stateParam){
|
|
86
|
-
case 1: array.push(1, 2, 3); break;
|
|
87
|
-
case 2: array.push(4, 5, 6); break;
|
|
88
|
-
case 3: array.push(7, 8, 9); break;
|
|
89
|
-
default: array.push(10); break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
runOnce(1);
|
|
94
|
-
runOnce(2);
|
|
95
|
-
runOnce(3);
|
|
96
|
-
runOnce(-1); // default case
|
|
97
|
-
|
|
98
|
-
input(array);
|
|
99
|
-
`;
|
|
100
|
-
|
|
101
|
-
var output = await JsConfuser(code, {
|
|
102
|
-
target: "browser",
|
|
103
|
-
controlFlowFlattening: true,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
expect(
|
|
107
|
-
output.includes("case 1:") &&
|
|
108
|
-
output.includes("case 2:") &&
|
|
109
|
-
output.includes("case 3:")
|
|
110
|
-
).toStrictEqual(true);
|
|
111
|
-
|
|
112
|
-
function input(array) {
|
|
113
|
-
expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
eval(output);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import JsConfuser from "../../src/index";
|
|
2
|
-
|
|
3
|
-
it("should put functions into eval statements", async () => {
|
|
4
|
-
var code = `
|
|
5
|
-
function TEST_FUNCTION(){
|
|
6
|
-
}
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
var output = await JsConfuser(code, { target: "node", eval: true });
|
|
10
|
-
|
|
11
|
-
expect(output).toContain("eval(");
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("should put functions into eval statements and have same result", async () => {
|
|
15
|
-
var code = `
|
|
16
|
-
function TEST_FUNCTION(){
|
|
17
|
-
input(100)
|
|
18
|
-
}
|
|
19
|
-
TEST_FUNCTION();
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
var output = await JsConfuser(code, { target: "node", eval: true });
|
|
23
|
-
|
|
24
|
-
expect(output).toContain("eval(");
|
|
25
|
-
|
|
26
|
-
var value = "never_called",
|
|
27
|
-
input = (valueIn) => (value = valueIn);
|
|
28
|
-
eval(output);
|
|
29
|
-
|
|
30
|
-
expect(value).toStrictEqual(100);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should move function declarations to the top of the block", async () => {
|
|
34
|
-
var code = `
|
|
35
|
-
TEST_FUNCTION();
|
|
36
|
-
function TEST_FUNCTION(){
|
|
37
|
-
input(100)
|
|
38
|
-
}
|
|
39
|
-
`;
|
|
40
|
-
|
|
41
|
-
var output = await JsConfuser(code, { target: "node", eval: true });
|
|
42
|
-
|
|
43
|
-
expect(output).toContain("eval(");
|
|
44
|
-
|
|
45
|
-
var value = "never_called",
|
|
46
|
-
input = (valueIn) => (value = valueIn);
|
|
47
|
-
eval(output);
|
|
48
|
-
|
|
49
|
-
expect(value).toStrictEqual(100);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("should work with Integrity also enabled", async () => {
|
|
53
|
-
var code = `
|
|
54
|
-
input("Hello World")
|
|
55
|
-
`;
|
|
56
|
-
|
|
57
|
-
var output = await JsConfuser(code, {
|
|
58
|
-
target: "node",
|
|
59
|
-
compact: false,
|
|
60
|
-
eval: true,
|
|
61
|
-
lock: {
|
|
62
|
-
integrity: true,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
expect(output).toContain("eval(");
|
|
67
|
-
|
|
68
|
-
var value = "never_called",
|
|
69
|
-
input = (valueIn) => (value = valueIn);
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
eval(output);
|
|
73
|
-
} catch (e) {
|
|
74
|
-
expect(e).toStrictEqual(undefined);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
expect(value).toStrictEqual("Hello World");
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("should work on async functions", async () => {
|
|
81
|
-
var output = await JsConfuser(
|
|
82
|
-
`
|
|
83
|
-
async function myFunction(){
|
|
84
|
-
return "Correct Value";
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
(async ()=>{
|
|
88
|
-
TEST_FUNCTION( await myFunction() );
|
|
89
|
-
})();
|
|
90
|
-
`,
|
|
91
|
-
{ target: "node", eval: true }
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
expect(output).toContain("eval");
|
|
95
|
-
|
|
96
|
-
var wasCalled = false;
|
|
97
|
-
|
|
98
|
-
function TEST_FUNCTION(value) {
|
|
99
|
-
wasCalled = true;
|
|
100
|
-
expect(value).toStrictEqual("Correct Value");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
eval(output);
|
|
104
|
-
|
|
105
|
-
setTimeout(() => {
|
|
106
|
-
expect(wasCalled).toStrictEqual(true);
|
|
107
|
-
}, 1000);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("should work on generator functions", async () => {
|
|
111
|
-
var output = await JsConfuser(
|
|
112
|
-
`
|
|
113
|
-
function* myFunction(){
|
|
114
|
-
yield "Correct Value";
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const gen = myFunction();
|
|
118
|
-
|
|
119
|
-
TEST_OUTPUT = gen.next().value;
|
|
120
|
-
`,
|
|
121
|
-
{ target: "node", eval: true }
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
expect(output).toContain("eval");
|
|
125
|
-
|
|
126
|
-
var TEST_OUTPUT;
|
|
127
|
-
|
|
128
|
-
eval(output);
|
|
129
|
-
|
|
130
|
-
expect(TEST_OUTPUT).toStrictEqual("Correct Value");
|
|
131
|
-
});
|