js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +24 -6
  2. package/dist/constants.js +6 -2
  3. package/dist/index.js +12 -0
  4. package/dist/obfuscator.js +117 -6
  5. package/dist/order.js +0 -1
  6. package/dist/probability.js +1 -96
  7. package/dist/templates/getGlobalTemplate.js +4 -1
  8. package/dist/templates/stringCompressionTemplate.js +3 -3
  9. package/dist/templates/tamperProtectionTemplates.js +1 -1
  10. package/dist/templates/template.js +17 -12
  11. package/dist/transforms/controlFlowFlattening.js +2 -6
  12. package/dist/transforms/deadCode.js +8 -15
  13. package/dist/transforms/dispatcher.js +1 -2
  14. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
  15. package/dist/transforms/extraction/objectExtraction.js +1 -2
  16. package/dist/transforms/finalizer.js +1 -1
  17. package/dist/transforms/flatten.js +2 -19
  18. package/dist/transforms/identifier/globalConcealing.js +1 -2
  19. package/dist/transforms/identifier/movedDeclarations.js +12 -5
  20. package/dist/transforms/identifier/renameVariables.js +7 -6
  21. package/dist/transforms/lock/lock.js +9 -2
  22. package/dist/transforms/minify.js +14 -1
  23. package/dist/transforms/opaquePredicates.js +5 -6
  24. package/dist/transforms/pack.js +5 -0
  25. package/dist/transforms/plugin.js +20 -39
  26. package/dist/transforms/renameLabels.js +1 -2
  27. package/dist/transforms/rgf.js +29 -11
  28. package/dist/transforms/shuffle.js +10 -11
  29. package/dist/transforms/string/stringCompression.js +14 -10
  30. package/dist/transforms/string/stringConcealing.js +4 -4
  31. package/dist/transforms/string/stringEncoding.js +4 -2
  32. package/dist/transforms/string/stringSplitting.js +4 -2
  33. package/dist/transforms/variableMasking.js +1 -2
  34. package/dist/utils/NameGen.js +3 -2
  35. package/dist/utils/PredicateGen.js +62 -0
  36. package/dist/utils/ast-utils.js +24 -9
  37. package/dist/validateOptions.js +2 -2
  38. package/package.json +2 -2
  39. package/src/constants.ts +6 -5
  40. package/src/index.ts +1 -0
  41. package/src/obfuscator.ts +148 -7
  42. package/src/options.ts +14 -6
  43. package/src/order.ts +0 -2
  44. package/src/probability.ts +0 -110
  45. package/src/templates/getGlobalTemplate.ts +5 -1
  46. package/src/templates/stringCompressionTemplate.ts +4 -28
  47. package/src/templates/tamperProtectionTemplates.ts +7 -3
  48. package/src/templates/template.ts +5 -3
  49. package/src/transforms/controlFlowFlattening.ts +2 -7
  50. package/src/transforms/deadCode.ts +11 -23
  51. package/src/transforms/dispatcher.ts +1 -2
  52. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
  53. package/src/transforms/extraction/objectExtraction.ts +1 -2
  54. package/src/transforms/finalizer.ts +1 -1
  55. package/src/transforms/flatten.ts +3 -22
  56. package/src/transforms/identifier/globalConcealing.ts +4 -2
  57. package/src/transforms/identifier/movedDeclarations.ts +18 -6
  58. package/src/transforms/identifier/renameVariables.ts +10 -6
  59. package/src/transforms/lock/lock.ts +14 -3
  60. package/src/transforms/minify.ts +24 -2
  61. package/src/transforms/opaquePredicates.ts +5 -8
  62. package/src/transforms/pack.ts +6 -0
  63. package/src/transforms/plugin.ts +47 -69
  64. package/src/transforms/renameLabels.ts +1 -2
  65. package/src/transforms/rgf.ts +39 -14
  66. package/src/transforms/shuffle.ts +28 -26
  67. package/src/transforms/string/encoding.ts +1 -1
  68. package/src/transforms/string/stringCompression.ts +22 -13
  69. package/src/transforms/string/stringConcealing.ts +11 -7
  70. package/src/transforms/string/stringEncoding.ts +6 -2
  71. package/src/transforms/string/stringSplitting.ts +9 -4
  72. package/src/transforms/variableMasking.ts +1 -2
  73. package/src/utils/NameGen.ts +4 -2
  74. package/src/utils/PredicateGen.ts +61 -0
  75. package/src/utils/ast-utils.ts +16 -9
  76. package/src/validateOptions.ts +7 -4
  77. package/src/transforms/functionOutlining.ts +0 -225
  78. package/src/utils/ControlObject.ts +0 -141
@@ -1,225 +0,0 @@
1
- import { NodePath } from "@babel/traverse";
2
- import { PluginArg, PluginObject } from "./plugin";
3
- import { Order } from "../order";
4
- import { ensureComputedExpression, prepend } from "../utils/ast-utils";
5
- import * as t from "@babel/types";
6
- import { NameGen } from "../utils/NameGen";
7
- import { chance, getRandomInteger } from "../utils/random-utils";
8
- import { Binding, Visitor } from "@babel/traverse";
9
- import { computeProbabilityMap } from "../probability";
10
-
11
- function isSafeForOutlining(path: NodePath): {
12
- isSafe: boolean;
13
- bindings?: Binding[];
14
- } {
15
- if (path.isIdentifier() || path.isLiteral()) return { isSafe: false };
16
-
17
- // Skip direct invocations ('this' will be different)
18
- if (path.key === "callee" && path.parentPath.isCallExpression()) {
19
- return { isSafe: false };
20
- }
21
-
22
- // Skip typeof and delete expressions (identifier behavior is different)
23
- if (path.key === "argument" && path.parentPath.isUnaryExpression()) {
24
- return { isSafe: false };
25
- }
26
-
27
- if (
28
- path.isReturnStatement() ||
29
- path.isYieldExpression() ||
30
- path.isAwaitExpression() ||
31
- path.isContinueStatement() ||
32
- path.isBreakStatement() ||
33
- path.isThrowStatement() ||
34
- path.isDebuggerStatement() ||
35
- path.isImportDeclaration() ||
36
- path.isExportDeclaration()
37
- ) {
38
- return { isSafe: false };
39
- }
40
-
41
- var isSafe = true;
42
- var bindings: Binding[] = [];
43
- var fnPath = path.getFunctionParent();
44
-
45
- var visitor: Visitor = {
46
- ThisExpression(path) {
47
- isSafe = false;
48
- path.stop();
49
- },
50
- Identifier(path) {
51
- if (["arguments", "eval"].includes(path.node.name)) {
52
- isSafe = false;
53
- path.stop();
54
- }
55
- },
56
- BindingIdentifier(path) {
57
- var binding = path.scope.getBinding(path.node.name);
58
- if (binding) {
59
- bindings.push(binding);
60
- }
61
- },
62
- // Function flow guard
63
- "ReturnStatement|YieldExpression|AwaitExpression"(path) {
64
- if (path.getFunctionParent() === fnPath) {
65
- isSafe = false;
66
- path.stop();
67
- }
68
- },
69
- };
70
-
71
- // Exclude 'ThisExpression' and semantic 'Identifier' nodes
72
- if (visitor[path.type]) return { isSafe: false };
73
-
74
- path.traverse(visitor);
75
-
76
- return { isSafe, bindings };
77
- }
78
-
79
- export default ({ Plugin }: PluginArg): PluginObject => {
80
- const me = Plugin(Order.FunctionOutlining, {
81
- changeData: {
82
- functionsMade: 0,
83
- },
84
- });
85
-
86
- var changesMade = 0;
87
-
88
- function checkProbability() {
89
- if (!computeProbabilityMap(me.options.functionOutlining)) return false;
90
-
91
- if (changesMade > 100 && chance(changesMade - 100)) return false;
92
-
93
- return true;
94
- }
95
-
96
- return {
97
- visitor: {
98
- Block: {
99
- exit(blockPath) {
100
- if (blockPath.isProgram()) {
101
- blockPath.scope.crawl();
102
- }
103
-
104
- if (blockPath.find((p) => me.isSkipped(p))) return;
105
-
106
- if (!checkProbability()) return;
107
-
108
- // Extract a random number of statements
109
-
110
- var statements = blockPath.get("body");
111
- // var startIndex = getRandomInteger(0, statements.length);
112
- // var endIndex = getRandomInteger(startIndex, statements.length);
113
-
114
- var startIndex = 0;
115
- var endIndex = statements.length;
116
-
117
- var extractedStatements = statements.slice(startIndex, endIndex);
118
- if (!extractedStatements.length) return;
119
-
120
- var bindings: Binding[] = [];
121
-
122
- for (var statement of extractedStatements) {
123
- // Don't override the control node
124
- if (me.isSkipped(statement)) return;
125
-
126
- var result = isSafeForOutlining(statement);
127
- if (!result.isSafe) {
128
- return;
129
- }
130
-
131
- bindings.push(...result.bindings);
132
- }
133
-
134
- const extractedStatementSet = new Set<NodePath>(extractedStatements);
135
-
136
- for (var binding of bindings) {
137
- for (var referencePath of binding.referencePaths) {
138
- var found = referencePath.find((p) =>
139
- extractedStatementSet.has(p)
140
- );
141
- if (!found) {
142
- return;
143
- }
144
- }
145
- for (var constantViolation of binding.constantViolations) {
146
- var found = constantViolation.find((p) =>
147
- extractedStatementSet.has(p)
148
- );
149
- if (!found) {
150
- return;
151
- }
152
- }
153
- }
154
-
155
- changesMade++;
156
-
157
- var isFirst = true;
158
- for (var statement of extractedStatements) {
159
- if (isFirst) {
160
- isFirst = false;
161
- var memberExpression = me
162
- .getControlObject(blockPath)
163
- .addProperty(
164
- t.functionExpression(
165
- null,
166
- [],
167
- t.blockStatement(extractedStatements.map((x) => x.node))
168
- )
169
- );
170
-
171
- me.changeData.functionsMade++;
172
-
173
- var callExpression = t.callExpression(memberExpression, []);
174
-
175
- statement.replaceWith(callExpression);
176
- continue;
177
- }
178
- statement.remove();
179
- }
180
- },
181
- },
182
- Expression: {
183
- exit(path) {
184
- // Skip assignment left
185
- if (
186
- path.find(
187
- (p) =>
188
- p.key === "left" &&
189
- p.parentPath?.type === "AssignmentExpression"
190
- )
191
- ) {
192
- return;
193
- }
194
-
195
- if (!checkProbability()) return;
196
-
197
- if (path.find((p) => me.isSkipped(p))) return;
198
- if (!isSafeForOutlining(path).isSafe) return;
199
-
200
- changesMade++;
201
-
202
- var blockPath = path.find((p) => p.isBlock()) as NodePath<t.Block>;
203
-
204
- var memberExpression = me
205
- .getControlObject(blockPath)
206
- .addProperty(
207
- t.functionExpression(
208
- null,
209
- [],
210
- t.blockStatement([t.returnStatement(t.cloneNode(path.node))])
211
- )
212
- );
213
-
214
- me.changeData.functionsMade++;
215
-
216
- var callExpression = t.callExpression(memberExpression, []);
217
-
218
- ensureComputedExpression(path);
219
- path.replaceWith(callExpression);
220
- me.skip(path);
221
- },
222
- },
223
- },
224
- };
225
- };
@@ -1,141 +0,0 @@
1
- import { NodePath } from "@babel/traverse";
2
- import * as t from "@babel/types";
3
- import { PluginInstance } from "../transforms/plugin";
4
- import { NameGen } from "./NameGen";
5
- import { prepend } from "./ast-utils";
6
- import { chance, choice } from "./random-utils";
7
-
8
- /**
9
- * A Control Object is an object that is used to store properties that are used in multiple places.
10
- */
11
- export default class ControlObject {
12
- propertyNames = new Set<string>();
13
- nameGen: NameGen;
14
- objectName: string | null = null;
15
- objectPath: NodePath<t.Declaration> | null = null;
16
- objectExpression: t.ObjectExpression | null = null;
17
-
18
- constructor(public me: PluginInstance, public blockPath: NodePath<t.Block>) {
19
- this.nameGen = new NameGen(me.options.identifierGenerator, {
20
- avoidReserved: true,
21
- avoidObjectPrototype: true,
22
- });
23
- }
24
-
25
- createMemberExpression(propertyName: string): t.MemberExpression {
26
- return t.memberExpression(
27
- t.identifier(this.objectName),
28
- t.stringLiteral(propertyName),
29
- true
30
- );
31
- }
32
-
33
- createPredicate() {
34
- this.ensureCreated();
35
-
36
- var propertyName = choice(Array.from(this.propertyNames));
37
- if (!propertyName || chance(50)) {
38
- propertyName = this.nameGen.generate();
39
- }
40
-
41
- return {
42
- node: t.binaryExpression(
43
- "in",
44
- t.stringLiteral(propertyName),
45
- t.identifier(this.objectName)
46
- ),
47
- value: this.propertyNames.has(propertyName),
48
- };
49
- }
50
-
51
- createTruePredicate() {
52
- var { node, value } = this.createPredicate();
53
- if (value) {
54
- return node;
55
- }
56
- return t.unaryExpression("!", node);
57
- }
58
-
59
- createFalsePredicate() {
60
- var { node, value } = this.createPredicate();
61
- if (!value) {
62
- return node;
63
- }
64
- return t.unaryExpression("!", node);
65
- }
66
-
67
- private ensureCreated(node?: t.Node) {
68
- if (!this.objectName) {
69
- // Object hasn't been created yet
70
- this.objectName = this.me.getPlaceholder() + "_controlObject";
71
-
72
- if (node && t.isFunctionExpression(node) && !node.id) {
73
- // Use function declaration as object
74
-
75
- let newNode: t.FunctionDeclaration = node as any;
76
- newNode.type = "FunctionDeclaration";
77
- newNode.id = t.identifier(this.objectName);
78
-
79
- let newPath = prepend(
80
- this.blockPath,
81
- newNode
82
- )[0] as NodePath<t.FunctionDeclaration>;
83
- this.me.skip(newPath);
84
-
85
- this.objectPath = newPath;
86
-
87
- return t.identifier(this.objectName);
88
- } else {
89
- // Create plain object
90
- let newPath = prepend(
91
- this.blockPath,
92
- t.variableDeclaration("var", [
93
- t.variableDeclarator(
94
- t.identifier(this.objectName),
95
- t.objectExpression([])
96
- ),
97
- ])
98
- )[0] as NodePath<t.VariableDeclaration>;
99
- this.me.skip(newPath);
100
-
101
- this.objectPath = newPath;
102
-
103
- var objectExpression = newPath.node.declarations[0]
104
- .init as t.ObjectExpression;
105
-
106
- this.objectExpression = objectExpression;
107
- this.me.skip(this.objectExpression);
108
- }
109
- }
110
- }
111
-
112
- addProperty(node: t.Expression) {
113
- var initialNode = this.ensureCreated(node);
114
- if (initialNode) return initialNode;
115
-
116
- const propertyName = this.nameGen.generate();
117
- this.propertyNames.add(propertyName);
118
-
119
- // Add an initial property
120
- if (this.objectExpression) {
121
- this.objectExpression.properties.push(
122
- t.objectProperty(t.identifier(propertyName), node)
123
- );
124
- } else {
125
- // Add as assignment expression
126
-
127
- let assignment = t.assignmentExpression(
128
- "=",
129
- this.createMemberExpression(propertyName),
130
- node
131
- );
132
-
133
- var newPath = this.objectPath.insertAfter(
134
- t.expressionStatement(assignment)
135
- )[0];
136
- this.me.skip(newPath);
137
- }
138
-
139
- return this.createMemberExpression(propertyName);
140
- }
141
- }