js-confuser 1.6.0 → 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/CHANGELOG.md +23 -0
- package/README.md +215 -170
- package/dist/constants.js +6 -2
- package/dist/obfuscator.js +0 -6
- package/dist/options.js +4 -4
- package/dist/presets.js +6 -7
- package/dist/templates/crash.js +2 -2
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/dispatcher.js +4 -1
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +89 -58
- package/dist/transforms/flatten.js +224 -147
- package/dist/transforms/identifier/movedDeclarations.js +38 -85
- package/dist/transforms/identifier/renameVariables.js +94 -41
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +2 -2
- package/dist/transforms/rgf.js +139 -246
- package/dist/transforms/stack.js +42 -1
- package/dist/transforms/transform.js +1 -1
- package/dist/util/gen.js +2 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +24 -3
- 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 +1 -1
- package/src/constants.ts +3 -0
- package/src/obfuscator.ts +0 -4
- package/src/options.ts +9 -86
- package/src/presets.ts +6 -7
- package/src/templates/crash.ts +10 -10
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/dispatcher.ts +5 -1
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +130 -129
- package/src/transforms/flatten.ts +357 -290
- package/src/transforms/identifier/movedDeclarations.ts +50 -96
- package/src/transforms/identifier/renameVariables.ts +120 -56
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +11 -2
- package/src/transforms/rgf.ts +214 -404
- package/src/transforms/stack.ts +62 -0
- package/src/transforms/transform.ts +6 -2
- package/src/util/gen.ts +7 -2
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +26 -2
- package/test/code/ES6.src.js +24 -0
- package/test/transforms/flatten.test.ts +352 -88
- package/test/transforms/identifier/movedDeclarations.test.ts +37 -9
- package/test/transforms/identifier/renameVariables.test.ts +37 -0
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +19 -0
- package/test/transforms/rgf.test.ts +262 -353
- package/test/transforms/stack.test.ts +52 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
|
@@ -40,6 +40,7 @@ class RenameVariables extends _transform.default {
|
|
|
40
40
|
// Names already used
|
|
41
41
|
// Map of Context->Object of changes
|
|
42
42
|
// Ref to VariableAnalysis data
|
|
43
|
+
// Option to re-use previously generated names
|
|
43
44
|
constructor(o) {
|
|
44
45
|
super(o, _order.ObfuscateOrder.RenameVariables);
|
|
45
46
|
|
|
@@ -49,6 +50,8 @@ class RenameVariables extends _transform.default {
|
|
|
49
50
|
|
|
50
51
|
_defineProperty(this, "variableAnalysis", void 0);
|
|
51
52
|
|
|
53
|
+
_defineProperty(this, "reusePreviousNames", true);
|
|
54
|
+
|
|
52
55
|
this.changed = new Map(); // 1.
|
|
53
56
|
|
|
54
57
|
this.variableAnalysis = new _variableAnalysis.default(o);
|
|
@@ -57,10 +60,10 @@ class RenameVariables extends _transform.default {
|
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
match(object, parents) {
|
|
60
|
-
return (0, _insert.isContext)(object);
|
|
63
|
+
return (0, _insert.isContext)(object) || object.type === "Identifier";
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
transformContext(object, parents) {
|
|
64
67
|
// 2. Notice this is on 'onEnter' (top-down)
|
|
65
68
|
var isGlobal = object.type == "Program";
|
|
66
69
|
var type = isGlobal ? "root" : (0, _insert.isVarContext)(object) ? "var" : (0, _insert.isLexContext)(object) ? "lex" : undefined;
|
|
@@ -77,7 +80,7 @@ class RenameVariables extends _transform.default {
|
|
|
77
80
|
|
|
78
81
|
var possible = new Set(); // 3. Try to re-use names when possible
|
|
79
82
|
|
|
80
|
-
if (this.generated.length && !isGlobal) {
|
|
83
|
+
if (this.reusePreviousNames && this.generated.length && !isGlobal) {
|
|
81
84
|
var allReferences = new Set();
|
|
82
85
|
var nope = new Set(defined);
|
|
83
86
|
(0, _traverse.walk)(object, [], (o, p) => {
|
|
@@ -115,8 +118,8 @@ class RenameVariables extends _transform.default {
|
|
|
115
118
|
|
|
116
119
|
|
|
117
120
|
for (var name of defined) {
|
|
118
|
-
if (!name.startsWith(
|
|
119
|
-
isGlobal && !name.startsWith(
|
|
121
|
+
if (!name.startsWith(_constants.noRenameVariablePrefix) && ( // Variables prefixed with '__NO_JS_CONFUSER_RENAME__' are never renamed
|
|
122
|
+
isGlobal && !name.startsWith(_constants.placeholderVariablePrefix) // Variables prefixed with '__p_' are created by the obfuscator, always renamed
|
|
120
123
|
? (0, _probability.ComputeProbabilityMap)(this.options.renameGlobals, x => x, name) : true) && (0, _probability.ComputeProbabilityMap)( // Check the user's option for renaming variables
|
|
121
124
|
this.options.renameVariables, x => x, name, isGlobal)) {
|
|
122
125
|
// Create a new name from (1) or (2) methods
|
|
@@ -142,58 +145,108 @@ class RenameVariables extends _transform.default {
|
|
|
142
145
|
// This variable name was deemed not to be renamed.
|
|
143
146
|
newNames[name] = name;
|
|
144
147
|
}
|
|
148
|
+
} // console.log(object.type, newNames);
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
this.changed.set(object, newNames);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
transformIdentifier(object, parents) {
|
|
155
|
+
const identifierName = object.name;
|
|
156
|
+
|
|
157
|
+
if (_constants.reservedIdentifiers.has(identifierName) || this.options.globalVariables.has(identifierName)) {
|
|
158
|
+
return;
|
|
145
159
|
}
|
|
146
160
|
|
|
147
|
-
|
|
161
|
+
if (object.$renamed) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
148
164
|
|
|
149
|
-
(0,
|
|
150
|
-
if (o.type == "Identifier") {
|
|
151
|
-
if (_constants.reservedIdentifiers.has(o.name) || this.options.globalVariables.has(o.name)) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
165
|
+
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
154
166
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
if (info.spec.isExported) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
158
170
|
|
|
159
|
-
|
|
171
|
+
if (!info.spec.isReferenced) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
160
174
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
175
|
+
var contexts = [object, ...parents].filter(x => (0, _insert.isContext)(x));
|
|
176
|
+
var newName = null; // Function default parameter check!
|
|
164
177
|
|
|
165
|
-
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
178
|
+
var functionIndices = [];
|
|
168
179
|
|
|
169
|
-
|
|
170
|
-
|
|
180
|
+
for (var i in parents) {
|
|
181
|
+
if ((0, _insert.isFunction)(parents[i])) {
|
|
182
|
+
functionIndices.push(i);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
171
185
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
for (var functionIndex of functionIndices) {
|
|
187
|
+
if (parents[functionIndex].id === object) {
|
|
188
|
+
// This context is not referenced, so remove it
|
|
189
|
+
contexts = contexts.filter(context => context != parents[functionIndex]);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (parents[functionIndex].params === parents[functionIndex - 1]) {
|
|
194
|
+
var isReferencedHere = true;
|
|
195
|
+
var slicedParents = parents.slice(0, functionIndex);
|
|
196
|
+
var forIndex = 0;
|
|
197
|
+
|
|
198
|
+
for (var parent of slicedParents) {
|
|
199
|
+
var childNode = slicedParents[forIndex - 1] || object;
|
|
200
|
+
|
|
201
|
+
if (parent.type === "AssignmentPattern" && parent.right === childNode) {
|
|
202
|
+
isReferencedHere = false;
|
|
203
|
+
break;
|
|
178
204
|
}
|
|
205
|
+
|
|
206
|
+
forIndex++;
|
|
179
207
|
}
|
|
180
208
|
|
|
181
|
-
if (
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
209
|
+
if (!isReferencedHere) {
|
|
210
|
+
// This context is not referenced, so remove it
|
|
211
|
+
contexts = contexts.filter(context => context != parents[functionIndex]);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
185
215
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
216
|
+
for (var check of contexts) {
|
|
217
|
+
if (this.variableAnalysis.defined.has(check) && this.variableAnalysis.defined.get(check).has(identifierName)) {
|
|
218
|
+
if (this.changed.has(check) && this.changed.get(check)[identifierName]) {
|
|
219
|
+
newName = this.changed.get(check)[identifierName];
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
190
224
|
|
|
225
|
+
if (newName && typeof newName === "string") {
|
|
226
|
+
// Strange behavior where the `local` and `imported` objects are the same
|
|
227
|
+
if (info.isImportSpecifier) {
|
|
228
|
+
var importSpecifierIndex = parents.findIndex(x => x.type === "ImportSpecifier");
|
|
191
229
|
|
|
192
|
-
|
|
193
|
-
|
|
230
|
+
if (importSpecifierIndex != -1 && parents[importSpecifierIndex].imported === (parents[importSpecifierIndex - 1] || object) && parents[importSpecifierIndex].imported && parents[importSpecifierIndex].imported.type === "Identifier") {
|
|
231
|
+
parents[importSpecifierIndex].imported = (0, _insert.clone)(parents[importSpecifierIndex - 1] || object);
|
|
194
232
|
}
|
|
195
|
-
}
|
|
196
|
-
|
|
233
|
+
} // console.log(o.name, "->", newName);
|
|
234
|
+
// 5. Update Identifier node's 'name' property
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
object.name = newName;
|
|
238
|
+
object.$renamed = true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
transform(object, parents) {
|
|
243
|
+
var matchType = object.type === "Identifier" ? "Identifier" : "Context";
|
|
244
|
+
|
|
245
|
+
if (matchType === "Identifier") {
|
|
246
|
+
this.transformIdentifier(object, parents);
|
|
247
|
+
} else {
|
|
248
|
+
this.transformContext(object, parents);
|
|
249
|
+
}
|
|
197
250
|
}
|
|
198
251
|
|
|
199
252
|
}
|
|
@@ -194,10 +194,6 @@ class Lock extends _transform.default {
|
|
|
194
194
|
choices.push("domainLock");
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
if (this.options.lock.nativeFunctions) {
|
|
198
|
-
choices.push("nativeFunction");
|
|
199
|
-
}
|
|
200
|
-
|
|
201
197
|
if (this.options.lock.context && this.options.lock.context.length) {
|
|
202
198
|
choices.push("context");
|
|
203
199
|
}
|
|
@@ -248,39 +244,6 @@ class Lock extends _transform.default {
|
|
|
248
244
|
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
249
245
|
break;
|
|
250
246
|
|
|
251
|
-
case "nativeFunction":
|
|
252
|
-
var set = this.options.lock.nativeFunctions;
|
|
253
|
-
|
|
254
|
-
if (set === true) {
|
|
255
|
-
if (this.options.target == "node") {
|
|
256
|
-
set = new Set(["Function", "String"]);
|
|
257
|
-
} else {
|
|
258
|
-
set = new Set(["Function", "String", "fetch"]);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (Array.isArray(set)) {
|
|
263
|
-
set = new Set(set);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (!set) {
|
|
267
|
-
set = new Set();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
var fn = (0, _random.choice)(Array.from(set));
|
|
271
|
-
|
|
272
|
-
if (fn) {
|
|
273
|
-
test = (0, _template.default)("(".concat(fn, "+\"\").indexOf(\"[native code]\") == -1")).single().expression;
|
|
274
|
-
|
|
275
|
-
if (Math.random() > 0.5) {
|
|
276
|
-
test = (0, _template.default)("".concat(fn, ".toString().split(\"{ [native code] }\").length <= 1")).single().expression;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
break;
|
|
283
|
-
|
|
284
247
|
case "startDate":
|
|
285
248
|
test = (0, _gen.BinaryExpression)("<", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.startDate)));
|
|
286
249
|
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
@@ -214,11 +214,11 @@ class Minify extends _transform.default {
|
|
|
214
214
|
if (canTransform) {
|
|
215
215
|
if (!this.arrowFunctionName) {
|
|
216
216
|
this.arrowFunctionName = this.getPlaceholder();
|
|
217
|
-
(0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn){\n
|
|
217
|
+
(0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn, functionLength){\n var functionObject = function(){ return arrowFn(...arguments) };\n\n Object[\"defineProperty\"](functionObject, \"length\", {\n \"value\": functionLength,\n \"configurable\": true\n });\n\n return functionObject;\n }\n ")).single());
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
const wrap = object => {
|
|
221
|
-
return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object)]);
|
|
221
|
+
return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object), (0, _gen.Literal)((0, _insert.computeFunctionLength)(object.params))]);
|
|
222
222
|
};
|
|
223
223
|
|
|
224
224
|
if (object.type == "FunctionExpression") {
|