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
|
@@ -1,15 +1,14 @@
|
|
|
1
|
+
import { ok } from "assert";
|
|
1
2
|
import { reservedIdentifiers } from "../constants";
|
|
2
3
|
import { ObfuscateOrder } from "../order";
|
|
3
4
|
import traverse, { walk } from "../traverse";
|
|
4
5
|
import {
|
|
5
|
-
FunctionDeclaration,
|
|
6
6
|
Identifier,
|
|
7
7
|
ReturnStatement,
|
|
8
8
|
VariableDeclaration,
|
|
9
9
|
VariableDeclarator,
|
|
10
10
|
CallExpression,
|
|
11
11
|
MemberExpression,
|
|
12
|
-
ThisExpression,
|
|
13
12
|
ArrayExpression,
|
|
14
13
|
ExpressionStatement,
|
|
15
14
|
AssignmentExpression,
|
|
@@ -19,21 +18,16 @@ import {
|
|
|
19
18
|
FunctionExpression,
|
|
20
19
|
ObjectExpression,
|
|
21
20
|
Property,
|
|
22
|
-
SpreadElement,
|
|
23
21
|
Literal,
|
|
24
22
|
IfStatement,
|
|
25
23
|
ThrowStatement,
|
|
26
24
|
NewExpression,
|
|
25
|
+
AwaitExpression,
|
|
26
|
+
UnaryExpression,
|
|
27
27
|
} from "../util/gen";
|
|
28
28
|
import { getIdentifierInfo } from "../util/identifiers";
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
getVarContext,
|
|
32
|
-
isFunction,
|
|
33
|
-
prepend,
|
|
34
|
-
clone,
|
|
35
|
-
} from "../util/insert";
|
|
36
|
-
import { shuffle } from "../util/random";
|
|
29
|
+
import { getBlockBody, getVarContext, prepend, clone } from "../util/insert";
|
|
30
|
+
import { chance, shuffle } from "../util/random";
|
|
37
31
|
import Transform from "./transform";
|
|
38
32
|
|
|
39
33
|
/**
|
|
@@ -46,20 +40,19 @@ import Transform from "./transform";
|
|
|
46
40
|
* return [ref1, ref2, refN, returnValue];
|
|
47
41
|
* }
|
|
48
42
|
* ```
|
|
43
|
+
*
|
|
44
|
+
* Flatten is used to make functions eligible for the RGF transformation.
|
|
49
45
|
*/
|
|
50
46
|
export default class Flatten extends Transform {
|
|
51
47
|
definedNames: Map<Node, Set<string>>;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
flatNode: Node;
|
|
55
|
-
gen: any;
|
|
48
|
+
flattenedFns: Node[];
|
|
49
|
+
gen: ReturnType<Transform["getGenerator"]>;
|
|
56
50
|
|
|
57
51
|
constructor(o) {
|
|
58
52
|
super(o, ObfuscateOrder.Flatten);
|
|
59
53
|
|
|
60
54
|
this.definedNames = new Map();
|
|
61
|
-
this.
|
|
62
|
-
this.flatNode = null;
|
|
55
|
+
this.flattenedFns = [];
|
|
63
56
|
this.gen = this.getGenerator();
|
|
64
57
|
}
|
|
65
58
|
|
|
@@ -87,33 +80,64 @@ export default class Flatten extends Transform {
|
|
|
87
80
|
});
|
|
88
81
|
|
|
89
82
|
super.apply(tree);
|
|
83
|
+
|
|
84
|
+
if (this.flattenedFns.length) {
|
|
85
|
+
prepend(tree, VariableDeclaration(this.flattenedFns));
|
|
86
|
+
}
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
match(object: Node, parents: Node[]) {
|
|
93
90
|
return (
|
|
94
|
-
object.type == "FunctionDeclaration"
|
|
91
|
+
(object.type == "FunctionDeclaration" ||
|
|
92
|
+
object.type === "FunctionExpression") &&
|
|
95
93
|
object.body.type == "BlockStatement" &&
|
|
96
94
|
!object.generator &&
|
|
97
|
-
!object.async &&
|
|
98
95
|
!object.params.find((x) => x.type !== "Identifier")
|
|
99
96
|
);
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
transform(object: Node, parents: Node[]) {
|
|
103
100
|
return () => {
|
|
104
|
-
|
|
101
|
+
if (parents[0]) {
|
|
102
|
+
// Don't change class methods
|
|
103
|
+
if (
|
|
104
|
+
parents[0].type === "MethodDefinition" &&
|
|
105
|
+
parents[0].value === object
|
|
106
|
+
) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
105
109
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return;
|
|
110
|
+
// Don't change getter/setter methods
|
|
111
|
+
if (
|
|
112
|
+
parents[0].type === "Property" &&
|
|
113
|
+
parents[0].value === object &&
|
|
114
|
+
parents[0].kind !== "init"
|
|
115
|
+
) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
115
118
|
}
|
|
116
119
|
|
|
120
|
+
ok(
|
|
121
|
+
object.type === "FunctionDeclaration" ||
|
|
122
|
+
object.type === "FunctionExpression"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// The name is purely for debugging purposes
|
|
126
|
+
var currentFnName =
|
|
127
|
+
object.type === "FunctionDeclaration"
|
|
128
|
+
? object.id?.name
|
|
129
|
+
: parents[0]?.type === "VariableDeclarator" &&
|
|
130
|
+
parents[0].id?.type === "Identifier" &&
|
|
131
|
+
parents[0].id?.name;
|
|
132
|
+
|
|
133
|
+
if (parents[0]?.type === "Property" && parents[0]?.key) {
|
|
134
|
+
currentFnName =
|
|
135
|
+
currentFnName ||
|
|
136
|
+
String(parents[0]?.key?.name || parents[0]?.key?.value);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!currentFnName) currentFnName = "unnamed";
|
|
140
|
+
|
|
117
141
|
var defined = new Set<string>();
|
|
118
142
|
var references = new Set<string>();
|
|
119
143
|
var modified = new Set<string>();
|
|
@@ -147,9 +171,7 @@ export default class Flatten extends Transform {
|
|
|
147
171
|
|
|
148
172
|
if (o.hidden) {
|
|
149
173
|
illegal.add(o.name);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (info.spec.isDefined) {
|
|
174
|
+
} else if (info.spec.isDefined) {
|
|
153
175
|
defined.add(o.name);
|
|
154
176
|
} else if (info.spec.isModified) {
|
|
155
177
|
modified.add(o.name);
|
|
@@ -198,9 +220,6 @@ export default class Flatten extends Transform {
|
|
|
198
220
|
return;
|
|
199
221
|
}
|
|
200
222
|
|
|
201
|
-
illegal.forEach((name) => {
|
|
202
|
-
defined.delete(name);
|
|
203
|
-
});
|
|
204
223
|
defined.forEach((name) => {
|
|
205
224
|
references.delete(name);
|
|
206
225
|
modified.delete(name);
|
|
@@ -216,16 +235,35 @@ export default class Flatten extends Transform {
|
|
|
216
235
|
|
|
217
236
|
var output = Array.from(modified);
|
|
218
237
|
|
|
219
|
-
var newName = this.
|
|
220
|
-
var valName = this.getPlaceholder();
|
|
238
|
+
var newName = this.getPlaceholder() + "_flat_" + currentFnName;
|
|
221
239
|
var resultName = this.getPlaceholder();
|
|
222
240
|
var propName = this.gen.generate();
|
|
223
241
|
|
|
242
|
+
var newOutputNames: { [originalName: string]: string } =
|
|
243
|
+
Object.create(null);
|
|
244
|
+
output.forEach((name) => {
|
|
245
|
+
newOutputNames[name] = this.gen.generate();
|
|
246
|
+
});
|
|
247
|
+
var returnOutputName = this.gen.generate();
|
|
248
|
+
|
|
224
249
|
getBlockBody(object.body).push(ReturnStatement());
|
|
225
250
|
walk(object.body, [object, ...parents], (o, p) => {
|
|
226
|
-
return
|
|
227
|
-
|
|
228
|
-
|
|
251
|
+
// Change return statements from
|
|
252
|
+
// return (argument)
|
|
253
|
+
// to
|
|
254
|
+
// return [ [modifiedRefs], ]
|
|
255
|
+
if (o.type == "ReturnStatement" && getVarContext(o, p) === object) {
|
|
256
|
+
return () => {
|
|
257
|
+
var returnObject = ObjectExpression(
|
|
258
|
+
output.map((outputName) =>
|
|
259
|
+
Property(
|
|
260
|
+
Literal(newOutputNames[outputName]),
|
|
261
|
+
Identifier(outputName),
|
|
262
|
+
true
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
);
|
|
266
|
+
|
|
229
267
|
if (
|
|
230
268
|
o.argument &&
|
|
231
269
|
!(
|
|
@@ -233,11 +271,12 @@ export default class Flatten extends Transform {
|
|
|
233
271
|
o.argument.name == "undefined"
|
|
234
272
|
)
|
|
235
273
|
) {
|
|
236
|
-
|
|
274
|
+
// FIX: The return argument must be executed first so it must use 'unshift'
|
|
275
|
+
returnObject.properties.unshift(
|
|
276
|
+
Property(Literal(returnOutputName), clone(o.argument), true)
|
|
277
|
+
);
|
|
237
278
|
}
|
|
238
279
|
|
|
239
|
-
o.argument = ArrayExpression(elements);
|
|
240
|
-
|
|
241
280
|
o.argument = AssignmentExpression(
|
|
242
281
|
"=",
|
|
243
282
|
MemberExpression(
|
|
@@ -245,188 +284,192 @@ export default class Flatten extends Transform {
|
|
|
245
284
|
Identifier(propName),
|
|
246
285
|
false
|
|
247
286
|
),
|
|
248
|
-
|
|
287
|
+
returnObject
|
|
249
288
|
);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
289
|
+
};
|
|
290
|
+
}
|
|
252
291
|
});
|
|
253
292
|
|
|
254
293
|
var newBody = getBlockBody(object.body);
|
|
255
294
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
ArrayPattern([
|
|
260
|
-
ArrayPattern(input.map(Identifier)),
|
|
261
|
-
ArrayPattern(clone(object.params)),
|
|
262
|
-
Identifier(resultName),
|
|
263
|
-
]),
|
|
264
|
-
|
|
265
|
-
Identifier(valName)
|
|
266
|
-
)
|
|
267
|
-
)
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
if (!this.flatMapName) {
|
|
271
|
-
this.flatMapName = this.getPlaceholder();
|
|
272
|
-
prepend(
|
|
273
|
-
parents[parents.length - 1],
|
|
274
|
-
VariableDeclaration(
|
|
275
|
-
VariableDeclarator(
|
|
276
|
-
this.flatMapName,
|
|
277
|
-
(this.flatNode = ObjectExpression([]))
|
|
278
|
-
)
|
|
279
|
-
)
|
|
280
|
-
);
|
|
295
|
+
// Remove 'use strict' directive
|
|
296
|
+
if (newBody.length > 0 && newBody[0].directive) {
|
|
297
|
+
newBody.shift();
|
|
281
298
|
}
|
|
282
299
|
|
|
283
300
|
var newFunctionExpression = FunctionExpression(
|
|
284
|
-
[
|
|
301
|
+
[
|
|
302
|
+
ArrayPattern(input.map((name) => Identifier(name))),
|
|
303
|
+
ArrayPattern(clone(object.params)),
|
|
304
|
+
Identifier(resultName),
|
|
305
|
+
],
|
|
285
306
|
newBody
|
|
286
307
|
);
|
|
287
308
|
|
|
288
309
|
newFunctionExpression.async = !!object.async;
|
|
289
310
|
newFunctionExpression.generator = !!object.generator;
|
|
290
311
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
newFunctionExpression,
|
|
294
|
-
false
|
|
312
|
+
this.flattenedFns.push(
|
|
313
|
+
VariableDeclarator(newName, newFunctionExpression)
|
|
295
314
|
);
|
|
296
|
-
property.kind = "set";
|
|
297
|
-
|
|
298
|
-
this.flatNode.properties.push(property);
|
|
299
315
|
|
|
300
|
-
var
|
|
301
|
-
|
|
302
|
-
Identifier(newName),
|
|
303
|
-
false
|
|
316
|
+
var newParamNames: string[] = object.params.map(() =>
|
|
317
|
+
this.getPlaceholder()
|
|
304
318
|
);
|
|
305
319
|
|
|
306
|
-
var newParamNodes = object.params.map(() =>
|
|
307
|
-
Identifier(this.getPlaceholder())
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
// var result = newFn.call([...refs], ...arguments)
|
|
311
|
-
var call = VariableDeclaration([
|
|
312
|
-
VariableDeclarator(resultName, ArrayExpression([])),
|
|
313
|
-
VariableDeclarator(
|
|
314
|
-
"_",
|
|
315
|
-
AssignmentExpression(
|
|
316
|
-
"=",
|
|
317
|
-
identifier,
|
|
318
|
-
ArrayExpression([
|
|
319
|
-
ArrayExpression(input.map(Identifier)),
|
|
320
|
-
ArrayExpression([...newParamNodes]),
|
|
321
|
-
Identifier(resultName),
|
|
322
|
-
])
|
|
323
|
-
)
|
|
324
|
-
),
|
|
325
|
-
]);
|
|
326
|
-
|
|
327
320
|
// result.pop()
|
|
328
|
-
var
|
|
321
|
+
var getOutputMemberExpression = (outputName) =>
|
|
329
322
|
MemberExpression(
|
|
330
|
-
MemberExpression(Identifier(resultName),
|
|
331
|
-
Literal(
|
|
323
|
+
MemberExpression(Identifier(resultName), Literal(propName), true),
|
|
324
|
+
Literal(outputName),
|
|
332
325
|
true
|
|
333
|
-
)
|
|
334
|
-
[]
|
|
335
|
-
);
|
|
326
|
+
);
|
|
336
327
|
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
328
|
+
// newFn.call([...refs], ...arguments, resultObject)
|
|
329
|
+
var callExpression = CallExpression(Identifier(newName), [
|
|
330
|
+
ArrayExpression(input.map((name) => Identifier(name))),
|
|
331
|
+
ArrayExpression(newParamNames.map((name) => Identifier(name))),
|
|
332
|
+
Identifier(resultName),
|
|
333
|
+
]);
|
|
334
|
+
|
|
335
|
+
var newObjectBody: Node[] = [
|
|
336
|
+
// var resultObject = {};
|
|
337
|
+
VariableDeclaration([
|
|
338
|
+
VariableDeclarator(resultName, ObjectExpression([])),
|
|
339
|
+
]),
|
|
340
|
+
|
|
341
|
+
ExpressionStatement(
|
|
342
|
+
newFunctionExpression.async
|
|
343
|
+
? AwaitExpression(callExpression)
|
|
344
|
+
: callExpression
|
|
345
|
+
),
|
|
346
|
+
];
|
|
343
347
|
|
|
344
|
-
var newObjectBody: Node[] = [call];
|
|
345
348
|
var outputReversed = [...output].reverse();
|
|
346
349
|
|
|
350
|
+
// realVar
|
|
351
|
+
outputReversed.forEach((outputName) => {
|
|
352
|
+
newObjectBody.push(
|
|
353
|
+
ExpressionStatement(
|
|
354
|
+
AssignmentExpression(
|
|
355
|
+
"=",
|
|
356
|
+
Identifier(outputName),
|
|
357
|
+
getOutputMemberExpression(newOutputNames[outputName])
|
|
358
|
+
)
|
|
359
|
+
)
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
|
|
347
363
|
// DECOY STATEMENTS
|
|
348
364
|
var decoyKey = this.gen.generate();
|
|
349
365
|
var decoyNodes = [
|
|
366
|
+
// if (result.random) throw result.prop.random
|
|
350
367
|
IfStatement(
|
|
351
368
|
MemberExpression(
|
|
352
369
|
Identifier(resultName),
|
|
353
|
-
|
|
354
|
-
|
|
370
|
+
Literal(this.gen.generate()),
|
|
371
|
+
true
|
|
355
372
|
),
|
|
356
373
|
[
|
|
357
374
|
ThrowStatement(
|
|
358
375
|
NewExpression(Identifier("Error"), [
|
|
359
|
-
|
|
376
|
+
getOutputMemberExpression(this.gen.generate()),
|
|
360
377
|
])
|
|
361
378
|
),
|
|
362
379
|
]
|
|
363
380
|
),
|
|
381
|
+
// if (result.random) return true;
|
|
364
382
|
IfStatement(
|
|
365
383
|
MemberExpression(
|
|
366
384
|
Identifier(resultName),
|
|
367
|
-
|
|
368
|
-
|
|
385
|
+
Literal(this.gen.generate()),
|
|
386
|
+
true
|
|
369
387
|
),
|
|
370
|
-
[ReturnStatement(
|
|
388
|
+
[ReturnStatement(Literal(true))]
|
|
371
389
|
),
|
|
390
|
+
// if (result.random) return result;
|
|
372
391
|
IfStatement(
|
|
373
392
|
MemberExpression(
|
|
374
393
|
Identifier(resultName),
|
|
375
|
-
|
|
376
|
-
|
|
394
|
+
Literal(this.gen.generate()),
|
|
395
|
+
true
|
|
377
396
|
),
|
|
378
397
|
[ReturnStatement(Identifier(resultName))]
|
|
379
398
|
),
|
|
399
|
+
// if (result.random) return result.random;
|
|
380
400
|
IfStatement(
|
|
381
|
-
MemberExpression(Identifier(resultName),
|
|
401
|
+
MemberExpression(Identifier(resultName), Literal(decoyKey), true),
|
|
382
402
|
[
|
|
383
403
|
ReturnStatement(
|
|
384
|
-
MemberExpression(
|
|
385
|
-
Identifier(resultName),
|
|
386
|
-
Identifier(decoyKey),
|
|
387
|
-
false
|
|
388
|
-
)
|
|
404
|
+
MemberExpression(Identifier(resultName), Literal(decoyKey), true)
|
|
389
405
|
),
|
|
390
406
|
]
|
|
391
407
|
),
|
|
408
|
+
// if(result.random1) return result.random2;
|
|
392
409
|
IfStatement(
|
|
393
410
|
MemberExpression(
|
|
394
411
|
Identifier(resultName),
|
|
395
|
-
|
|
396
|
-
|
|
412
|
+
Literal(this.gen.generate()),
|
|
413
|
+
true
|
|
397
414
|
),
|
|
398
415
|
[
|
|
399
416
|
ReturnStatement(
|
|
400
417
|
MemberExpression(
|
|
401
418
|
Identifier(resultName),
|
|
402
|
-
|
|
403
|
-
|
|
419
|
+
Literal(this.gen.generate()),
|
|
420
|
+
true
|
|
404
421
|
)
|
|
405
422
|
),
|
|
406
423
|
]
|
|
407
424
|
),
|
|
408
|
-
|
|
425
|
+
// if(result.random) return flatFn;
|
|
426
|
+
IfStatement(
|
|
427
|
+
MemberExpression(
|
|
428
|
+
Identifier(resultName),
|
|
429
|
+
Literal(this.gen.generate()),
|
|
430
|
+
true
|
|
431
|
+
),
|
|
432
|
+
[ReturnStatement(Identifier(newName))]
|
|
433
|
+
),
|
|
434
|
+
// if(result.random) flatFn = undefined;
|
|
435
|
+
IfStatement(
|
|
436
|
+
MemberExpression(
|
|
437
|
+
Identifier(resultName),
|
|
438
|
+
Literal(this.gen.generate()),
|
|
439
|
+
true
|
|
440
|
+
),
|
|
441
|
+
[
|
|
442
|
+
ExpressionStatement(
|
|
443
|
+
AssignmentExpression(
|
|
444
|
+
"=",
|
|
445
|
+
Identifier(newName),
|
|
446
|
+
Identifier("undefined")
|
|
447
|
+
)
|
|
448
|
+
),
|
|
449
|
+
]
|
|
450
|
+
),
|
|
451
|
+
// if(!result) return;
|
|
452
|
+
IfStatement(UnaryExpression("!", Identifier(resultName)), [
|
|
453
|
+
ReturnStatement(),
|
|
454
|
+
]),
|
|
455
|
+
].filter(() => chance(25));
|
|
456
|
+
|
|
457
|
+
// if (result.output) return result.output.returnValue;
|
|
458
|
+
// this is the real return statement, it is always added
|
|
459
|
+
decoyNodes.push(
|
|
460
|
+
IfStatement(
|
|
461
|
+
MemberExpression(Identifier(resultName), Literal(propName), true),
|
|
462
|
+
[ReturnStatement(getOutputMemberExpression(returnOutputName))]
|
|
463
|
+
)
|
|
464
|
+
);
|
|
409
465
|
|
|
410
466
|
shuffle(decoyNodes);
|
|
411
|
-
decoyNodes.forEach((decoyNode) => {
|
|
412
|
-
if (Math.random() < 0.5) {
|
|
413
|
-
newObjectBody.push(decoyNode);
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
467
|
|
|
417
|
-
newObjectBody.push(
|
|
418
|
-
...outputReversed.map((name) => {
|
|
419
|
-
return ExpressionStatement(
|
|
420
|
-
AssignmentExpression("=", Identifier(name), clone(pop))
|
|
421
|
-
);
|
|
422
|
-
}),
|
|
423
|
-
|
|
424
|
-
ReturnStatement(clone(pop))
|
|
425
|
-
);
|
|
468
|
+
newObjectBody.push(...decoyNodes);
|
|
426
469
|
|
|
427
470
|
object.body = BlockStatement(newObjectBody);
|
|
428
471
|
|
|
429
|
-
object.params =
|
|
472
|
+
object.params = newParamNames.map((name) => Identifier(name));
|
|
430
473
|
};
|
|
431
474
|
}
|
|
432
475
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { reservedKeywords } from "../../constants";
|
|
2
|
+
import { Location, Node } from "../../util/gen";
|
|
3
|
+
import { getIdentifierInfo } from "../../util/identifiers";
|
|
4
|
+
import Transform from "../transform";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Global Analysis is responsible for finding all the global variables used in the code.
|
|
8
|
+
*
|
|
9
|
+
* A 'global variable' is one that is:
|
|
10
|
+
* - Referenced
|
|
11
|
+
* - Never defined or overridden
|
|
12
|
+
*/
|
|
13
|
+
export default class GlobalAnalysis extends Transform {
|
|
14
|
+
notGlobals: Set<string>;
|
|
15
|
+
globals: { [name: string]: Location[] };
|
|
16
|
+
|
|
17
|
+
constructor(o) {
|
|
18
|
+
super(o);
|
|
19
|
+
|
|
20
|
+
this.globals = Object.create(null);
|
|
21
|
+
this.notGlobals = new Set();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
match(object: Node, parents: Node[]) {
|
|
25
|
+
return object.type == "Identifier" && !reservedKeywords.has(object.name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
transform(object: Node, parents: Node[]) {
|
|
29
|
+
// no touching `import()` or `import x from ...`
|
|
30
|
+
var importIndex = parents.findIndex(
|
|
31
|
+
(x) => x.type == "ImportExpression" || x.type == "ImportDeclaration"
|
|
32
|
+
);
|
|
33
|
+
if (importIndex !== -1) {
|
|
34
|
+
if (
|
|
35
|
+
parents[importIndex].source === (parents[importIndex - 1] || object)
|
|
36
|
+
) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var info = getIdentifierInfo(object, parents);
|
|
42
|
+
if (!info.spec.isReferenced) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Cannot be defined or overridden
|
|
47
|
+
if (info.spec.isDefined || info.spec.isModified) {
|
|
48
|
+
delete this.globals[object.name];
|
|
49
|
+
|
|
50
|
+
this.notGlobals.add(object.name);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Add to globals
|
|
55
|
+
if (!this.notGlobals.has(object.name)) {
|
|
56
|
+
if (!this.globals[object.name]) {
|
|
57
|
+
this.globals[object.name] = [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.globals[object.name].push([object, parents]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var assignmentIndex = parents.findIndex(
|
|
64
|
+
(x) => x.type == "AssignmentExpression"
|
|
65
|
+
);
|
|
66
|
+
var updateIndex = parents.findIndex((x) => x.type == "UpdateExpression");
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
(assignmentIndex != -1 &&
|
|
70
|
+
parents[assignmentIndex].left ===
|
|
71
|
+
(parents[assignmentIndex - 1] || object)) ||
|
|
72
|
+
updateIndex != -1
|
|
73
|
+
) {
|
|
74
|
+
var memberIndex = parents.findIndex((x) => x.type == "MemberExpression");
|
|
75
|
+
if (
|
|
76
|
+
memberIndex == -1 ||
|
|
77
|
+
memberIndex > (assignmentIndex == -1 ? assignmentIndex : updateIndex)
|
|
78
|
+
) {
|
|
79
|
+
delete this.globals[object.name];
|
|
80
|
+
|
|
81
|
+
this.notGlobals.add(object.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|