js-confuser 1.5.8 → 1.6.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 +69 -0
- package/README.md +143 -7
- package/dist/index.js +33 -4
- package/dist/obfuscator.js +30 -31
- package/dist/options.js +4 -5
- package/dist/order.js +4 -6
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +2 -2
- package/dist/templates/es5.js +18 -0
- package/dist/transforms/antiTooling.js +1 -1
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +7 -6
- package/dist/transforms/es5/antiClass.js +6 -2
- package/dist/transforms/es5/antiDestructuring.js +3 -1
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/eval.js +11 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
- package/dist/transforms/extraction/objectExtraction.js +6 -1
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +82 -55
- package/dist/transforms/hexadecimalNumbers.js +34 -9
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +2 -8
- package/dist/transforms/identifier/renameVariables.js +39 -27
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/minify.js +80 -61
- 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 +4 -5
- package/dist/transforms/stack.js +87 -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 +11 -18
- package/dist/traverse.js +24 -18
- package/dist/util/compare.js +2 -2
- package/dist/util/gen.js +15 -0
- package/dist/util/insert.js +31 -7
- package/dist/util/random.js +15 -0
- package/package.json +5 -5
- package/src/index.ts +57 -19
- package/src/obfuscator.ts +26 -29
- package/src/options.ts +17 -21
- package/src/order.ts +4 -8
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +5 -9
- package/src/templates/es5.ts +131 -0
- package/src/transforms/antiTooling.ts +1 -1
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +8 -6
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/es5/antiDestructuring.ts +3 -1
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/eval.ts +18 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
- package/src/transforms/extraction/objectExtraction.ts +12 -5
- package/src/transforms/finalizer.ts +75 -0
- package/src/transforms/flatten.ts +194 -151
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +4 -11
- package/src/transforms/identifier/renameVariables.ts +37 -30
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/minify.ts +116 -77
- 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 +6 -7
- package/src/transforms/stack.ts +97 -37
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +41 -11
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +15 -21
- package/src/traverse.ts +24 -12
- package/src/types.ts +11 -2
- package/src/util/compare.ts +2 -2
- package/src/util/gen.ts +21 -1
- package/src/util/insert.ts +49 -9
- 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 +136 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/code/NewFeatures.test.ts +19 -0
- package/test/index.test.ts +15 -2
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +52 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +44 -1
- package/test/transforms/es5/antiClass.test.ts +33 -0
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/eval.test.ts +53 -0
- package/test/transforms/extraction/objectExtraction.test.ts +21 -0
- package/test/transforms/flatten.test.ts +195 -3
- package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
- package/test/transforms/identifier/renameVariables.test.ts +108 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/minify.test.ts +151 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +56 -29
- package/test/transforms/stack.test.ts +91 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +115 -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/compare.test.ts +23 -1
- 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/hexadecimalNumbers.ts +0 -31
- package/src/transforms/hideInitializingCode.ts +0 -432
- 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/hideInitializingCode.test.ts +0 -336
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
package/src/transforms/minify.ts
CHANGED
|
@@ -2,7 +2,6 @@ import Transform from "./transform";
|
|
|
2
2
|
import { ObfuscateOrder } from "../order";
|
|
3
3
|
import {
|
|
4
4
|
Node,
|
|
5
|
-
Location,
|
|
6
5
|
VariableDeclaration,
|
|
7
6
|
BinaryExpression,
|
|
8
7
|
ExpressionStatement,
|
|
@@ -15,18 +14,20 @@ import {
|
|
|
15
14
|
AssignmentExpression,
|
|
16
15
|
VariableDeclarator,
|
|
17
16
|
Identifier,
|
|
17
|
+
CallExpression,
|
|
18
18
|
} from "../util/gen";
|
|
19
19
|
import {
|
|
20
20
|
getBlockBody,
|
|
21
21
|
clone,
|
|
22
22
|
isForInitialize,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
append,
|
|
24
|
+
isVarContext,
|
|
25
25
|
} from "../util/insert";
|
|
26
26
|
import { isValidIdentifier, isEquivalent } from "../util/compare";
|
|
27
27
|
import { walk, isBlock } from "../traverse";
|
|
28
28
|
import { ok } from "assert";
|
|
29
29
|
import { isLexicalScope } from "../util/scope";
|
|
30
|
+
import Template from "../templates/template";
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Basic transformations to reduce code size.
|
|
@@ -37,12 +38,13 @@ import { isLexicalScope } from "../util/scope";
|
|
|
37
38
|
* - `x['y']` **->** `x.y`
|
|
38
39
|
*/
|
|
39
40
|
export default class Minify extends Transform {
|
|
40
|
-
|
|
41
|
+
/**
|
|
42
|
+
* A helper function that is introduced preserve function semantics
|
|
43
|
+
*/
|
|
44
|
+
arrowFunctionName: string;
|
|
41
45
|
|
|
42
46
|
constructor(o) {
|
|
43
47
|
super(o, ObfuscateOrder.Minify);
|
|
44
|
-
|
|
45
|
-
this.variables = new Map();
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
match(object: Node, parents: Node[]) {
|
|
@@ -92,7 +94,7 @@ export default class Minify extends Transform {
|
|
|
92
94
|
var sequences: { index: number; exprs: Node[] }[] = [];
|
|
93
95
|
|
|
94
96
|
body.forEach((stmt, i) => {
|
|
95
|
-
if (stmt.type == "ExpressionStatement") {
|
|
97
|
+
if (stmt.type == "ExpressionStatement" && !stmt.directive) {
|
|
96
98
|
exprs.push(stmt.expression);
|
|
97
99
|
if (startIndex == -1) {
|
|
98
100
|
startIndex = i;
|
|
@@ -124,51 +126,52 @@ export default class Minify extends Transform {
|
|
|
124
126
|
});
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
129
|
+
// Unnecessary return
|
|
130
|
+
if (
|
|
131
|
+
parents[0] &&
|
|
132
|
+
isVarContext(parents[0]) &&
|
|
133
|
+
body.length &&
|
|
134
|
+
body[body.length - 1]
|
|
135
|
+
) {
|
|
136
|
+
var last = body[body.length - 1];
|
|
137
|
+
if (last.type == "ReturnStatement") {
|
|
138
|
+
var isUndefined = last.argument == null;
|
|
139
|
+
|
|
140
|
+
if (isUndefined) {
|
|
141
|
+
body.pop();
|
|
139
142
|
}
|
|
140
143
|
}
|
|
144
|
+
}
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
} else {
|
|
160
|
-
lastDec.declarations.push(...clone(x.declarations));
|
|
161
|
-
remove.unshift(i);
|
|
162
|
-
}
|
|
146
|
+
// Variable declaration grouping
|
|
147
|
+
// var a = 1;
|
|
148
|
+
// var b = 1;
|
|
149
|
+
// var c = 1;
|
|
150
|
+
//
|
|
151
|
+
// var a=1,b=1,c=1;
|
|
152
|
+
var lastDec = null;
|
|
153
|
+
|
|
154
|
+
var remove = [];
|
|
155
|
+
body.forEach((x, i) => {
|
|
156
|
+
if (x.type === "VariableDeclaration") {
|
|
157
|
+
if (
|
|
158
|
+
!lastDec ||
|
|
159
|
+
lastDec.kind !== x.kind ||
|
|
160
|
+
!lastDec.declarations.length
|
|
161
|
+
) {
|
|
162
|
+
lastDec = x;
|
|
163
163
|
} else {
|
|
164
|
-
lastDec
|
|
164
|
+
lastDec.declarations.push(...clone(x.declarations));
|
|
165
|
+
remove.unshift(i);
|
|
165
166
|
}
|
|
166
|
-
}
|
|
167
|
+
} else {
|
|
168
|
+
lastDec = null;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
167
171
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
+
remove.forEach((x) => {
|
|
173
|
+
body.splice(x, 1);
|
|
174
|
+
});
|
|
172
175
|
};
|
|
173
176
|
}
|
|
174
177
|
|
|
@@ -198,28 +201,38 @@ export default class Minify extends Transform {
|
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
203
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
var block = parents[blockIndex];
|
|
204
|
-
var body = block.body;
|
|
204
|
+
if (object.type === "FunctionDeclaration") {
|
|
205
|
+
var body = parents[0];
|
|
205
206
|
if (!Array.isArray(body)) {
|
|
206
207
|
return;
|
|
207
208
|
}
|
|
208
209
|
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
var index = body.indexOf(stmt);
|
|
210
|
+
var index = body.indexOf(object);
|
|
212
211
|
if (index == -1) {
|
|
213
212
|
return;
|
|
214
213
|
}
|
|
215
214
|
|
|
216
215
|
var before = body.slice(0, index);
|
|
217
|
-
ok(!before.includes(
|
|
216
|
+
ok(!before.includes(object));
|
|
218
217
|
|
|
219
|
-
var
|
|
220
|
-
|
|
218
|
+
var beforeTypes = new Set(before.map((x) => x.type));
|
|
219
|
+
beforeTypes.delete("FunctionDeclaration");
|
|
221
220
|
|
|
222
|
-
if (
|
|
221
|
+
if (beforeTypes.size > 0) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Test Variant #25: Don't break redefined function declaration
|
|
226
|
+
if (
|
|
227
|
+
object.id &&
|
|
228
|
+
body.find(
|
|
229
|
+
(x) =>
|
|
230
|
+
x.type === "FunctionDeclaration" &&
|
|
231
|
+
x !== object &&
|
|
232
|
+
x.id &&
|
|
233
|
+
x.id.name === object.id.name
|
|
234
|
+
)
|
|
235
|
+
) {
|
|
223
236
|
return;
|
|
224
237
|
}
|
|
225
238
|
}
|
|
@@ -239,17 +252,42 @@ export default class Minify extends Transform {
|
|
|
239
252
|
});
|
|
240
253
|
|
|
241
254
|
if (canTransform) {
|
|
255
|
+
if (!this.arrowFunctionName) {
|
|
256
|
+
this.arrowFunctionName = this.getPlaceholder();
|
|
257
|
+
|
|
258
|
+
append(
|
|
259
|
+
parents[parents.length - 1] || object,
|
|
260
|
+
Template(`
|
|
261
|
+
function ${this.arrowFunctionName}(arrowFn){
|
|
262
|
+
return function(){ return arrowFn(...arguments) }
|
|
263
|
+
}
|
|
264
|
+
`).single()
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const wrap = (object: Node) => {
|
|
269
|
+
return CallExpression(Identifier(this.arrowFunctionName), [
|
|
270
|
+
clone(object),
|
|
271
|
+
]);
|
|
272
|
+
};
|
|
273
|
+
|
|
242
274
|
if (object.type == "FunctionExpression") {
|
|
243
275
|
object.type = "ArrowFunctionExpression";
|
|
276
|
+
|
|
277
|
+
this.replace(object, wrap(clone(object)));
|
|
244
278
|
} else {
|
|
245
279
|
var arrow = { ...clone(object), type: "ArrowFunctionExpression" };
|
|
246
280
|
this.replace(
|
|
247
281
|
object,
|
|
248
|
-
VariableDeclaration(
|
|
282
|
+
VariableDeclaration(
|
|
283
|
+
VariableDeclarator(object.id.name, wrap(arrow))
|
|
284
|
+
)
|
|
249
285
|
);
|
|
250
286
|
|
|
251
287
|
var x = this.transform(arrow, []);
|
|
252
|
-
x
|
|
288
|
+
if (typeof x === "function") {
|
|
289
|
+
x();
|
|
290
|
+
}
|
|
253
291
|
}
|
|
254
292
|
}
|
|
255
293
|
};
|
|
@@ -268,7 +306,7 @@ export default class Minify extends Transform {
|
|
|
268
306
|
|
|
269
307
|
if (body.length == 1 && stmt1.type == "ReturnStatement") {
|
|
270
308
|
// x=>{a: 1} // Invalid syntax
|
|
271
|
-
if (stmt1.argument.type != "ObjectExpression") {
|
|
309
|
+
if (stmt1.argument && stmt1.argument.type != "ObjectExpression") {
|
|
272
310
|
object.body = stmt1.argument;
|
|
273
311
|
object.expression = true;
|
|
274
312
|
}
|
|
@@ -442,6 +480,8 @@ export default class Minify extends Transform {
|
|
|
442
480
|
}
|
|
443
481
|
|
|
444
482
|
if (
|
|
483
|
+
object.consequent &&
|
|
484
|
+
object.consequent.body &&
|
|
445
485
|
object.consequent.body.length == 1 &&
|
|
446
486
|
object.alternate &&
|
|
447
487
|
object.alternate.body.length == 1
|
|
@@ -512,16 +552,16 @@ export default class Minify extends Transform {
|
|
|
512
552
|
object.property.type = "Identifier";
|
|
513
553
|
object.property.name = clone(object.property.value);
|
|
514
554
|
|
|
515
|
-
obj.name &&
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
555
|
+
// obj.name &&
|
|
556
|
+
// this.log(
|
|
557
|
+
// obj.name +
|
|
558
|
+
// "['" +
|
|
559
|
+
// object.property.name +
|
|
560
|
+
// "'] -> " +
|
|
561
|
+
// obj.name +
|
|
562
|
+
// "." +
|
|
563
|
+
// object.property.name
|
|
564
|
+
// );
|
|
525
565
|
}
|
|
526
566
|
}
|
|
527
567
|
|
|
@@ -540,7 +580,7 @@ export default class Minify extends Transform {
|
|
|
540
580
|
}
|
|
541
581
|
|
|
542
582
|
// { "x": 1 } -> {x: 1}
|
|
543
|
-
if (object.type
|
|
583
|
+
if (object.type === "Property" || object.type === "MethodDefinition") {
|
|
544
584
|
if (
|
|
545
585
|
object.key.type == "SequenceExpression" &&
|
|
546
586
|
object.key.expressions.length == 1
|
|
@@ -549,15 +589,14 @@ export default class Minify extends Transform {
|
|
|
549
589
|
object.computed = true;
|
|
550
590
|
}
|
|
551
591
|
|
|
552
|
-
if (
|
|
592
|
+
if (
|
|
593
|
+
object.key.type == "Literal" &&
|
|
594
|
+
typeof object.key.value === "string" &&
|
|
595
|
+
isValidIdentifier(object.key.value)
|
|
596
|
+
) {
|
|
553
597
|
object.key.type = "Identifier";
|
|
554
598
|
object.key.name = object.key.value;
|
|
555
599
|
object.computed = false;
|
|
556
|
-
} else if (
|
|
557
|
-
object.key.type == "Identifier" &&
|
|
558
|
-
!isValidIdentifier(object.key.name)
|
|
559
|
-
) {
|
|
560
|
-
object.key = Literal(object.key.name);
|
|
561
600
|
}
|
|
562
601
|
}
|
|
563
602
|
|
|
@@ -64,14 +64,14 @@ export default class OpaquePredicates extends Transform {
|
|
|
64
64
|
predicate: Node;
|
|
65
65
|
predicates: { [name: string]: Node };
|
|
66
66
|
|
|
67
|
-
gen:
|
|
67
|
+
gen: ReturnType<Transform["getGenerator"]>;
|
|
68
68
|
made: number;
|
|
69
69
|
|
|
70
70
|
constructor(o) {
|
|
71
71
|
super(o, ObfuscateOrder.OpaquePredicates);
|
|
72
72
|
|
|
73
73
|
this.predicates = Object.create(null);
|
|
74
|
-
this.gen = this.getGenerator(
|
|
74
|
+
this.gen = this.getGenerator();
|
|
75
75
|
this.made = 0;
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import Transform from "./transform";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BlockStatement,
|
|
5
|
+
Identifier,
|
|
6
|
+
LabeledStatement,
|
|
7
|
+
Literal,
|
|
8
|
+
Node,
|
|
9
|
+
ReturnStatement,
|
|
10
|
+
} from "../util/gen";
|
|
11
|
+
import { ObfuscateOrder } from "../order";
|
|
12
|
+
import { clone, getFunction } from "../util/insert";
|
|
13
|
+
import { getIdentifierInfo } from "../util/identifiers";
|
|
14
|
+
import { isLoop } from "../util/compare";
|
|
15
|
+
import { ExitCallback, walk } from "../traverse";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Preparation arranges the user's code into an AST the obfuscator can easily transform.
|
|
19
|
+
*
|
|
20
|
+
* ExplicitIdentifiers
|
|
21
|
+
* - `object.IDENTIFIER` -> `object['IDENTIFIER']` // Now String Concealing can apply on it
|
|
22
|
+
* - `{ IDENTIFIER: ... }` -> `{ "IDENTIFIER": ... }`
|
|
23
|
+
*
|
|
24
|
+
* ExplicitDeclarations
|
|
25
|
+
* - `var a,b,c` -> `var a; var b; var c;` // Now Stack can apply on it
|
|
26
|
+
*
|
|
27
|
+
* Block
|
|
28
|
+
* - `x => x * 2` -> `x => { return x * 2 }` // Change into Block Statements
|
|
29
|
+
* - `if(true) return` -> `if (true) { return }`
|
|
30
|
+
* - `while(a) a--;` -> `while(a) { a-- }`
|
|
31
|
+
*
|
|
32
|
+
* Label
|
|
33
|
+
* - `for(...) { break; }` -> `_1: for(...) { break _1; }`
|
|
34
|
+
* - `switch(v) { case 1...break }` -> `_2: switch(v) { case 1...break _2; }`
|
|
35
|
+
* - // Control Flow Flattening can safely apply now
|
|
36
|
+
*/
|
|
37
|
+
export default class Preparation extends Transform {
|
|
38
|
+
constructor(o) {
|
|
39
|
+
super(o, ObfuscateOrder.Preparation);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
match(object: Node, parents: Node[]) {
|
|
43
|
+
return !!object.type;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
transform(object: Node, parents: Node[]): void | ExitCallback {
|
|
47
|
+
// ExplicitIdentifiers
|
|
48
|
+
if (object.type === "Identifier") {
|
|
49
|
+
return this.transformExplicitIdentifiers(object, parents);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ExplicitDeclarations
|
|
53
|
+
if (object.type === "VariableDeclaration") {
|
|
54
|
+
return this.transformExplicitDeclarations(object, parents);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Block
|
|
58
|
+
switch (object.type) {
|
|
59
|
+
/**
|
|
60
|
+
* People use shortcuts and its harder to parse.
|
|
61
|
+
*
|
|
62
|
+
* - `if (a) b()` -> `if (a) { b() }`
|
|
63
|
+
* - Ensures all bodies are `BlockStatement`, not individual expression statements
|
|
64
|
+
*/
|
|
65
|
+
case "IfStatement":
|
|
66
|
+
if (object.consequent.type != "BlockStatement") {
|
|
67
|
+
object.consequent = BlockStatement([clone(object.consequent)]);
|
|
68
|
+
}
|
|
69
|
+
if (object.alternate && object.alternate.type != "BlockStatement") {
|
|
70
|
+
object.alternate = BlockStatement([clone(object.alternate)]);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
|
|
74
|
+
case "WhileStatement":
|
|
75
|
+
case "WithStatement":
|
|
76
|
+
case "ForStatement":
|
|
77
|
+
case "ForOfStatement":
|
|
78
|
+
case "ForInStatement":
|
|
79
|
+
if (object.body.type != "BlockStatement") {
|
|
80
|
+
object.body = BlockStatement([clone(object.body)]);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case "ArrowFunctionExpression":
|
|
85
|
+
if (object.body.type !== "BlockStatement" && object.expression) {
|
|
86
|
+
object.body = BlockStatement([ReturnStatement(clone(object.body))]);
|
|
87
|
+
object.expression = false;
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Label
|
|
93
|
+
if (
|
|
94
|
+
isLoop(object) ||
|
|
95
|
+
(object.type == "BlockStatement" &&
|
|
96
|
+
parents[0] &&
|
|
97
|
+
parents[0].type == "LabeledStatement" &&
|
|
98
|
+
parents[0].body === object)
|
|
99
|
+
) {
|
|
100
|
+
return this.transformLabel(object, parents);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Ensures every break; statement has a label to point to.
|
|
106
|
+
*
|
|
107
|
+
* This is because Control Flow Flattening adds For Loops which label-less break statements point to the nearest,
|
|
108
|
+
* when they actually need to point to the original statement.
|
|
109
|
+
*/
|
|
110
|
+
transformLabel(object: Node, parents: Node[]) {
|
|
111
|
+
return () => {
|
|
112
|
+
var currentLabel =
|
|
113
|
+
parents[0].type == "LabeledStatement" && parents[0].label.name;
|
|
114
|
+
|
|
115
|
+
var label = currentLabel || this.getPlaceholder();
|
|
116
|
+
|
|
117
|
+
walk(object, parents, (o, p) => {
|
|
118
|
+
if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
|
|
119
|
+
function isContinuableStatement(x) {
|
|
120
|
+
return isLoop(x) && x.type !== "SwitchStatement";
|
|
121
|
+
}
|
|
122
|
+
function isBreakableStatement(x) {
|
|
123
|
+
return isLoop(x) || (o.label && x.type == "BlockStatement");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var fn =
|
|
127
|
+
o.type == "ContinueStatement"
|
|
128
|
+
? isContinuableStatement
|
|
129
|
+
: isBreakableStatement;
|
|
130
|
+
|
|
131
|
+
var loop = p.find(fn);
|
|
132
|
+
if (object == loop) {
|
|
133
|
+
if (!o.label) {
|
|
134
|
+
o.label = Identifier(label);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Append label statement as this loop has none
|
|
141
|
+
if (!currentLabel) {
|
|
142
|
+
this.replace(object, LabeledStatement(label, { ...object }));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Transforms Identifiers (a.IDENTIFIER, {IDENTIFIER:...}) into string properties
|
|
149
|
+
*/
|
|
150
|
+
transformExplicitIdentifiers(object: Node, parents: Node[]) {
|
|
151
|
+
// Mark functions containing 'eval'
|
|
152
|
+
// Some transformations avoid functions that have 'eval' to not break them
|
|
153
|
+
if (object.name === "eval") {
|
|
154
|
+
var fn = getFunction(object, parents);
|
|
155
|
+
if (fn) {
|
|
156
|
+
fn.$requiresEval = true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
var info = getIdentifierInfo(object, parents);
|
|
161
|
+
if (info.isPropertyKey || info.isAccessor) {
|
|
162
|
+
var propIndex = parents.findIndex(
|
|
163
|
+
(x) => x.type == "MethodDefinition" || x.type == "Property"
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// Don't change constructor!
|
|
167
|
+
if (propIndex !== -1) {
|
|
168
|
+
if (
|
|
169
|
+
parents[propIndex].type == "MethodDefinition" &&
|
|
170
|
+
parents[propIndex].kind == "constructor"
|
|
171
|
+
) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.replace(object, Literal(object.name));
|
|
177
|
+
parents[0].computed = true;
|
|
178
|
+
parents[0].shorthand = false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Transforms VariableDeclaration into single declarations.
|
|
184
|
+
*/
|
|
185
|
+
transformExplicitDeclarations(object: Node, parents: Node[]) {
|
|
186
|
+
// for ( var x in ... ) {...}
|
|
187
|
+
var forIndex = parents.findIndex(
|
|
188
|
+
(x) => x.type == "ForInStatement" || x.type == "ForOfStatement"
|
|
189
|
+
);
|
|
190
|
+
if (
|
|
191
|
+
forIndex != -1 &&
|
|
192
|
+
parents[forIndex].left == (parents[forIndex - 1] || object)
|
|
193
|
+
) {
|
|
194
|
+
object.declarations.forEach((x) => {
|
|
195
|
+
x.init = null;
|
|
196
|
+
});
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
var body = parents[0];
|
|
201
|
+
if (isLoop(body) || body.type == "LabeledStatement") {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (body.type == "ExportNamedDeclaration") {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!Array.isArray(body)) {
|
|
210
|
+
this.error(new Error("body is " + body.type));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (object.declarations.length > 1) {
|
|
214
|
+
// Make singular
|
|
215
|
+
|
|
216
|
+
var index = body.indexOf(object);
|
|
217
|
+
if (index == -1) {
|
|
218
|
+
this.error(new Error("index is -1"));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
var after = object.declarations.slice(1);
|
|
222
|
+
|
|
223
|
+
body.splice(
|
|
224
|
+
index + 1,
|
|
225
|
+
0,
|
|
226
|
+
...after.map((x) => {
|
|
227
|
+
return {
|
|
228
|
+
type: "VariableDeclaration",
|
|
229
|
+
declarations: [clone(x)],
|
|
230
|
+
kind: object.kind,
|
|
231
|
+
};
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
object.declarations.length = 1;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -9,12 +9,12 @@ import Transform from "./transform";
|
|
|
9
9
|
* Renames the labels to shorter names.
|
|
10
10
|
*/
|
|
11
11
|
export default class RenameLabels extends Transform {
|
|
12
|
-
gen:
|
|
12
|
+
gen: ReturnType<Transform["getGenerator"]>;
|
|
13
13
|
|
|
14
14
|
constructor(o) {
|
|
15
15
|
super(o, ObfuscateOrder.RenameLabels);
|
|
16
16
|
|
|
17
|
-
this.gen = this.getGenerator();
|
|
17
|
+
this.gen = this.getGenerator("randomized");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
match(object, parents) {
|
package/src/transforms/rgf.ts
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
Node,
|
|
21
21
|
ReturnStatement,
|
|
22
22
|
SpreadElement,
|
|
23
|
-
ThisExpression,
|
|
24
23
|
VariableDeclaration,
|
|
25
24
|
VariableDeclarator,
|
|
26
25
|
} from "../util/gen";
|
|
@@ -31,6 +30,7 @@ import {
|
|
|
31
30
|
isFunction,
|
|
32
31
|
prepend,
|
|
33
32
|
getDefiningContext,
|
|
33
|
+
clone,
|
|
34
34
|
} from "../util/insert";
|
|
35
35
|
import { getRandomString } from "../util/random";
|
|
36
36
|
import Transform from "./transform";
|
|
@@ -300,14 +300,15 @@ export default class RGF extends Transform {
|
|
|
300
300
|
[],
|
|
301
301
|
[
|
|
302
302
|
ReturnStatement(
|
|
303
|
-
|
|
303
|
+
// clone() is required!
|
|
304
|
+
CallExpression(clone(memberExpression), [
|
|
304
305
|
Identifier(referenceArray),
|
|
305
306
|
SpreadElement(Identifier("arguments")),
|
|
306
307
|
])
|
|
307
308
|
),
|
|
308
309
|
]
|
|
309
310
|
),
|
|
310
|
-
memberExpression
|
|
311
|
+
clone(memberExpression)
|
|
311
312
|
);
|
|
312
313
|
|
|
313
314
|
this.replace(o, conditionalExpression);
|
|
@@ -328,8 +329,6 @@ export default class RGF extends Transform {
|
|
|
328
329
|
|
|
329
330
|
queue.forEach(([object, parents]) => {
|
|
330
331
|
var name = object?.id?.name;
|
|
331
|
-
var hasName = !!name;
|
|
332
|
-
var params = object.params.map((x) => x.name) || [];
|
|
333
332
|
var signature = referenceSignatures[names.get(name)];
|
|
334
333
|
|
|
335
334
|
var embeddedName = name || this.getPlaceholder();
|
|
@@ -348,9 +347,9 @@ export default class RGF extends Transform {
|
|
|
348
347
|
integrity: false,
|
|
349
348
|
},
|
|
350
349
|
eval: false,
|
|
351
|
-
|
|
350
|
+
stringEncoding: false,
|
|
352
351
|
});
|
|
353
|
-
var transforms =
|
|
352
|
+
var transforms = obfuscator.array.filter(
|
|
354
353
|
(x) => x.priority > this.priority
|
|
355
354
|
);
|
|
356
355
|
|