js-confuser 1.2.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -0
- package/README.md +7 -6
- package/dist/options.js +5 -1
- package/dist/parser.js +1 -2
- package/dist/presets.js +2 -2
- package/dist/transforms/calculator.js +48 -60
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
- package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
- package/dist/transforms/deadCode.js +1 -1
- package/dist/transforms/dispatcher.js +14 -13
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
- package/dist/transforms/flatten.js +5 -1
- package/dist/transforms/hideInitializingCode.js +17 -2
- package/dist/transforms/identifier/globalConcealing.js +46 -25
- package/dist/transforms/identifier/movedDeclarations.js +69 -68
- package/dist/transforms/identifier/renameVariables.js +22 -98
- package/dist/transforms/identifier/variableAnalysis.js +133 -0
- package/dist/transforms/label.js +11 -2
- package/dist/transforms/lock/antiDebug.js +32 -13
- package/dist/transforms/lock/lock.js +13 -2
- package/dist/transforms/minify.js +117 -120
- package/dist/transforms/opaquePredicates.js +4 -2
- package/dist/transforms/preparation/preparation.js +8 -0
- package/dist/transforms/renameLabels.js +17 -3
- package/dist/transforms/rgf.js +8 -3
- package/dist/transforms/shuffle.js +25 -9
- package/dist/transforms/stack.js +5 -9
- package/dist/transforms/string/encoding.js +209 -0
- package/dist/transforms/string/stringCompression.js +10 -10
- package/dist/transforms/string/stringConcealing.js +94 -65
- package/dist/transforms/string/stringSplitting.js +7 -7
- package/dist/transforms/transform.js +10 -0
- package/dist/traverse.js +1 -35
- package/dist/util/gen.js +3 -1
- package/dist/util/identifiers.js +9 -19
- package/dist/util/insert.js +6 -40
- package/dist/util/scope.js +17 -0
- package/package.json +2 -2
- package/src/options.ts +19 -3
- package/src/parser.ts +1 -2
- package/src/presets.ts +2 -2
- package/src/transforms/calculator.ts +87 -91
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
- package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
- package/src/transforms/deadCode.ts +8 -0
- package/src/transforms/dispatcher.ts +29 -14
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
- package/src/transforms/flatten.ts +15 -2
- package/src/transforms/hideInitializingCode.ts +432 -406
- package/src/transforms/identifier/globalConcealing.ts +148 -46
- package/src/transforms/identifier/movedDeclarations.ts +78 -101
- package/src/transforms/identifier/renameVariables.ts +21 -96
- package/src/transforms/identifier/variableAnalysis.ts +124 -0
- package/src/transforms/label.ts +20 -2
- package/src/transforms/lock/antiDebug.ts +69 -26
- package/src/transforms/lock/lock.ts +37 -3
- package/src/transforms/minify.ts +154 -130
- package/src/transforms/opaquePredicates.ts +25 -3
- package/src/transforms/preparation/preparation.ts +8 -1
- package/src/transforms/renameLabels.ts +26 -3
- package/src/transforms/rgf.ts +6 -1
- package/src/transforms/shuffle.ts +87 -29
- package/src/transforms/stack.ts +6 -8
- package/src/transforms/string/encoding.ts +310 -0
- package/src/transforms/string/stringCompression.ts +37 -24
- package/src/transforms/string/stringConcealing.ts +157 -160
- package/src/transforms/string/stringSplitting.ts +12 -8
- package/src/transforms/transform.ts +15 -2
- package/src/traverse.ts +1 -31
- package/src/util/gen.ts +5 -3
- package/src/util/identifiers.ts +20 -20
- package/src/util/insert.ts +12 -78
- package/src/util/scope.ts +9 -0
- package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
- package/test/index.test.ts +109 -1
- package/test/templates/template.test.ts +14 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
- package/test/transforms/dispatcher.test.ts +30 -0
- package/test/transforms/flatten.test.ts +28 -0
- package/test/transforms/hideInitializingCode.test.ts +336 -336
- package/test/transforms/identifier/globalConcealing.test.ts +1 -2
- package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
- package/test/transforms/identifier/renameVariables.test.ts +124 -13
- package/test/transforms/lock/antiDebug.test.ts +43 -0
- package/test/transforms/lock/selfDefending.test.ts +68 -0
- package/test/transforms/minify.test.ts +137 -0
- package/test/transforms/renameLabels.test.ts +33 -0
- package/test/transforms/rgf.test.ts +29 -0
- package/test/transforms/string/stringSplitting.test.ts +33 -0
- package/test/util/identifiers.test.ts +105 -17
- package/dist/util/expr.js +0 -60
- package/src/util/expr.ts +0 -56
|
@@ -12,8 +12,16 @@ import {
|
|
|
12
12
|
MemberExpression,
|
|
13
13
|
SwitchStatement,
|
|
14
14
|
SwitchCase,
|
|
15
|
+
LogicalExpression,
|
|
16
|
+
VariableDeclarator,
|
|
17
|
+
FunctionExpression,
|
|
18
|
+
ExpressionStatement,
|
|
19
|
+
SequenceExpression,
|
|
20
|
+
AssignmentExpression,
|
|
21
|
+
VariableDeclaration,
|
|
22
|
+
BreakStatement,
|
|
15
23
|
} from "../../util/gen";
|
|
16
|
-
import { prepend } from "../../util/insert";
|
|
24
|
+
import { append, prepend } from "../../util/insert";
|
|
17
25
|
import { getIdentifierInfo } from "../../util/identifiers";
|
|
18
26
|
import { getRandomInteger } from "../../util/random";
|
|
19
27
|
import { reservedIdentifiers, reservedKeywords } from "../../constants";
|
|
@@ -98,15 +106,12 @@ class GlobalAnalysis extends Transform {
|
|
|
98
106
|
*/
|
|
99
107
|
export default class GlobalConcealing extends Transform {
|
|
100
108
|
globalAnalysis: GlobalAnalysis;
|
|
101
|
-
globalVar: string;
|
|
102
109
|
|
|
103
110
|
constructor(o) {
|
|
104
111
|
super(o, ObfuscateOrder.GlobalConcealing);
|
|
105
112
|
|
|
106
113
|
this.globalAnalysis = new GlobalAnalysis(o);
|
|
107
114
|
this.before.push(this.globalAnalysis);
|
|
108
|
-
|
|
109
|
-
this.globalVar = null;
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
match(object: Node, parents: Node[]) {
|
|
@@ -120,6 +125,8 @@ export default class GlobalConcealing extends Transform {
|
|
|
120
125
|
delete globals[del];
|
|
121
126
|
});
|
|
122
127
|
|
|
128
|
+
delete globals["require"];
|
|
129
|
+
|
|
123
130
|
reservedIdentifiers.forEach((x) => {
|
|
124
131
|
delete globals[x];
|
|
125
132
|
});
|
|
@@ -141,28 +148,38 @@ export default class GlobalConcealing extends Transform {
|
|
|
141
148
|
|
|
142
149
|
// 1. Make getter function
|
|
143
150
|
|
|
144
|
-
|
|
151
|
+
// holds "window" or "global"
|
|
152
|
+
var globalVar = this.getPlaceholder();
|
|
153
|
+
|
|
154
|
+
// holds outermost "this"
|
|
155
|
+
var thisVar = this.getPlaceholder();
|
|
156
|
+
|
|
145
157
|
// "window" or "global" in node
|
|
146
158
|
var global =
|
|
147
159
|
this.options.globalVariables.values().next().value || "window";
|
|
148
|
-
var
|
|
160
|
+
var getGlobalVariableFnName = this.getPlaceholder();
|
|
161
|
+
var getThisVariableFnName = this.getPlaceholder();
|
|
149
162
|
|
|
150
163
|
// Returns global variable or fall backs to `this`
|
|
151
|
-
var
|
|
152
|
-
|
|
164
|
+
var getGlobalVariableFn = Template(`
|
|
165
|
+
var ${getGlobalVariableFnName} = function(){
|
|
153
166
|
try {
|
|
154
167
|
return ${global};
|
|
155
168
|
} catch (e){
|
|
169
|
+
return ${getThisVariableFnName}["call"](this);
|
|
170
|
+
}
|
|
171
|
+
}`).single();
|
|
172
|
+
|
|
173
|
+
var getThisVariableFn = Template(`
|
|
174
|
+
var ${getThisVariableFnName} = function(){
|
|
175
|
+
try {
|
|
156
176
|
return this;
|
|
177
|
+
} catch (e){
|
|
178
|
+
return null;
|
|
157
179
|
}
|
|
158
180
|
}`).single();
|
|
159
181
|
|
|
160
182
|
// 2. Replace old accessors
|
|
161
|
-
|
|
162
|
-
var variableDeclaration = Template(`
|
|
163
|
-
var ${this.globalVar} = ${callee}.call(this);
|
|
164
|
-
`).single();
|
|
165
|
-
|
|
166
183
|
var globalFn = this.getPlaceholder();
|
|
167
184
|
|
|
168
185
|
var newNames = Object.create(null);
|
|
@@ -179,6 +196,20 @@ export default class GlobalConcealing extends Transform {
|
|
|
179
196
|
|
|
180
197
|
locations.forEach(([node, parents]) => {
|
|
181
198
|
if (!parents.find((x) => x.$dispatcherSkip)) {
|
|
199
|
+
// Do not replace
|
|
200
|
+
if (parents[0]) {
|
|
201
|
+
if (
|
|
202
|
+
parents[0].type == "ClassDeclaration" ||
|
|
203
|
+
parents[0].type == "ClassExpression" ||
|
|
204
|
+
parents[0].type == "FunctionExpression" ||
|
|
205
|
+
parents[0].type == "FunctionDeclaration"
|
|
206
|
+
) {
|
|
207
|
+
if (parents[0].id === node) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
182
213
|
this.replace(
|
|
183
214
|
node,
|
|
184
215
|
CallExpression(Identifier(globalFn), [Literal(state)])
|
|
@@ -188,49 +219,120 @@ export default class GlobalConcealing extends Transform {
|
|
|
188
219
|
});
|
|
189
220
|
|
|
190
221
|
// Adds all global variables to the switch statement
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
222
|
+
this.options.globalVariables.forEach((name) => {
|
|
223
|
+
if (!newNames[name]) {
|
|
224
|
+
var state;
|
|
225
|
+
do {
|
|
226
|
+
state = getRandomInteger(
|
|
227
|
+
-1000,
|
|
228
|
+
1000 + used.size + this.options.globalVariables.size * 100
|
|
229
|
+
);
|
|
230
|
+
} while (used.has(state));
|
|
231
|
+
used.add(state);
|
|
232
|
+
|
|
233
|
+
newNames[name] = state;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
var indexParamName = this.getPlaceholder();
|
|
238
|
+
var returnName = this.getPlaceholder();
|
|
239
|
+
|
|
240
|
+
var functionDeclaration = FunctionDeclaration(
|
|
241
|
+
globalFn,
|
|
242
|
+
[Identifier(indexParamName)],
|
|
243
|
+
[
|
|
244
|
+
VariableDeclaration(VariableDeclarator(returnName)),
|
|
245
|
+
SwitchStatement(
|
|
246
|
+
Identifier(indexParamName),
|
|
247
|
+
Object.keys(newNames).map((name) => {
|
|
248
|
+
var code = newNames[name];
|
|
249
|
+
var body: Node[] = [
|
|
250
|
+
ReturnStatement(
|
|
251
|
+
LogicalExpression(
|
|
252
|
+
"||",
|
|
219
253
|
MemberExpression(
|
|
220
|
-
Identifier(
|
|
254
|
+
Identifier(globalVar),
|
|
221
255
|
Literal(name),
|
|
222
256
|
true
|
|
257
|
+
),
|
|
258
|
+
MemberExpression(Identifier(thisVar), Literal(name), true)
|
|
259
|
+
)
|
|
260
|
+
),
|
|
261
|
+
];
|
|
262
|
+
if (Math.random() > 0.5 && name) {
|
|
263
|
+
body = [
|
|
264
|
+
ExpressionStatement(
|
|
265
|
+
AssignmentExpression(
|
|
266
|
+
"=",
|
|
267
|
+
Identifier(returnName),
|
|
268
|
+
LogicalExpression(
|
|
269
|
+
"||",
|
|
270
|
+
Literal(name),
|
|
271
|
+
MemberExpression(
|
|
272
|
+
Identifier(thisVar),
|
|
273
|
+
Literal(name),
|
|
274
|
+
true
|
|
275
|
+
)
|
|
276
|
+
)
|
|
223
277
|
)
|
|
224
278
|
),
|
|
225
|
-
|
|
226
|
-
|
|
279
|
+
BreakStatement(),
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return SwitchCase(Literal(code), body);
|
|
284
|
+
})
|
|
285
|
+
),
|
|
286
|
+
ReturnStatement(
|
|
287
|
+
LogicalExpression(
|
|
288
|
+
"||",
|
|
289
|
+
MemberExpression(
|
|
290
|
+
Identifier(globalVar),
|
|
291
|
+
Identifier(returnName),
|
|
292
|
+
true
|
|
293
|
+
),
|
|
294
|
+
MemberExpression(
|
|
295
|
+
Identifier(thisVar),
|
|
296
|
+
Identifier(returnName),
|
|
297
|
+
true
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
),
|
|
301
|
+
]
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
var tempVar = this.getPlaceholder();
|
|
305
|
+
|
|
306
|
+
var variableDeclaration = Template(`
|
|
307
|
+
var ${globalVar}, ${thisVar};
|
|
308
|
+
`).single();
|
|
309
|
+
|
|
310
|
+
variableDeclaration.declarations.push(
|
|
311
|
+
VariableDeclarator(
|
|
312
|
+
tempVar,
|
|
313
|
+
CallExpression(
|
|
314
|
+
MemberExpression(
|
|
315
|
+
FunctionExpression(
|
|
316
|
+
[],
|
|
317
|
+
[
|
|
318
|
+
getGlobalVariableFn,
|
|
319
|
+
getThisVariableFn,
|
|
320
|
+
|
|
321
|
+
Template(
|
|
322
|
+
`return ${thisVar} = ${getThisVariableFnName}["call"](this, ${globalFn}), ${globalVar} = ${getGlobalVariableFnName}["call"](this)`
|
|
323
|
+
).single(),
|
|
324
|
+
]
|
|
325
|
+
),
|
|
326
|
+
Literal("call"),
|
|
327
|
+
true
|
|
227
328
|
),
|
|
228
|
-
|
|
329
|
+
[]
|
|
330
|
+
)
|
|
229
331
|
)
|
|
230
332
|
);
|
|
231
333
|
|
|
232
334
|
prepend(object, variableDeclaration);
|
|
233
|
-
|
|
335
|
+
append(object, functionDeclaration);
|
|
234
336
|
}
|
|
235
337
|
};
|
|
236
338
|
}
|
|
@@ -7,14 +7,16 @@ import {
|
|
|
7
7
|
AssignmentExpression,
|
|
8
8
|
Identifier,
|
|
9
9
|
Node,
|
|
10
|
-
VariableDeclaration,
|
|
11
10
|
VariableDeclarator,
|
|
11
|
+
VariableDeclaration,
|
|
12
12
|
} from "../../util/gen";
|
|
13
13
|
import { clone, isForInitialize, isFunction, prepend } from "../../util/insert";
|
|
14
14
|
import { ok } from "assert";
|
|
15
15
|
import { ObfuscateOrder } from "../../order";
|
|
16
16
|
import { getIdentifierInfo } from "../../util/identifiers";
|
|
17
17
|
import { isLoop } from "../../util/compare";
|
|
18
|
+
import { reservedIdentifiers } from "../../constants";
|
|
19
|
+
import { isLexicalScope, getLexicalScope } from "../../util/scope";
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Defines all the names at the top of every lexical block.
|
|
@@ -25,139 +27,114 @@ export default class MovedDeclarations extends Transform {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
match(object, parents) {
|
|
28
|
-
return
|
|
30
|
+
return isLexicalScope(object);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
transform(object: Node, parents: Node[]) {
|
|
32
34
|
return () => {
|
|
33
|
-
var
|
|
35
|
+
var body = isBlock(object) ? object.body : object.consequent;
|
|
36
|
+
ok(Array.isArray(body));
|
|
34
37
|
|
|
35
|
-
var varDecs: Location[] = [];
|
|
36
|
-
var varNames = new Set<string>();
|
|
37
38
|
var illegal = new Set<string>();
|
|
38
|
-
var
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
var defined = new Set<string>();
|
|
40
|
+
var variableDeclarations: {
|
|
41
|
+
[name: string]: {
|
|
42
|
+
location: Location;
|
|
43
|
+
replace: Node;
|
|
44
|
+
};
|
|
45
|
+
} = Object.create(null);
|
|
46
|
+
|
|
47
|
+
walk(object, parents, (o, p) => {
|
|
48
|
+
if (o.type == "Identifier") {
|
|
49
|
+
if (getLexicalScope(o, p) !== object) {
|
|
45
50
|
illegal.add(o.name);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
51
|
+
} else {
|
|
52
|
+
var info = getIdentifierInfo(o, p);
|
|
53
|
+
if (!info.spec.isReferenced) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
if (info.spec.isDefined) {
|
|
58
|
+
if (info.isFunctionDeclaration || info.isClassDeclaration) {
|
|
59
|
+
illegal.add(o.name);
|
|
60
|
+
} else {
|
|
61
|
+
if (defined.has(o.name)) {
|
|
62
|
+
illegal.add(o.name);
|
|
63
|
+
} else {
|
|
64
|
+
defined.add(o.name);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
55
68
|
}
|
|
56
69
|
}
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
if (s == block) {
|
|
71
|
+
if (o.type == "VariableDeclaration") {
|
|
60
72
|
return () => {
|
|
61
73
|
if (
|
|
62
|
-
o.
|
|
63
|
-
o.declarations.
|
|
64
|
-
o.kind !== "let" &&
|
|
65
|
-
!o.declarations.find(
|
|
66
|
-
(x) => x.id.type !== "Identifier" || illegal.has(x.id.name)
|
|
67
|
-
)
|
|
74
|
+
o.declarations.length === 1 &&
|
|
75
|
+
o.declarations[0].id.type === "Identifier"
|
|
68
76
|
) {
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.log(
|
|
75
|
-
o.declarations.map((x) => x.id.name).join(", "),
|
|
76
|
-
"is/are illegal due to already being at the top"
|
|
77
|
-
);
|
|
77
|
+
var name = o.declarations[0].id.name;
|
|
78
|
+
|
|
79
|
+
// Check if duplicate
|
|
80
|
+
if (variableDeclarations[name] || o.kind !== "var") {
|
|
81
|
+
illegal.add(name);
|
|
78
82
|
return;
|
|
79
83
|
}
|
|
80
84
|
|
|
81
|
-
if
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"is/are illegal due to being in for initializer"
|
|
85
|
-
);
|
|
85
|
+
// Check if already at top
|
|
86
|
+
if (body[0] === o) {
|
|
87
|
+
illegal.add(name);
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
var
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (!isIllegal) {
|
|
103
|
-
varDecs.push([o, p]);
|
|
104
|
-
|
|
105
|
-
o.declarations.forEach((x) => {
|
|
106
|
-
ok(x.id.name);
|
|
107
|
-
varNames.add(x.id.name);
|
|
108
|
-
|
|
109
|
-
definingIdentifiers.set(x.id.name, x.id);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Change this line to assignment expressions
|
|
113
|
-
|
|
114
|
-
var assignmentExpressions = o.declarations.map((x) =>
|
|
115
|
-
AssignmentExpression(
|
|
116
|
-
"=",
|
|
117
|
-
clone(x.id),
|
|
118
|
-
clone(x.init) || Identifier("undefined")
|
|
119
|
-
)
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
ok(assignmentExpressions.length, "Should be at least 1");
|
|
123
|
-
|
|
124
|
-
var value: Node = SequenceExpression(assignmentExpressions);
|
|
125
|
-
|
|
126
|
-
value = ExpressionStatement(value);
|
|
127
|
-
|
|
128
|
-
toReplace.push([
|
|
129
|
-
o.declarations.map((x) => x.id.name),
|
|
130
|
-
o,
|
|
131
|
-
value,
|
|
132
|
-
]);
|
|
91
|
+
var replace: Node = AssignmentExpression(
|
|
92
|
+
"=",
|
|
93
|
+
Identifier(name),
|
|
94
|
+
o.declarations[0].init || Identifier("undefined")
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
var forType = isForInitialize(o, p);
|
|
98
|
+
if (forType === "left-hand") {
|
|
99
|
+
replace = Identifier(name);
|
|
100
|
+
} else if (!forType) {
|
|
101
|
+
replace = ExpressionStatement(replace);
|
|
133
102
|
}
|
|
103
|
+
variableDeclarations[name] = {
|
|
104
|
+
location: [o, p],
|
|
105
|
+
replace: replace,
|
|
106
|
+
};
|
|
134
107
|
}
|
|
135
108
|
};
|
|
136
109
|
}
|
|
137
110
|
});
|
|
138
111
|
|
|
139
112
|
illegal.forEach((name) => {
|
|
140
|
-
|
|
113
|
+
delete variableDeclarations[name];
|
|
141
114
|
});
|
|
142
115
|
|
|
143
|
-
|
|
144
|
-
if (!x[0].find((x) => illegal.has(x))) {
|
|
145
|
-
this.replace(x[1], x[2]);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
116
|
+
var movingNames = Object.keys(variableDeclarations);
|
|
148
117
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
118
|
+
if (movingNames.length === 0) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
152
121
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
122
|
+
var variableDeclaration = VariableDeclaration(
|
|
123
|
+
movingNames.map((name) => {
|
|
124
|
+
return VariableDeclarator(name);
|
|
125
|
+
})
|
|
126
|
+
);
|
|
158
127
|
|
|
159
|
-
|
|
128
|
+
if (object.type == "Program") {
|
|
129
|
+
prepend(object, variableDeclaration);
|
|
130
|
+
} else {
|
|
131
|
+
body.unshift(variableDeclaration);
|
|
160
132
|
}
|
|
133
|
+
|
|
134
|
+
movingNames.forEach((name) => {
|
|
135
|
+
var { location, replace } = variableDeclarations[name];
|
|
136
|
+
this.replace(location[0], replace);
|
|
137
|
+
});
|
|
161
138
|
};
|
|
162
139
|
}
|
|
163
140
|
}
|
|
@@ -15,91 +15,7 @@ import { isValidIdentifier } from "../../util/compare";
|
|
|
15
15
|
import Transform from "../transform";
|
|
16
16
|
import { reservedIdentifiers } from "../../constants";
|
|
17
17
|
import { ComputeProbabilityMap } from "../../probability";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Keeps track of what identifiers are defined and referenced in each context.
|
|
21
|
-
*/
|
|
22
|
-
export class VariableAnalysis extends Transform {
|
|
23
|
-
/**
|
|
24
|
-
* Node being the context.
|
|
25
|
-
*/
|
|
26
|
-
defined: Map<Node, Set<string>>;
|
|
27
|
-
references: Map<Node, Set<string>>;
|
|
28
|
-
|
|
29
|
-
constructor(o) {
|
|
30
|
-
super(o);
|
|
31
|
-
|
|
32
|
-
this.defined = new Map();
|
|
33
|
-
this.references = new Map();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
match(object, parents) {
|
|
37
|
-
return isContext(object);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
transform(object, parents) {
|
|
41
|
-
walk(object, parents, (o, p) => {
|
|
42
|
-
if (o.type == "Identifier") {
|
|
43
|
-
var name = o.name;
|
|
44
|
-
ok(typeof name === "string");
|
|
45
|
-
if (!isValidIdentifier(name)) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (reservedIdentifiers.has(name)) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (this.options.globalVariables.has(name)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
var info = getIdentifierInfo(o, p);
|
|
57
|
-
if (!info.spec.isReferenced) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (info.spec.isExported) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
var definingContexts = info.spec.isDefined
|
|
66
|
-
? [getDefiningContext(o, p)]
|
|
67
|
-
: [getVarContext(o, p), getLexContext(o, p)];
|
|
68
|
-
|
|
69
|
-
ok(definingContexts.length);
|
|
70
|
-
|
|
71
|
-
var isDefined = info.spec.isDefined;
|
|
72
|
-
definingContexts.forEach((definingContext) => {
|
|
73
|
-
ok(
|
|
74
|
-
isContext(definingContext),
|
|
75
|
-
`${definingContext.type} is not a context`
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
if (isDefined) {
|
|
79
|
-
// Add to defined Map
|
|
80
|
-
if (!this.defined.has(definingContext)) {
|
|
81
|
-
this.defined.set(definingContext, new Set());
|
|
82
|
-
}
|
|
83
|
-
this.defined.get(definingContext).add(name);
|
|
84
|
-
this.references.has(definingContext) &&
|
|
85
|
-
this.references.get(definingContext).delete(name);
|
|
86
|
-
} else {
|
|
87
|
-
// Add to references Map
|
|
88
|
-
if (
|
|
89
|
-
!this.defined.has(definingContext) ||
|
|
90
|
-
!this.defined.get(definingContext).has(name)
|
|
91
|
-
) {
|
|
92
|
-
if (!this.references.has(definingContext)) {
|
|
93
|
-
this.references.set(definingContext, new Set());
|
|
94
|
-
}
|
|
95
|
-
this.references.get(definingContext).add(name);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
18
|
+
import VariableAnalysis from "./variableAnalysis";
|
|
103
19
|
|
|
104
20
|
/**
|
|
105
21
|
* Rename variables to randomly generated names.
|
|
@@ -123,7 +39,9 @@ export default class RenameVariables extends Transform {
|
|
|
123
39
|
super(o, ObfuscateOrder.RenameVariables);
|
|
124
40
|
|
|
125
41
|
this.changed = new Map();
|
|
126
|
-
|
|
42
|
+
|
|
43
|
+
this.variableAnalysis = new VariableAnalysis(o);
|
|
44
|
+
this.before.push(this.variableAnalysis);
|
|
127
45
|
this.gen = this.getGenerator();
|
|
128
46
|
this.generated = [];
|
|
129
47
|
}
|
|
@@ -204,16 +122,23 @@ export default class RenameVariables extends Transform {
|
|
|
204
122
|
isGlobal
|
|
205
123
|
)
|
|
206
124
|
) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
125
|
+
// Fix 2. Ensure global names aren't overridden
|
|
126
|
+
var newName;
|
|
127
|
+
do {
|
|
128
|
+
if (possible.size) {
|
|
129
|
+
var first = possible.values().next().value;
|
|
130
|
+
possible.delete(first);
|
|
131
|
+
newName = first;
|
|
132
|
+
} else {
|
|
133
|
+
// Fix 1. Use `generateIdentifier` over `gen.generate()` so Integrity can get unique variable names
|
|
134
|
+
var g = this.generateIdentifier();
|
|
135
|
+
|
|
136
|
+
newName = g;
|
|
137
|
+
this.generated.push(g);
|
|
138
|
+
}
|
|
139
|
+
} while (this.variableAnalysis.globals.has(newName));
|
|
140
|
+
|
|
141
|
+
newNames[name] = newName;
|
|
217
142
|
} else {
|
|
218
143
|
newNames[name] = name;
|
|
219
144
|
}
|