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/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,
|
|
@@ -21,10 +20,9 @@ import {
|
|
|
21
20
|
getBlockBody,
|
|
22
21
|
clone,
|
|
23
22
|
isForInitialize,
|
|
24
|
-
isLexContext,
|
|
25
|
-
getFunction,
|
|
26
|
-
prepend,
|
|
27
23
|
append,
|
|
24
|
+
isVarContext,
|
|
25
|
+
computeFunctionLength,
|
|
28
26
|
} from "../util/insert";
|
|
29
27
|
import { isValidIdentifier, isEquivalent } from "../util/compare";
|
|
30
28
|
import { walk, isBlock } from "../traverse";
|
|
@@ -97,7 +95,7 @@ export default class Minify extends Transform {
|
|
|
97
95
|
var sequences: { index: number; exprs: Node[] }[] = [];
|
|
98
96
|
|
|
99
97
|
body.forEach((stmt, i) => {
|
|
100
|
-
if (stmt.type == "ExpressionStatement") {
|
|
98
|
+
if (stmt.type == "ExpressionStatement" && !stmt.directive) {
|
|
101
99
|
exprs.push(stmt.expression);
|
|
102
100
|
if (startIndex == -1) {
|
|
103
101
|
startIndex = i;
|
|
@@ -129,51 +127,52 @@ export default class Minify extends Transform {
|
|
|
129
127
|
});
|
|
130
128
|
}
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
130
|
+
// Unnecessary return
|
|
131
|
+
if (
|
|
132
|
+
parents[0] &&
|
|
133
|
+
isVarContext(parents[0]) &&
|
|
134
|
+
body.length &&
|
|
135
|
+
body[body.length - 1]
|
|
136
|
+
) {
|
|
137
|
+
var last = body[body.length - 1];
|
|
138
|
+
if (last.type == "ReturnStatement") {
|
|
139
|
+
var isUndefined = last.argument == null;
|
|
140
|
+
|
|
141
|
+
if (isUndefined) {
|
|
142
|
+
body.pop();
|
|
144
143
|
}
|
|
145
144
|
}
|
|
145
|
+
}
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
} else {
|
|
165
|
-
lastDec.declarations.push(...clone(x.declarations));
|
|
166
|
-
remove.unshift(i);
|
|
167
|
-
}
|
|
147
|
+
// Variable declaration grouping
|
|
148
|
+
// var a = 1;
|
|
149
|
+
// var b = 1;
|
|
150
|
+
// var c = 1;
|
|
151
|
+
//
|
|
152
|
+
// var a=1,b=1,c=1;
|
|
153
|
+
var lastDec = null;
|
|
154
|
+
|
|
155
|
+
var remove = [];
|
|
156
|
+
body.forEach((x, i) => {
|
|
157
|
+
if (x.type === "VariableDeclaration") {
|
|
158
|
+
if (
|
|
159
|
+
!lastDec ||
|
|
160
|
+
lastDec.kind !== x.kind ||
|
|
161
|
+
!lastDec.declarations.length
|
|
162
|
+
) {
|
|
163
|
+
lastDec = x;
|
|
168
164
|
} else {
|
|
169
|
-
lastDec
|
|
165
|
+
lastDec.declarations.push(...clone(x.declarations));
|
|
166
|
+
remove.unshift(i);
|
|
170
167
|
}
|
|
171
|
-
}
|
|
168
|
+
} else {
|
|
169
|
+
lastDec = null;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
173
|
+
remove.forEach((x) => {
|
|
174
|
+
body.splice(x, 1);
|
|
175
|
+
});
|
|
177
176
|
};
|
|
178
177
|
}
|
|
179
178
|
|
|
@@ -203,28 +202,38 @@ export default class Minify extends Transform {
|
|
|
203
202
|
}
|
|
204
203
|
}
|
|
205
204
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
var block = parents[blockIndex];
|
|
209
|
-
var body = block.body;
|
|
205
|
+
if (object.type === "FunctionDeclaration") {
|
|
206
|
+
var body = parents[0];
|
|
210
207
|
if (!Array.isArray(body)) {
|
|
211
208
|
return;
|
|
212
209
|
}
|
|
213
210
|
|
|
214
|
-
var
|
|
215
|
-
|
|
216
|
-
var index = body.indexOf(stmt);
|
|
211
|
+
var index = body.indexOf(object);
|
|
217
212
|
if (index == -1) {
|
|
218
213
|
return;
|
|
219
214
|
}
|
|
220
215
|
|
|
221
216
|
var before = body.slice(0, index);
|
|
222
|
-
ok(!before.includes(
|
|
217
|
+
ok(!before.includes(object));
|
|
223
218
|
|
|
224
|
-
var
|
|
225
|
-
|
|
219
|
+
var beforeTypes = new Set(before.map((x) => x.type));
|
|
220
|
+
beforeTypes.delete("FunctionDeclaration");
|
|
226
221
|
|
|
227
|
-
if (
|
|
222
|
+
if (beforeTypes.size > 0) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Test Variant #25: Don't break redefined function declaration
|
|
227
|
+
if (
|
|
228
|
+
object.id &&
|
|
229
|
+
body.find(
|
|
230
|
+
(x) =>
|
|
231
|
+
x.type === "FunctionDeclaration" &&
|
|
232
|
+
x !== object &&
|
|
233
|
+
x.id &&
|
|
234
|
+
x.id.name === object.id.name
|
|
235
|
+
)
|
|
236
|
+
) {
|
|
228
237
|
return;
|
|
229
238
|
}
|
|
230
239
|
}
|
|
@@ -250,8 +259,15 @@ export default class Minify extends Transform {
|
|
|
250
259
|
append(
|
|
251
260
|
parents[parents.length - 1] || object,
|
|
252
261
|
Template(`
|
|
253
|
-
function ${this.arrowFunctionName}(arrowFn){
|
|
254
|
-
|
|
262
|
+
function ${this.arrowFunctionName}(arrowFn, functionLength){
|
|
263
|
+
var functionObject = function(){ return arrowFn(...arguments) };
|
|
264
|
+
|
|
265
|
+
Object["defineProperty"](functionObject, "length", {
|
|
266
|
+
"value": functionLength,
|
|
267
|
+
"configurable": true
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
return functionObject;
|
|
255
271
|
}
|
|
256
272
|
`).single()
|
|
257
273
|
);
|
|
@@ -260,6 +276,7 @@ export default class Minify extends Transform {
|
|
|
260
276
|
const wrap = (object: Node) => {
|
|
261
277
|
return CallExpression(Identifier(this.arrowFunctionName), [
|
|
262
278
|
clone(object),
|
|
279
|
+
Literal(computeFunctionLength(object.params)),
|
|
263
280
|
]);
|
|
264
281
|
};
|
|
265
282
|
|
|
@@ -298,7 +315,7 @@ export default class Minify extends Transform {
|
|
|
298
315
|
|
|
299
316
|
if (body.length == 1 && stmt1.type == "ReturnStatement") {
|
|
300
317
|
// x=>{a: 1} // Invalid syntax
|
|
301
|
-
if (stmt1.argument.type != "ObjectExpression") {
|
|
318
|
+
if (stmt1.argument && stmt1.argument.type != "ObjectExpression") {
|
|
302
319
|
object.body = stmt1.argument;
|
|
303
320
|
object.expression = true;
|
|
304
321
|
}
|
|
@@ -544,16 +561,16 @@ export default class Minify extends Transform {
|
|
|
544
561
|
object.property.type = "Identifier";
|
|
545
562
|
object.property.name = clone(object.property.value);
|
|
546
563
|
|
|
547
|
-
obj.name &&
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
564
|
+
// obj.name &&
|
|
565
|
+
// this.log(
|
|
566
|
+
// obj.name +
|
|
567
|
+
// "['" +
|
|
568
|
+
// object.property.name +
|
|
569
|
+
// "'] -> " +
|
|
570
|
+
// obj.name +
|
|
571
|
+
// "." +
|
|
572
|
+
// object.property.name
|
|
573
|
+
// );
|
|
557
574
|
}
|
|
558
575
|
}
|
|
559
576
|
|
|
@@ -572,7 +589,7 @@ export default class Minify extends Transform {
|
|
|
572
589
|
}
|
|
573
590
|
|
|
574
591
|
// { "x": 1 } -> {x: 1}
|
|
575
|
-
if (object.type
|
|
592
|
+
if (object.type === "Property" || object.type === "MethodDefinition") {
|
|
576
593
|
if (
|
|
577
594
|
object.key.type == "SequenceExpression" &&
|
|
578
595
|
object.key.expressions.length == 1
|
|
@@ -581,15 +598,14 @@ export default class Minify extends Transform {
|
|
|
581
598
|
object.computed = true;
|
|
582
599
|
}
|
|
583
600
|
|
|
584
|
-
if (
|
|
601
|
+
if (
|
|
602
|
+
object.key.type == "Literal" &&
|
|
603
|
+
typeof object.key.value === "string" &&
|
|
604
|
+
isValidIdentifier(object.key.value)
|
|
605
|
+
) {
|
|
585
606
|
object.key.type = "Identifier";
|
|
586
607
|
object.key.name = object.key.value;
|
|
587
608
|
object.computed = false;
|
|
588
|
-
} else if (
|
|
589
|
-
object.key.type == "Identifier" &&
|
|
590
|
-
!isValidIdentifier(object.key.name)
|
|
591
|
-
) {
|
|
592
|
-
object.key = Literal(object.key.name);
|
|
593
609
|
}
|
|
594
610
|
}
|
|
595
611
|
|
|
@@ -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) {
|