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
|
@@ -1,111 +1,30 @@
|
|
|
1
1
|
import { ok } from "assert";
|
|
2
2
|
import { ObfuscateOrder } from "../../order";
|
|
3
3
|
import Template from "../../templates/template";
|
|
4
|
+
import { isBlock } from "../../traverse";
|
|
4
5
|
import { isDirective } from "../../util/compare";
|
|
5
6
|
import {
|
|
6
7
|
ArrayExpression,
|
|
7
8
|
CallExpression,
|
|
9
|
+
ConditionalExpression,
|
|
8
10
|
FunctionDeclaration,
|
|
11
|
+
FunctionExpression,
|
|
9
12
|
Identifier,
|
|
13
|
+
IfStatement,
|
|
10
14
|
Literal,
|
|
11
15
|
MemberExpression,
|
|
12
16
|
Node,
|
|
13
17
|
ReturnStatement,
|
|
18
|
+
SequenceExpression,
|
|
19
|
+
ThisExpression,
|
|
20
|
+
UpdateExpression,
|
|
14
21
|
VariableDeclaration,
|
|
15
22
|
VariableDeclarator,
|
|
16
23
|
} from "../../util/gen";
|
|
17
|
-
import { append, prepend } from "../../util/insert";
|
|
24
|
+
import { append, isLexContext, isVarContext, prepend } from "../../util/insert";
|
|
25
|
+
import { choice, getRandomInteger, getRandomString } from "../../util/random";
|
|
18
26
|
import Transform from "../transform";
|
|
19
|
-
|
|
20
|
-
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
21
|
-
function encode_ascii85(a) {
|
|
22
|
-
var b, c, d, e, f, g, h, i, j, k;
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
for (
|
|
25
|
-
// @ts-ignore
|
|
26
|
-
!/[^\x00-\xFF]/.test(a),
|
|
27
|
-
b = "\x00\x00\x00\x00".slice(a.length % 4 || 4),
|
|
28
|
-
a += b,
|
|
29
|
-
c = [],
|
|
30
|
-
d = 0,
|
|
31
|
-
e = a.length;
|
|
32
|
-
e > d;
|
|
33
|
-
d += 4
|
|
34
|
-
)
|
|
35
|
-
(f =
|
|
36
|
-
(a.charCodeAt(d) << 24) +
|
|
37
|
-
(a.charCodeAt(d + 1) << 16) +
|
|
38
|
-
(a.charCodeAt(d + 2) << 8) +
|
|
39
|
-
a.charCodeAt(d + 3)),
|
|
40
|
-
0 !== f
|
|
41
|
-
? ((k = f % 85),
|
|
42
|
-
(f = (f - k) / 85),
|
|
43
|
-
(j = f % 85),
|
|
44
|
-
(f = (f - j) / 85),
|
|
45
|
-
(i = f % 85),
|
|
46
|
-
(f = (f - i) / 85),
|
|
47
|
-
(h = f % 85),
|
|
48
|
-
(f = (f - h) / 85),
|
|
49
|
-
(g = f % 85),
|
|
50
|
-
c.push(g + 33, h + 33, i + 33, j + 33, k + 33))
|
|
51
|
-
: c.push(122);
|
|
52
|
-
return (
|
|
53
|
-
(function (a, b) {
|
|
54
|
-
for (var c = b; c > 0; c--) a.pop();
|
|
55
|
-
})(c, b.length),
|
|
56
|
-
"<~" + String.fromCharCode.apply(String, c) + "~>"
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function decode_ascii85(a) {
|
|
61
|
-
var c,
|
|
62
|
-
d,
|
|
63
|
-
e,
|
|
64
|
-
f,
|
|
65
|
-
g,
|
|
66
|
-
h = String,
|
|
67
|
-
l = "length",
|
|
68
|
-
w = 255,
|
|
69
|
-
x = "charCodeAt",
|
|
70
|
-
y = "slice",
|
|
71
|
-
z = "replace";
|
|
72
|
-
for (
|
|
73
|
-
"<~" === a[y](0, 2) && "~>" === a[y](-2),
|
|
74
|
-
a = a[y](2, -2)[z](/s/g, "")[z]("z", "!!!!!"),
|
|
75
|
-
c = "uuuuu"[y](a[l] % 5 || 5),
|
|
76
|
-
a += c,
|
|
77
|
-
e = [],
|
|
78
|
-
f = 0,
|
|
79
|
-
g = a[l];
|
|
80
|
-
g > f;
|
|
81
|
-
f += 5
|
|
82
|
-
)
|
|
83
|
-
(d =
|
|
84
|
-
52200625 * (a[x](f) - 33) +
|
|
85
|
-
614125 * (a[x](f + 1) - 33) +
|
|
86
|
-
7225 * (a[x](f + 2) - 33) +
|
|
87
|
-
85 * (a[x](f + 3) - 33) +
|
|
88
|
-
(a[x](f + 4) - 33)),
|
|
89
|
-
e.push(w & (d >> 24), w & (d >> 16), w & (d >> 8), w & d);
|
|
90
|
-
return (
|
|
91
|
-
(function (a, b) {
|
|
92
|
-
for (var c = b; c > 0; c--) a.pop();
|
|
93
|
-
})(e, c[l]),
|
|
94
|
-
h.fromCharCode.apply(h, e)
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
var Ascii85Template = Template(`
|
|
99
|
-
function {name}(a, LL = ["fromCharCode", "apply"]) {
|
|
100
|
-
var c, d, e, f, g, h = String, l = "length", w = 255, x = "charCodeAt", y = "slice", z = "replace";
|
|
101
|
-
for ("<~" === a[y](0, 2) && "~>" === a[y](-2), a = a[y](2, -2)[z](/\s/g, "")[z]("z", "!!!!!"),
|
|
102
|
-
c = "uuuuu"[y](a[l] % 5 || 5), a += c, e = [], f = 0, g = a[l]; g > f; f += 5) d = 52200625 * (a[x](f) - 33) + 614125 * (a[x](f + 1) - 33) + 7225 * (a[x](f + 2) - 33) + 85 * (a[x](f + 3) - 33) + (a[x](f + 4) - 33),
|
|
103
|
-
e.push(w & d >> 24, w & d >> 16, w & d >> 8, w & d);
|
|
104
|
-
return function(a, b) {
|
|
105
|
-
for (var c = b; c > 0; c--) a.pop();
|
|
106
|
-
}(e, c[l]), h[LL[0]][LL[1]](h, e);
|
|
107
|
-
}
|
|
108
|
-
`);
|
|
27
|
+
import Encoding from "./encoding";
|
|
109
28
|
|
|
110
29
|
export function isModuleSource(object: Node, parents: Node[]) {
|
|
111
30
|
if (!parents[0]) {
|
|
@@ -140,83 +59,135 @@ export function isModuleSource(object: Node, parents: Node[]) {
|
|
|
140
59
|
export default class StringConcealing extends Transform {
|
|
141
60
|
arrayExpression: Node;
|
|
142
61
|
set: Set<string>;
|
|
143
|
-
index: { [str: string]: number };
|
|
62
|
+
index: { [str: string]: [number, string] };
|
|
144
63
|
|
|
145
|
-
getterName = this.getPlaceholder();
|
|
146
64
|
arrayName = this.getPlaceholder();
|
|
147
|
-
|
|
65
|
+
ignore = new Set<string>();
|
|
66
|
+
variablesMade = 1;
|
|
67
|
+
encoding: { [type: string]: string } = Object.create(null);
|
|
148
68
|
|
|
149
|
-
|
|
69
|
+
hasAllEncodings: boolean;
|
|
150
70
|
|
|
151
71
|
constructor(o) {
|
|
152
72
|
super(o, ObfuscateOrder.StringConcealing);
|
|
153
73
|
|
|
154
74
|
this.set = new Set();
|
|
155
75
|
this.index = Object.create(null);
|
|
156
|
-
|
|
76
|
+
this.arrayExpression = ArrayExpression([]);
|
|
77
|
+
this.hasAllEncodings = false;
|
|
157
78
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
79
|
+
// Pad array with useless strings
|
|
80
|
+
var dead = getRandomInteger(4, 10);
|
|
81
|
+
for (var i = 0; i < dead; i++) {
|
|
82
|
+
var str = getRandomString(getRandomInteger(4, 20));
|
|
83
|
+
var fn = this.transform(Literal(str), []);
|
|
84
|
+
if (fn) {
|
|
85
|
+
fn();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
167
88
|
}
|
|
168
89
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
90
|
+
apply(tree) {
|
|
91
|
+
super.apply(tree);
|
|
92
|
+
|
|
93
|
+
var cacheName = this.getPlaceholder();
|
|
172
94
|
|
|
173
|
-
|
|
174
|
-
|
|
95
|
+
Object.keys(this.encoding).forEach((type) => {
|
|
96
|
+
var { template } = Encoding[type];
|
|
97
|
+
var decodeFn = this.getPlaceholder();
|
|
98
|
+
var getterFn = this.encoding[type];
|
|
175
99
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
100
|
+
append(tree, template.single({ name: decodeFn }));
|
|
101
|
+
|
|
102
|
+
append(
|
|
103
|
+
tree,
|
|
104
|
+
Template(`
|
|
105
|
+
|
|
106
|
+
function ${getterFn}(x, y, z, a = ${decodeFn}, b = ${cacheName}){
|
|
107
|
+
if ( z ) {
|
|
108
|
+
return y[${cacheName}[z]] = ${getterFn}(x, y);
|
|
109
|
+
} else if ( y ) {
|
|
110
|
+
[b, y] = [a(b), x || z]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return y ? x[b[y]] : ${cacheName}[x] || (z=(b[x], a), ${cacheName}[x] = z(${this.arrayName}[x]))
|
|
183
114
|
}
|
|
184
|
-
|
|
185
|
-
|
|
115
|
+
|
|
116
|
+
`).single()
|
|
117
|
+
);
|
|
118
|
+
});
|
|
186
119
|
|
|
187
|
-
|
|
188
|
-
);
|
|
120
|
+
var flowIntegrity = this.getPlaceholder();
|
|
189
121
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
122
|
+
prepend(
|
|
123
|
+
tree,
|
|
124
|
+
VariableDeclaration([
|
|
125
|
+
VariableDeclarator(cacheName, ArrayExpression([])),
|
|
126
|
+
VariableDeclarator(flowIntegrity, Literal(0)),
|
|
127
|
+
VariableDeclarator(
|
|
128
|
+
this.arrayName,
|
|
129
|
+
CallExpression(
|
|
130
|
+
FunctionExpression(
|
|
131
|
+
[],
|
|
132
|
+
[
|
|
133
|
+
VariableDeclaration(
|
|
134
|
+
VariableDeclarator("a", this.arrayExpression)
|
|
135
|
+
),
|
|
136
|
+
Template(
|
|
137
|
+
`return (${flowIntegrity} ? a.pop() : ${flowIntegrity}++, a)`
|
|
138
|
+
).single(),
|
|
139
|
+
]
|
|
140
|
+
),
|
|
141
|
+
[]
|
|
142
|
+
)
|
|
143
|
+
),
|
|
144
|
+
])
|
|
145
|
+
);
|
|
146
|
+
}
|
|
197
147
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
148
|
+
match(object, parents) {
|
|
149
|
+
return (
|
|
150
|
+
object.type == "Literal" &&
|
|
151
|
+
typeof object.value === "string" &&
|
|
152
|
+
object.value.length >= 3 &&
|
|
153
|
+
!isModuleSource(object, parents) &&
|
|
154
|
+
!isDirective(object, parents) //&&
|
|
155
|
+
/*!parents.find((x) => x.$dispatcherSkip)*/
|
|
156
|
+
);
|
|
157
|
+
}
|
|
206
158
|
|
|
159
|
+
transform(object: Node, parents: Node[]) {
|
|
207
160
|
return () => {
|
|
208
|
-
//
|
|
209
|
-
if (
|
|
161
|
+
// Empty strings are discarded
|
|
162
|
+
if (!object.value || this.ignore.has(object.value)) {
|
|
210
163
|
return;
|
|
211
164
|
}
|
|
212
165
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
166
|
+
var types = Object.keys(this.encoding);
|
|
167
|
+
|
|
168
|
+
var type = choice(types);
|
|
169
|
+
if (!type || (!this.hasAllEncodings && Math.random() > 0.9)) {
|
|
170
|
+
var allowed = Object.keys(Encoding).filter(
|
|
171
|
+
(type) => !this.encoding[type]
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (!allowed.length) {
|
|
175
|
+
this.hasAllEncodings = true;
|
|
176
|
+
} else {
|
|
177
|
+
var random = choice(allowed);
|
|
178
|
+
type = random;
|
|
179
|
+
|
|
180
|
+
this.encoding[random] = this.getPlaceholder();
|
|
181
|
+
}
|
|
216
182
|
}
|
|
217
183
|
|
|
184
|
+
var fnName = this.encoding[type];
|
|
185
|
+
var encoder = Encoding[type];
|
|
186
|
+
|
|
218
187
|
// The decode function must return correct result
|
|
219
|
-
|
|
188
|
+
var encoded = encoder.encode(object.value);
|
|
189
|
+
if (encoder.decode(encoded) != object.value) {
|
|
190
|
+
this.ignore.add(object.value);
|
|
220
191
|
this.warn(object.value.slice(0, 100));
|
|
221
192
|
return;
|
|
222
193
|
}
|
|
@@ -225,33 +196,59 @@ export default class StringConcealing extends Transform {
|
|
|
225
196
|
if (object.value && object.value.length > 0) {
|
|
226
197
|
var index = -1;
|
|
227
198
|
if (!this.set.has(object.value)) {
|
|
228
|
-
this.arrayExpression.elements.push(
|
|
229
|
-
Literal(encode_ascii85(object.value))
|
|
230
|
-
);
|
|
199
|
+
this.arrayExpression.elements.push(Literal(encoded));
|
|
231
200
|
index = this.arrayExpression.elements.length - 1;
|
|
232
|
-
this.index[object.value] = index;
|
|
201
|
+
this.index[object.value] = [index, fnName];
|
|
233
202
|
|
|
234
203
|
this.set.add(object.value);
|
|
235
204
|
} else {
|
|
236
|
-
index = this.index[object.value];
|
|
205
|
+
[index, fnName] = this.index[object.value];
|
|
237
206
|
ok(typeof index === "number");
|
|
238
207
|
}
|
|
239
208
|
|
|
240
209
|
ok(index != -1, "index == -1");
|
|
241
|
-
this.replace(
|
|
242
|
-
object,
|
|
243
|
-
CallExpression(Identifier(this.getterName), [Literal(index)])
|
|
244
|
-
);
|
|
245
210
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
211
|
+
var callExpr = CallExpression(Identifier(fnName), [Literal(index)]);
|
|
212
|
+
|
|
213
|
+
// use `.apply` to fool automated de-obfuscators
|
|
214
|
+
if (Math.random() > 0.5) {
|
|
215
|
+
callExpr = CallExpression(
|
|
216
|
+
MemberExpression(Identifier(fnName), Identifier("apply"), false),
|
|
217
|
+
[ThisExpression(), ArrayExpression([Literal(index)])]
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// use `.call`
|
|
222
|
+
else if (Math.random() > 0.5) {
|
|
223
|
+
callExpr = CallExpression(
|
|
224
|
+
MemberExpression(Identifier(fnName), Identifier("call"), false),
|
|
225
|
+
[ThisExpression(), Literal(index)]
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
var constantReference =
|
|
230
|
+
parents.length && Math.random() > 0.5 / this.variablesMade;
|
|
231
|
+
|
|
232
|
+
if (constantReference) {
|
|
233
|
+
// Define the string earlier, reference the name here
|
|
234
|
+
|
|
235
|
+
var name = this.getPlaceholder();
|
|
236
|
+
|
|
237
|
+
var place = choice(parents.filter((node) => isBlock(node)));
|
|
238
|
+
if (!place) {
|
|
239
|
+
this.error(Error("No lexical block to insert code"));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
place.body.unshift(
|
|
243
|
+
VariableDeclaration(VariableDeclarator(name, callExpr))
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
this.replaceIdentifierOrLiteral(object, Identifier(name), parents);
|
|
247
|
+
|
|
248
|
+
this.variablesMade++;
|
|
249
|
+
} else {
|
|
250
|
+
// Direct call to the getter function
|
|
251
|
+
this.replaceIdentifierOrLiteral(object, callExpr, parents);
|
|
255
252
|
}
|
|
256
253
|
}
|
|
257
254
|
};
|
|
@@ -6,6 +6,7 @@ import { ObfuscateOrder } from "../../order";
|
|
|
6
6
|
import { isModuleSource } from "./stringConcealing";
|
|
7
7
|
import { isDirective } from "../../util/compare";
|
|
8
8
|
import { ok } from "assert";
|
|
9
|
+
import { ComputeProbabilityMap } from "../../probability";
|
|
9
10
|
|
|
10
11
|
export default class StringSplitting extends Transform {
|
|
11
12
|
joinPrototype: string;
|
|
@@ -59,13 +60,6 @@ export default class StringSplitting extends Transform {
|
|
|
59
60
|
|
|
60
61
|
transform(object: Node, parents: Node[]) {
|
|
61
62
|
return () => {
|
|
62
|
-
var propIndex = parents.findIndex(
|
|
63
|
-
(x) => x.type == "Property" || x.type == "MethodDefinition"
|
|
64
|
-
);
|
|
65
|
-
if (propIndex !== -1 && parents[propIndex].key == object) {
|
|
66
|
-
parents[propIndex].computed = true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
63
|
var size = Math.round(
|
|
70
64
|
Math.max(6, object.value.length / getRandomInteger(3, 8))
|
|
71
65
|
);
|
|
@@ -78,6 +72,16 @@ export default class StringSplitting extends Transform {
|
|
|
78
72
|
return;
|
|
79
73
|
}
|
|
80
74
|
|
|
75
|
+
if (
|
|
76
|
+
!ComputeProbabilityMap(
|
|
77
|
+
this.options.stringSplitting,
|
|
78
|
+
(x) => x,
|
|
79
|
+
object.value
|
|
80
|
+
)
|
|
81
|
+
) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
81
85
|
var binaryExpression;
|
|
82
86
|
var parent;
|
|
83
87
|
var last = chunks.pop();
|
|
@@ -101,7 +105,7 @@ export default class StringSplitting extends Transform {
|
|
|
101
105
|
|
|
102
106
|
parent.right = Literal(last);
|
|
103
107
|
|
|
104
|
-
this.
|
|
108
|
+
this.replaceIdentifierOrLiteral(object, parent, parents);
|
|
105
109
|
};
|
|
106
110
|
}
|
|
107
111
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import traverse, {
|
|
1
|
+
import traverse, { ExitCallback } from "../traverse";
|
|
2
2
|
import { AddComment, Node } from "../util/gen";
|
|
3
3
|
import {
|
|
4
4
|
alphabeticalGenerator,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
getRandomInteger,
|
|
7
7
|
} from "../util/random";
|
|
8
8
|
import { ok } from "assert";
|
|
9
|
-
import { isValidIdentifier } from "../util/compare";
|
|
10
9
|
import Obfuscator from "../obfuscator";
|
|
11
10
|
import { ObfuscateOptions } from "../options";
|
|
12
11
|
import { ComputeProbabilityMap } from "../probability";
|
|
@@ -353,6 +352,20 @@ export default class Transform {
|
|
|
353
352
|
this.objectAssign(node1, node2);
|
|
354
353
|
}
|
|
355
354
|
|
|
355
|
+
replaceIdentifierOrLiteral(node1: Node, node2: Node, parents: Node[]) {
|
|
356
|
+
// Fix 2. Make parent property key computed
|
|
357
|
+
if (
|
|
358
|
+
parents[0] &&
|
|
359
|
+
(parents[0].type == "Property" ||
|
|
360
|
+
parents[0].type == "MethodDefinition") &&
|
|
361
|
+
parents[0].key == node1
|
|
362
|
+
) {
|
|
363
|
+
parents[0].computed = true;
|
|
364
|
+
parents[0].shorthand = false;
|
|
365
|
+
}
|
|
366
|
+
this.replace(node1, node2);
|
|
367
|
+
}
|
|
368
|
+
|
|
356
369
|
/**
|
|
357
370
|
* Smartly merges two Nodes.
|
|
358
371
|
* - Null checking
|
package/src/traverse.ts
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import { Node } from "./util/gen";
|
|
2
2
|
import { validateChain } from "./util/identifiers";
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Returns all the scopes given parents array.
|
|
6
|
-
* - `[object, ...parents]` is recommended.
|
|
7
|
-
*
|
|
8
|
-
* @param parents
|
|
9
|
-
*/
|
|
10
|
-
export function getBlocks(parents: any[]): any[] {
|
|
11
|
-
return parents.filter((x) => isBlock(x));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
4
|
/**
|
|
15
5
|
* A block refers to any object that has a **`.body`** property where code is nested.
|
|
16
6
|
*
|
|
@@ -23,7 +13,7 @@ export function getBlock(object: any, parents: any[]) {
|
|
|
23
13
|
if (!Array.isArray(parents)) {
|
|
24
14
|
throw new Error("parents must be an array");
|
|
25
15
|
}
|
|
26
|
-
return
|
|
16
|
+
return [object, ...parents].find((node) => isBlock(node));
|
|
27
17
|
}
|
|
28
18
|
|
|
29
19
|
/**
|
|
@@ -40,26 +30,6 @@ export function isBlock(object: any) {
|
|
|
40
30
|
);
|
|
41
31
|
}
|
|
42
32
|
|
|
43
|
-
/**
|
|
44
|
-
* Returns a numerical representation of the depth.
|
|
45
|
-
* - Depth is how many blocks nested.
|
|
46
|
-
* - Program = 1 depth
|
|
47
|
-
* - First Fn = 2 depth
|
|
48
|
-
* - Nested Fn = 3 depth
|
|
49
|
-
* - Second Fn = 2 depth
|
|
50
|
-
* - etc...
|
|
51
|
-
* @param object
|
|
52
|
-
* @param parents
|
|
53
|
-
*/
|
|
54
|
-
export function getDepth(object: any, parents: any[]) {
|
|
55
|
-
if (!Array.isArray(parents)) {
|
|
56
|
-
throw new Error("parents should be an array");
|
|
57
|
-
}
|
|
58
|
-
var scopes = getBlocks([object, ...parents].filter((x) => x));
|
|
59
|
-
|
|
60
|
-
return scopes.length;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
33
|
export type EnterCallback = (
|
|
64
34
|
object: Node,
|
|
65
35
|
parents: Node[]
|
package/src/util/gen.ts
CHANGED
|
@@ -134,7 +134,9 @@ export function ThisExpression() {
|
|
|
134
134
|
return { type: "ThisExpression" };
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
export function SwitchCase(test: any, consequent:
|
|
137
|
+
export function SwitchCase(test: any, consequent: Node[]) {
|
|
138
|
+
ok(test === null || test);
|
|
139
|
+
ok(Array.isArray(consequent));
|
|
138
140
|
return {
|
|
139
141
|
type: "SwitchCase",
|
|
140
142
|
test,
|
|
@@ -142,7 +144,7 @@ export function SwitchCase(test: any, consequent: any[]) {
|
|
|
142
144
|
};
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
export function SwitchDefaultCase(consequent:
|
|
147
|
+
export function SwitchDefaultCase(consequent: Node[]) {
|
|
146
148
|
return SwitchCase(null, consequent);
|
|
147
149
|
}
|
|
148
150
|
|
|
@@ -496,7 +498,7 @@ export function AssignmentPattern(left: Node, right: Node) {
|
|
|
496
498
|
ok(left);
|
|
497
499
|
ok(right);
|
|
498
500
|
return {
|
|
499
|
-
type: "
|
|
501
|
+
type: "AssignmentPattern",
|
|
500
502
|
left: left,
|
|
501
503
|
right: right,
|
|
502
504
|
};
|
package/src/util/identifiers.ts
CHANGED
|
@@ -30,17 +30,6 @@ export function validateChain(object: Node, parents: Node[]) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export function isWithinClass(object: Node, parents: Node[]) {
|
|
34
|
-
return (
|
|
35
|
-
isWithin(object, parents, "ClassDeclaration") ||
|
|
36
|
-
isWithin(object, parents, "ClassExpression")
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function isWithin(object: Node, parents: Node[], type: string): boolean {
|
|
41
|
-
return [object, ...parents].some((x) => x.type == type);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
/**
|
|
45
34
|
* Returns detailed information about the given Identifier node.
|
|
46
35
|
* @param object
|
|
@@ -117,15 +106,22 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
|
|
|
117
106
|
|
|
118
107
|
var isFunctionCall = parent.callee == object; // NewExpression and CallExpression
|
|
119
108
|
|
|
109
|
+
var assignmentIndex = parents.findIndex(
|
|
110
|
+
(p) => p.type === "AssignmentExpression"
|
|
111
|
+
);
|
|
112
|
+
|
|
120
113
|
var isAssignmentLeft =
|
|
121
|
-
|
|
114
|
+
assignmentIndex !== -1 &&
|
|
115
|
+
parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object);
|
|
122
116
|
var isAssignmentValue =
|
|
123
|
-
|
|
117
|
+
assignmentIndex !== -1 &&
|
|
118
|
+
parents[assignmentIndex].right === (parents[assignmentIndex - 1] || object);
|
|
124
119
|
|
|
125
120
|
var isUpdateExpression = parent.type == "UpdateExpression";
|
|
126
121
|
|
|
127
122
|
var isClassDeclaration =
|
|
128
|
-
parent.type == "ClassDeclaration"
|
|
123
|
+
(parent.type == "ClassDeclaration" || parent.type == "ClassExpression") &&
|
|
124
|
+
parent.id == object;
|
|
129
125
|
var isMethodDefinition =
|
|
130
126
|
parent.type == "MethodDefinition" &&
|
|
131
127
|
parent.key == object &&
|
|
@@ -352,7 +348,7 @@ export function getDefiningIdentifier(object: Node, parents: Node[]): Location {
|
|
|
352
348
|
}
|
|
353
349
|
}
|
|
354
350
|
|
|
355
|
-
export function isFunctionParameter(o: Node, p: Node[]) {
|
|
351
|
+
export function isFunctionParameter(o: Node, p: Node[], c?: Node) {
|
|
356
352
|
ok(o);
|
|
357
353
|
ok(p);
|
|
358
354
|
validateChain(o, p);
|
|
@@ -365,7 +361,7 @@ export function isFunctionParameter(o: Node, p: Node[]) {
|
|
|
365
361
|
return false;
|
|
366
362
|
}
|
|
367
363
|
|
|
368
|
-
|
|
364
|
+
c = c || getVarContext(o, p);
|
|
369
365
|
if (c === object) {
|
|
370
366
|
var pIndex = p.indexOf(object.params);
|
|
371
367
|
if (pIndex == -1) {
|
|
@@ -376,8 +372,7 @@ export function isFunctionParameter(o: Node, p: Node[]) {
|
|
|
376
372
|
var paramIndex = object.params.indexOf(param);
|
|
377
373
|
ok(paramIndex !== -1);
|
|
378
374
|
|
|
379
|
-
var sliced = p.slice(
|
|
380
|
-
ok(!sliced.includes(o));
|
|
375
|
+
var sliced = p.slice(0, pIndex);
|
|
381
376
|
|
|
382
377
|
var isReferenced = true;
|
|
383
378
|
var i = 0;
|
|
@@ -391,7 +386,12 @@ export function isFunctionParameter(o: Node, p: Node[]) {
|
|
|
391
386
|
break;
|
|
392
387
|
}
|
|
393
388
|
|
|
394
|
-
if (
|
|
389
|
+
if (
|
|
390
|
+
node.type == "Property" &&
|
|
391
|
+
node.key === down &&
|
|
392
|
+
sliced[i + 2] &&
|
|
393
|
+
sliced[i + 2].type == "ObjectPattern"
|
|
394
|
+
) {
|
|
395
395
|
isReferenced = false;
|
|
396
396
|
break;
|
|
397
397
|
}
|
|
@@ -419,7 +419,7 @@ export function getFunctionParameters(
|
|
|
419
419
|
|
|
420
420
|
walk(object.params, [object, ...parents], (o, p) => {
|
|
421
421
|
if (o.type == "Identifier") {
|
|
422
|
-
if (isFunctionParameter(o, p)) {
|
|
422
|
+
if (isFunctionParameter(o, p, object)) {
|
|
423
423
|
locations.push([o, p]);
|
|
424
424
|
}
|
|
425
425
|
}
|