js-confuser 2.0.0 → 2.0.1
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/ISSUE_TEMPLATE/bug_report.md +43 -43
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/.github/workflows/node.js.yml +28 -28
- package/.prettierrc +4 -4
- package/CHANGELOG.md +1015 -987
- package/CODE_OF_CONDUCT.md +131 -131
- package/CONTRIBUTING.md +52 -52
- package/LICENSE +21 -21
- package/Migration.md +72 -72
- package/README.md +86 -86
- package/dist/constants.js +43 -43
- package/dist/index.js +14 -23
- package/dist/obfuscator.js +31 -25
- package/dist/order.js +4 -4
- package/dist/presets.js +31 -31
- package/dist/templates/integrityTemplate.js +4 -4
- package/dist/templates/template.js +1 -2
- package/dist/transforms/astScrambler.js +1 -2
- package/dist/transforms/calculator.js +1 -2
- package/dist/transforms/controlFlowFlattening.js +60 -41
- package/dist/transforms/deadCode.js +1 -2
- package/dist/transforms/dispatcher.js +4 -5
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +1 -2
- package/dist/transforms/extraction/objectExtraction.js +1 -2
- package/dist/transforms/finalizer.js +1 -2
- package/dist/transforms/flatten.js +1 -2
- package/dist/transforms/identifier/globalConcealing.js +15 -2
- package/dist/transforms/identifier/movedDeclarations.js +8 -7
- package/dist/transforms/identifier/renameVariables.js +7 -7
- package/dist/transforms/lock/integrity.js +8 -9
- package/dist/transforms/lock/lock.js +1 -2
- package/dist/transforms/minify.js +11 -29
- package/dist/transforms/opaquePredicates.js +1 -2
- package/dist/transforms/pack.js +1 -2
- package/dist/transforms/plugin.js +18 -19
- package/dist/transforms/preparation.js +16 -16
- package/dist/transforms/renameLabels.js +1 -2
- package/dist/transforms/rgf.js +8 -9
- package/dist/transforms/shuffle.js +1 -2
- package/dist/transforms/string/encoding.js +1 -2
- package/dist/transforms/string/stringCompression.js +3 -4
- package/dist/transforms/string/stringConcealing.js +1 -2
- package/dist/transforms/string/stringEncoding.js +1 -2
- package/dist/transforms/variableMasking.js +1 -2
- package/dist/utils/NameGen.js +2 -2
- package/dist/utils/PredicateGen.js +1 -2
- package/dist/utils/ast-utils.js +87 -88
- package/dist/utils/function-utils.js +8 -8
- package/dist/utils/node.js +5 -6
- package/dist/utils/object-utils.js +4 -4
- package/dist/utils/random-utils.js +20 -20
- package/dist/utils/static-utils.js +1 -2
- package/dist/validateOptions.js +4 -7
- package/index.d.ts +17 -17
- package/package.json +61 -59
- package/src/constants.ts +168 -168
- package/src/index.ts +118 -118
- package/src/obfuscationResult.ts +49 -49
- package/src/obfuscator.ts +501 -497
- package/src/options.ts +407 -407
- package/src/order.ts +54 -54
- package/src/presets.ts +125 -125
- package/src/templates/bufferToStringTemplate.ts +57 -57
- package/src/templates/deadCodeTemplates.ts +1185 -1185
- package/src/templates/getGlobalTemplate.ts +76 -76
- package/src/templates/integrityTemplate.ts +64 -64
- package/src/templates/setFunctionLengthTemplate.ts +11 -11
- package/src/templates/stringCompressionTemplate.ts +20 -20
- package/src/templates/tamperProtectionTemplates.ts +120 -120
- package/src/templates/template.ts +224 -224
- package/src/transforms/astScrambler.ts +99 -99
- package/src/transforms/calculator.ts +99 -99
- package/src/transforms/controlFlowFlattening.ts +1716 -1680
- package/src/transforms/deadCode.ts +82 -82
- package/src/transforms/dispatcher.ts +450 -450
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +156 -158
- package/src/transforms/extraction/objectExtraction.ts +186 -186
- package/src/transforms/finalizer.ts +74 -74
- package/src/transforms/flatten.ts +421 -418
- package/src/transforms/identifier/globalConcealing.ts +315 -295
- package/src/transforms/identifier/movedDeclarations.ts +252 -251
- package/src/transforms/identifier/renameVariables.ts +328 -321
- package/src/transforms/lock/integrity.ts +117 -117
- package/src/transforms/lock/lock.ts +418 -418
- package/src/transforms/minify.ts +615 -629
- package/src/transforms/opaquePredicates.ts +100 -100
- package/src/transforms/pack.ts +239 -239
- package/src/transforms/plugin.ts +173 -173
- package/src/transforms/preparation.ts +349 -347
- package/src/transforms/renameLabels.ts +175 -175
- package/src/transforms/rgf.ts +322 -322
- package/src/transforms/shuffle.ts +82 -82
- package/src/transforms/string/encoding.ts +144 -144
- package/src/transforms/string/stringCompression.ts +128 -128
- package/src/transforms/string/stringConcealing.ts +312 -312
- package/src/transforms/string/stringEncoding.ts +80 -80
- package/src/transforms/string/stringSplitting.ts +77 -77
- package/src/transforms/variableMasking.ts +257 -257
- package/src/utils/IntGen.ts +33 -33
- package/src/utils/NameGen.ts +116 -116
- package/src/utils/PredicateGen.ts +61 -61
- package/src/utils/ast-utils.ts +663 -663
- package/src/utils/function-utils.ts +50 -50
- package/src/utils/gen-utils.ts +48 -48
- package/src/utils/node.ts +78 -78
- package/src/utils/object-utils.ts +21 -21
- package/src/utils/random-utils.ts +93 -93
- package/src/utils/static-utils.ts +66 -66
- package/src/validateOptions.ts +256 -259
- package/tsconfig.json +13 -14
- package/dist/probability.js +0 -1
- package/dist/transforms/functionOutlining.js +0 -230
- package/dist/utils/ControlObject.js +0 -125
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import { PluginArg, PluginObject } from "./plugin";
|
|
2
|
-
import { Order } from "../order";
|
|
3
|
-
import { NodePath } from "@babel/traverse";
|
|
4
|
-
import * as t from "@babel/types";
|
|
5
|
-
import { chance, getRandomString } from "../utils/random-utils";
|
|
6
|
-
import PredicateGen from "../utils/PredicateGen";
|
|
7
|
-
|
|
8
|
-
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
9
|
-
const me = Plugin(Order.OpaquePredicates, {
|
|
10
|
-
changeData: {
|
|
11
|
-
opaquePredicates: 0,
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const predicateGen = new PredicateGen(me);
|
|
16
|
-
|
|
17
|
-
function createTruePredicate(path: NodePath) {
|
|
18
|
-
return predicateGen.generateTrueExpression(path);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let active = true;
|
|
22
|
-
let transformCount = 0;
|
|
23
|
-
function shouldTransform(path: NodePath) {
|
|
24
|
-
if (!active) return false;
|
|
25
|
-
if (path.find((p) => me.isSkipped(p))) return false;
|
|
26
|
-
|
|
27
|
-
if (!me.computeProbabilityMap(me.options.opaquePredicates)) return false;
|
|
28
|
-
|
|
29
|
-
transformCount++;
|
|
30
|
-
|
|
31
|
-
const depth = path.getAncestry().length;
|
|
32
|
-
|
|
33
|
-
return chance(500 - transformCount - depth * 100);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function wrapWithPredicate(path: NodePath) {
|
|
37
|
-
let newExpression = t.logicalExpression(
|
|
38
|
-
"&&",
|
|
39
|
-
createTruePredicate(path),
|
|
40
|
-
path.node as t.Expression
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
me.changeData.opaquePredicates++;
|
|
44
|
-
|
|
45
|
-
path.replaceWith(me.skip(newExpression));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
visitor: {
|
|
50
|
-
// if (test) -> if (PREDICATE() && test) {}
|
|
51
|
-
IfStatement: {
|
|
52
|
-
exit(path) {
|
|
53
|
-
if (!shouldTransform(path)) return;
|
|
54
|
-
wrapWithPredicate(path.get("test"));
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
// test ? a : b -> PREDICATE() && test ? a : b
|
|
59
|
-
ConditionalExpression: {
|
|
60
|
-
exit(path) {
|
|
61
|
-
if (!shouldTransform(path)) return;
|
|
62
|
-
|
|
63
|
-
wrapWithPredicate(path.get("test"));
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
// case test: -> case PREDICATE() && test:
|
|
68
|
-
SwitchCase: {
|
|
69
|
-
exit(path) {
|
|
70
|
-
if (!path.node.test) return;
|
|
71
|
-
if (!shouldTransform(path)) return;
|
|
72
|
-
|
|
73
|
-
wrapWithPredicate(path.get("test"));
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
// return test -> if (predicate()) { return test } else { return fake }
|
|
78
|
-
ReturnStatement: {
|
|
79
|
-
exit(path) {
|
|
80
|
-
if (!path.node.argument) return;
|
|
81
|
-
if (!shouldTransform(path)) return;
|
|
82
|
-
|
|
83
|
-
me.changeData.opaquePredicates++;
|
|
84
|
-
|
|
85
|
-
path.replaceWith(
|
|
86
|
-
t.ifStatement(
|
|
87
|
-
createTruePredicate(path),
|
|
88
|
-
t.blockStatement([t.returnStatement(path.node.argument)]),
|
|
89
|
-
t.blockStatement([
|
|
90
|
-
t.returnStatement(t.stringLiteral(getRandomString(6))),
|
|
91
|
-
])
|
|
92
|
-
)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
me.skip(path);
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
};
|
|
1
|
+
import { PluginArg, PluginObject } from "./plugin";
|
|
2
|
+
import { Order } from "../order";
|
|
3
|
+
import { NodePath } from "@babel/traverse";
|
|
4
|
+
import * as t from "@babel/types";
|
|
5
|
+
import { chance, getRandomString } from "../utils/random-utils";
|
|
6
|
+
import PredicateGen from "../utils/PredicateGen";
|
|
7
|
+
|
|
8
|
+
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
9
|
+
const me = Plugin(Order.OpaquePredicates, {
|
|
10
|
+
changeData: {
|
|
11
|
+
opaquePredicates: 0,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const predicateGen = new PredicateGen(me);
|
|
16
|
+
|
|
17
|
+
function createTruePredicate(path: NodePath) {
|
|
18
|
+
return predicateGen.generateTrueExpression(path);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let active = true;
|
|
22
|
+
let transformCount = 0;
|
|
23
|
+
function shouldTransform(path: NodePath) {
|
|
24
|
+
if (!active) return false;
|
|
25
|
+
if (path.find((p) => me.isSkipped(p))) return false;
|
|
26
|
+
|
|
27
|
+
if (!me.computeProbabilityMap(me.options.opaquePredicates)) return false;
|
|
28
|
+
|
|
29
|
+
transformCount++;
|
|
30
|
+
|
|
31
|
+
const depth = path.getAncestry().length;
|
|
32
|
+
|
|
33
|
+
return chance(500 - transformCount - depth * 100);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function wrapWithPredicate(path: NodePath) {
|
|
37
|
+
let newExpression = t.logicalExpression(
|
|
38
|
+
"&&",
|
|
39
|
+
createTruePredicate(path),
|
|
40
|
+
path.node as t.Expression
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
me.changeData.opaquePredicates++;
|
|
44
|
+
|
|
45
|
+
path.replaceWith(me.skip(newExpression));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
visitor: {
|
|
50
|
+
// if (test) -> if (PREDICATE() && test) {}
|
|
51
|
+
IfStatement: {
|
|
52
|
+
exit(path) {
|
|
53
|
+
if (!shouldTransform(path)) return;
|
|
54
|
+
wrapWithPredicate(path.get("test"));
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// test ? a : b -> PREDICATE() && test ? a : b
|
|
59
|
+
ConditionalExpression: {
|
|
60
|
+
exit(path) {
|
|
61
|
+
if (!shouldTransform(path)) return;
|
|
62
|
+
|
|
63
|
+
wrapWithPredicate(path.get("test"));
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// case test: -> case PREDICATE() && test:
|
|
68
|
+
SwitchCase: {
|
|
69
|
+
exit(path) {
|
|
70
|
+
if (!path.node.test) return;
|
|
71
|
+
if (!shouldTransform(path)) return;
|
|
72
|
+
|
|
73
|
+
wrapWithPredicate(path.get("test"));
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// return test -> if (predicate()) { return test } else { return fake }
|
|
78
|
+
ReturnStatement: {
|
|
79
|
+
exit(path) {
|
|
80
|
+
if (!path.node.argument) return;
|
|
81
|
+
if (!shouldTransform(path)) return;
|
|
82
|
+
|
|
83
|
+
me.changeData.opaquePredicates++;
|
|
84
|
+
|
|
85
|
+
path.replaceWith(
|
|
86
|
+
t.ifStatement(
|
|
87
|
+
createTruePredicate(path),
|
|
88
|
+
t.blockStatement([t.returnStatement(path.node.argument)]),
|
|
89
|
+
t.blockStatement([
|
|
90
|
+
t.returnStatement(t.stringLiteral(getRandomString(6))),
|
|
91
|
+
])
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
me.skip(path);
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
};
|
package/src/transforms/pack.ts
CHANGED
|
@@ -1,239 +1,239 @@
|
|
|
1
|
-
import * as t from "@babel/types";
|
|
2
|
-
import Obfuscator from "../obfuscator";
|
|
3
|
-
import Template from "../templates/template";
|
|
4
|
-
import {
|
|
5
|
-
isDefiningIdentifier,
|
|
6
|
-
isModifiedIdentifier,
|
|
7
|
-
isVariableIdentifier,
|
|
8
|
-
} from "../utils/ast-utils";
|
|
9
|
-
import {
|
|
10
|
-
GEN_NODE,
|
|
11
|
-
NodeSymbol,
|
|
12
|
-
reservedIdentifiers,
|
|
13
|
-
reservedNodeModuleIdentifiers,
|
|
14
|
-
variableFunctionName,
|
|
15
|
-
WITH_STATEMENT,
|
|
16
|
-
} from "../constants";
|
|
17
|
-
import { PluginArg, PluginObject } from "./plugin";
|
|
18
|
-
import { Order } from "../order";
|
|
19
|
-
|
|
20
|
-
export interface PackInterface {
|
|
21
|
-
objectName: string;
|
|
22
|
-
mappings: Map<string, string>;
|
|
23
|
-
setterPropsNeeded: Set<string>;
|
|
24
|
-
typeofMappings: Map<string, string>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default function pack({ Plugin }: PluginArg): PluginObject {
|
|
28
|
-
const me = Plugin(Order.Pack, {
|
|
29
|
-
changeData: {
|
|
30
|
-
globals: 0,
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// RGF functions will re-use parent Pack Interface
|
|
35
|
-
let packInterface = me.obfuscator.parentObfuscator?.packInterface;
|
|
36
|
-
|
|
37
|
-
// Create new Pack Interface (root)
|
|
38
|
-
if (!packInterface) {
|
|
39
|
-
packInterface = {
|
|
40
|
-
objectName: me.obfuscator.nameGen.generate(),
|
|
41
|
-
mappings: new Map<string, string>(),
|
|
42
|
-
setterPropsNeeded: new Set<string>(),
|
|
43
|
-
typeofMappings: new Map<string, string>(),
|
|
44
|
-
};
|
|
45
|
-
me.obfuscator.packInterface = packInterface;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { objectName, mappings, setterPropsNeeded, typeofMappings } =
|
|
49
|
-
packInterface;
|
|
50
|
-
|
|
51
|
-
const prependNodes: t.Statement[] = [];
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
// Transform identifiers, preserve import statements
|
|
55
|
-
visitor: {
|
|
56
|
-
ImportDeclaration(path) {
|
|
57
|
-
prependNodes.push(path.node);
|
|
58
|
-
path.remove();
|
|
59
|
-
|
|
60
|
-
// Ensure bindings are removed -> variable becomes a global -> added to mappings object
|
|
61
|
-
path.scope.crawl();
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
// TODO: Add support for export statements
|
|
65
|
-
"ExportNamedDeclaration|ExportDefaultDeclaration|ExportAllDeclaration"(
|
|
66
|
-
path
|
|
67
|
-
) {
|
|
68
|
-
me.error("Export statements are not supported in packed code.");
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
Program(path) {
|
|
72
|
-
path.scope.crawl();
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
Identifier: {
|
|
76
|
-
exit(path) {
|
|
77
|
-
if (!isVariableIdentifier(path)) return;
|
|
78
|
-
|
|
79
|
-
if (isDefiningIdentifier(path)) return;
|
|
80
|
-
if ((path.node as NodeSymbol)[GEN_NODE]) return;
|
|
81
|
-
if ((path.node as NodeSymbol)[WITH_STATEMENT]) return;
|
|
82
|
-
|
|
83
|
-
const identifierName = path.node.name;
|
|
84
|
-
if (reservedIdentifiers.has(identifierName)) return;
|
|
85
|
-
if (
|
|
86
|
-
me.options.target === "node" &&
|
|
87
|
-
reservedNodeModuleIdentifiers.has(identifierName)
|
|
88
|
-
) {
|
|
89
|
-
// Allow module.exports and require
|
|
90
|
-
} else {
|
|
91
|
-
if (me.options.globalVariables.has(identifierName)) return;
|
|
92
|
-
}
|
|
93
|
-
if (identifierName === variableFunctionName) return;
|
|
94
|
-
if (identifierName === objectName) return;
|
|
95
|
-
|
|
96
|
-
if (!path.scope.hasGlobal(identifierName)) return;
|
|
97
|
-
if (path.scope.hasBinding(identifierName)) return;
|
|
98
|
-
|
|
99
|
-
// Check user's custom implementation
|
|
100
|
-
if (!me.computeProbabilityMap(me.options.pack, identifierName))
|
|
101
|
-
return;
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
path.key === "argument" &&
|
|
105
|
-
path.parentPath.isUnaryExpression({ operator: "typeof" })
|
|
106
|
-
) {
|
|
107
|
-
const unaryExpression = path.parentPath;
|
|
108
|
-
|
|
109
|
-
let propertyName = typeofMappings.get(identifierName);
|
|
110
|
-
if (!propertyName) {
|
|
111
|
-
propertyName = me.obfuscator.nameGen.generate();
|
|
112
|
-
typeofMappings.set(identifierName, propertyName);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
unaryExpression.replaceWith(
|
|
116
|
-
t.memberExpression(
|
|
117
|
-
t.identifier(objectName),
|
|
118
|
-
t.stringLiteral(propertyName),
|
|
119
|
-
true
|
|
120
|
-
)
|
|
121
|
-
);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
let propertyName = mappings.get(identifierName);
|
|
126
|
-
if (!propertyName) {
|
|
127
|
-
propertyName = me.obfuscator.nameGen.generate();
|
|
128
|
-
mappings.set(identifierName, propertyName);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Only add setter if the identifier is modified
|
|
132
|
-
if (isModifiedIdentifier(path)) {
|
|
133
|
-
setterPropsNeeded.add(identifierName);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
path.replaceWith(
|
|
137
|
-
t.memberExpression(
|
|
138
|
-
t.identifier(objectName),
|
|
139
|
-
t.stringLiteral(propertyName),
|
|
140
|
-
true
|
|
141
|
-
)
|
|
142
|
-
);
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
// Final AST handler
|
|
148
|
-
// Very last step in the obfuscation process
|
|
149
|
-
finalASTHandler(ast) {
|
|
150
|
-
if (me.obfuscator.parentObfuscator) return ast; // Only for root obfuscator
|
|
151
|
-
|
|
152
|
-
// Create object expression
|
|
153
|
-
// Very similar to flatten, maybe refactor to use the same code
|
|
154
|
-
const objectProperties: t.ObjectMethod[] = [];
|
|
155
|
-
|
|
156
|
-
me.changeData.globals = mappings.size;
|
|
157
|
-
|
|
158
|
-
for (const [identifierName, propertyName] of mappings) {
|
|
159
|
-
// get identifier() { return identifier; }
|
|
160
|
-
objectProperties.push(
|
|
161
|
-
t.objectMethod(
|
|
162
|
-
"get",
|
|
163
|
-
t.stringLiteral(propertyName),
|
|
164
|
-
[],
|
|
165
|
-
t.blockStatement([t.returnStatement(t.identifier(identifierName))])
|
|
166
|
-
)
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
// Only add setter if the identifier is modified
|
|
170
|
-
if (setterPropsNeeded.has(identifierName)) {
|
|
171
|
-
// set identifier(value) { return identifier = value; }
|
|
172
|
-
objectProperties.push(
|
|
173
|
-
t.objectMethod(
|
|
174
|
-
"set",
|
|
175
|
-
t.stringLiteral(propertyName),
|
|
176
|
-
[t.identifier(objectName)],
|
|
177
|
-
t.blockStatement([
|
|
178
|
-
t.returnStatement(
|
|
179
|
-
t.assignmentExpression(
|
|
180
|
-
"=",
|
|
181
|
-
t.identifier(identifierName),
|
|
182
|
-
t.identifier(objectName)
|
|
183
|
-
)
|
|
184
|
-
),
|
|
185
|
-
])
|
|
186
|
-
)
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Add typeof mappings
|
|
192
|
-
for (const [identifierName, propertyName] of typeofMappings) {
|
|
193
|
-
// get typeof identifier() { return typeof identifier; }
|
|
194
|
-
objectProperties.push(
|
|
195
|
-
t.objectMethod(
|
|
196
|
-
"get",
|
|
197
|
-
t.stringLiteral(propertyName),
|
|
198
|
-
[],
|
|
199
|
-
t.blockStatement([
|
|
200
|
-
t.returnStatement(
|
|
201
|
-
t.unaryExpression("typeof", t.identifier(identifierName))
|
|
202
|
-
),
|
|
203
|
-
])
|
|
204
|
-
)
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const objectExpression = t.objectExpression(objectProperties);
|
|
209
|
-
|
|
210
|
-
// Convert last expression to return statement
|
|
211
|
-
// This preserves the last expression in the packed code
|
|
212
|
-
var lastStatement = ast.program.body.at(-1);
|
|
213
|
-
if (lastStatement && t.isExpressionStatement(lastStatement)) {
|
|
214
|
-
Object.assign(
|
|
215
|
-
lastStatement,
|
|
216
|
-
|
|
217
|
-
t.returnStatement(lastStatement.expression)
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const outputCode = Obfuscator.generateCode(ast, {
|
|
222
|
-
...me.obfuscator.options,
|
|
223
|
-
compact: true,
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
var newAST = new Template(`
|
|
227
|
-
{prependNodes}
|
|
228
|
-
Function({objectName}, {outputCode})({objectExpression});
|
|
229
|
-
`).file({
|
|
230
|
-
objectName: () => t.stringLiteral(objectName),
|
|
231
|
-
outputCode: () => t.stringLiteral(outputCode),
|
|
232
|
-
objectExpression: objectExpression,
|
|
233
|
-
prependNodes: prependNodes,
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
return newAST;
|
|
237
|
-
},
|
|
238
|
-
};
|
|
239
|
-
}
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import Obfuscator from "../obfuscator";
|
|
3
|
+
import Template from "../templates/template";
|
|
4
|
+
import {
|
|
5
|
+
isDefiningIdentifier,
|
|
6
|
+
isModifiedIdentifier,
|
|
7
|
+
isVariableIdentifier,
|
|
8
|
+
} from "../utils/ast-utils";
|
|
9
|
+
import {
|
|
10
|
+
GEN_NODE,
|
|
11
|
+
NodeSymbol,
|
|
12
|
+
reservedIdentifiers,
|
|
13
|
+
reservedNodeModuleIdentifiers,
|
|
14
|
+
variableFunctionName,
|
|
15
|
+
WITH_STATEMENT,
|
|
16
|
+
} from "../constants";
|
|
17
|
+
import { PluginArg, PluginObject } from "./plugin";
|
|
18
|
+
import { Order } from "../order";
|
|
19
|
+
|
|
20
|
+
export interface PackInterface {
|
|
21
|
+
objectName: string;
|
|
22
|
+
mappings: Map<string, string>;
|
|
23
|
+
setterPropsNeeded: Set<string>;
|
|
24
|
+
typeofMappings: Map<string, string>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function pack({ Plugin }: PluginArg): PluginObject {
|
|
28
|
+
const me = Plugin(Order.Pack, {
|
|
29
|
+
changeData: {
|
|
30
|
+
globals: 0,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// RGF functions will re-use parent Pack Interface
|
|
35
|
+
let packInterface = me.obfuscator.parentObfuscator?.packInterface;
|
|
36
|
+
|
|
37
|
+
// Create new Pack Interface (root)
|
|
38
|
+
if (!packInterface) {
|
|
39
|
+
packInterface = {
|
|
40
|
+
objectName: me.obfuscator.nameGen.generate(),
|
|
41
|
+
mappings: new Map<string, string>(),
|
|
42
|
+
setterPropsNeeded: new Set<string>(),
|
|
43
|
+
typeofMappings: new Map<string, string>(),
|
|
44
|
+
};
|
|
45
|
+
me.obfuscator.packInterface = packInterface;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { objectName, mappings, setterPropsNeeded, typeofMappings } =
|
|
49
|
+
packInterface;
|
|
50
|
+
|
|
51
|
+
const prependNodes: t.Statement[] = [];
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
// Transform identifiers, preserve import statements
|
|
55
|
+
visitor: {
|
|
56
|
+
ImportDeclaration(path) {
|
|
57
|
+
prependNodes.push(path.node);
|
|
58
|
+
path.remove();
|
|
59
|
+
|
|
60
|
+
// Ensure bindings are removed -> variable becomes a global -> added to mappings object
|
|
61
|
+
path.scope.crawl();
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
// TODO: Add support for export statements
|
|
65
|
+
"ExportNamedDeclaration|ExportDefaultDeclaration|ExportAllDeclaration"(
|
|
66
|
+
path
|
|
67
|
+
) {
|
|
68
|
+
me.error("Export statements are not supported in packed code.");
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
Program(path) {
|
|
72
|
+
path.scope.crawl();
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
Identifier: {
|
|
76
|
+
exit(path) {
|
|
77
|
+
if (!isVariableIdentifier(path)) return;
|
|
78
|
+
|
|
79
|
+
if (isDefiningIdentifier(path)) return;
|
|
80
|
+
if ((path.node as NodeSymbol)[GEN_NODE]) return;
|
|
81
|
+
if ((path.node as NodeSymbol)[WITH_STATEMENT]) return;
|
|
82
|
+
|
|
83
|
+
const identifierName = path.node.name;
|
|
84
|
+
if (reservedIdentifiers.has(identifierName)) return;
|
|
85
|
+
if (
|
|
86
|
+
me.options.target === "node" &&
|
|
87
|
+
reservedNodeModuleIdentifiers.has(identifierName)
|
|
88
|
+
) {
|
|
89
|
+
// Allow module.exports and require
|
|
90
|
+
} else {
|
|
91
|
+
if (me.options.globalVariables.has(identifierName)) return;
|
|
92
|
+
}
|
|
93
|
+
if (identifierName === variableFunctionName) return;
|
|
94
|
+
if (identifierName === objectName) return;
|
|
95
|
+
|
|
96
|
+
if (!path.scope.hasGlobal(identifierName)) return;
|
|
97
|
+
if (path.scope.hasBinding(identifierName)) return;
|
|
98
|
+
|
|
99
|
+
// Check user's custom implementation
|
|
100
|
+
if (!me.computeProbabilityMap(me.options.pack, identifierName))
|
|
101
|
+
return;
|
|
102
|
+
|
|
103
|
+
if (
|
|
104
|
+
path.key === "argument" &&
|
|
105
|
+
path.parentPath.isUnaryExpression({ operator: "typeof" })
|
|
106
|
+
) {
|
|
107
|
+
const unaryExpression = path.parentPath;
|
|
108
|
+
|
|
109
|
+
let propertyName = typeofMappings.get(identifierName);
|
|
110
|
+
if (!propertyName) {
|
|
111
|
+
propertyName = me.obfuscator.nameGen.generate();
|
|
112
|
+
typeofMappings.set(identifierName, propertyName);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
unaryExpression.replaceWith(
|
|
116
|
+
t.memberExpression(
|
|
117
|
+
t.identifier(objectName),
|
|
118
|
+
t.stringLiteral(propertyName),
|
|
119
|
+
true
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let propertyName = mappings.get(identifierName);
|
|
126
|
+
if (!propertyName) {
|
|
127
|
+
propertyName = me.obfuscator.nameGen.generate();
|
|
128
|
+
mappings.set(identifierName, propertyName);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Only add setter if the identifier is modified
|
|
132
|
+
if (isModifiedIdentifier(path)) {
|
|
133
|
+
setterPropsNeeded.add(identifierName);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
path.replaceWith(
|
|
137
|
+
t.memberExpression(
|
|
138
|
+
t.identifier(objectName),
|
|
139
|
+
t.stringLiteral(propertyName),
|
|
140
|
+
true
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
// Final AST handler
|
|
148
|
+
// Very last step in the obfuscation process
|
|
149
|
+
finalASTHandler(ast) {
|
|
150
|
+
if (me.obfuscator.parentObfuscator) return ast; // Only for root obfuscator
|
|
151
|
+
|
|
152
|
+
// Create object expression
|
|
153
|
+
// Very similar to flatten, maybe refactor to use the same code
|
|
154
|
+
const objectProperties: t.ObjectMethod[] = [];
|
|
155
|
+
|
|
156
|
+
me.changeData.globals = mappings.size;
|
|
157
|
+
|
|
158
|
+
for (const [identifierName, propertyName] of mappings) {
|
|
159
|
+
// get identifier() { return identifier; }
|
|
160
|
+
objectProperties.push(
|
|
161
|
+
t.objectMethod(
|
|
162
|
+
"get",
|
|
163
|
+
t.stringLiteral(propertyName),
|
|
164
|
+
[],
|
|
165
|
+
t.blockStatement([t.returnStatement(t.identifier(identifierName))])
|
|
166
|
+
)
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Only add setter if the identifier is modified
|
|
170
|
+
if (setterPropsNeeded.has(identifierName)) {
|
|
171
|
+
// set identifier(value) { return identifier = value; }
|
|
172
|
+
objectProperties.push(
|
|
173
|
+
t.objectMethod(
|
|
174
|
+
"set",
|
|
175
|
+
t.stringLiteral(propertyName),
|
|
176
|
+
[t.identifier(objectName)],
|
|
177
|
+
t.blockStatement([
|
|
178
|
+
t.returnStatement(
|
|
179
|
+
t.assignmentExpression(
|
|
180
|
+
"=",
|
|
181
|
+
t.identifier(identifierName),
|
|
182
|
+
t.identifier(objectName)
|
|
183
|
+
)
|
|
184
|
+
),
|
|
185
|
+
])
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Add typeof mappings
|
|
192
|
+
for (const [identifierName, propertyName] of typeofMappings) {
|
|
193
|
+
// get typeof identifier() { return typeof identifier; }
|
|
194
|
+
objectProperties.push(
|
|
195
|
+
t.objectMethod(
|
|
196
|
+
"get",
|
|
197
|
+
t.stringLiteral(propertyName),
|
|
198
|
+
[],
|
|
199
|
+
t.blockStatement([
|
|
200
|
+
t.returnStatement(
|
|
201
|
+
t.unaryExpression("typeof", t.identifier(identifierName))
|
|
202
|
+
),
|
|
203
|
+
])
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const objectExpression = t.objectExpression(objectProperties);
|
|
209
|
+
|
|
210
|
+
// Convert last expression to return statement
|
|
211
|
+
// This preserves the last expression in the packed code
|
|
212
|
+
var lastStatement = ast.program.body.at(-1);
|
|
213
|
+
if (lastStatement && t.isExpressionStatement(lastStatement)) {
|
|
214
|
+
Object.assign(
|
|
215
|
+
lastStatement,
|
|
216
|
+
|
|
217
|
+
t.returnStatement(lastStatement.expression)
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const outputCode = Obfuscator.generateCode(ast, {
|
|
222
|
+
...me.obfuscator.options,
|
|
223
|
+
compact: true,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
var newAST = new Template(`
|
|
227
|
+
{prependNodes}
|
|
228
|
+
Function({objectName}, {outputCode})({objectExpression});
|
|
229
|
+
`).file({
|
|
230
|
+
objectName: () => t.stringLiteral(objectName),
|
|
231
|
+
outputCode: () => t.stringLiteral(outputCode),
|
|
232
|
+
objectExpression: objectExpression,
|
|
233
|
+
prependNodes: prependNodes,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
return newAST;
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|