js-confuser 1.5.5 → 1.5.7
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 +34 -2
- package/README.md +2 -2
- package/dist/transforms/flatten.js +1 -1
- package/dist/transforms/identifier/variableAnalysis.js +4 -2
- package/dist/transforms/lock/integrity.js +6 -2
- package/dist/transforms/lock/lock.js +40 -32
- package/dist/transforms/minify.js +2 -2
- package/dist/transforms/preparation/preparation.js +0 -7
- package/dist/transforms/rgf.js +80 -10
- package/dist/transforms/string/stringSplitting.js +1 -22
- package/package.json +2 -2
- package/src/transforms/flatten.ts +2 -2
- package/src/transforms/identifier/variableAnalysis.ts +4 -4
- package/src/transforms/lock/integrity.ts +13 -1
- package/src/transforms/lock/lock.ts +81 -44
- package/src/transforms/minify.ts +5 -4
- package/src/transforms/preparation/preparation.ts +2 -21
- package/src/transforms/rgf.ts +164 -29
- package/src/transforms/string/stringSplitting.ts +1 -25
- package/test/transforms/lock/countermeasures.test.ts +18 -0
- package/test/transforms/minify.test.ts +50 -5
- package/test/transforms/rgf.test.ts +134 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
|
+
# `1.5.7`
|
|
2
|
+
Countermeasures function fixes
|
|
3
|
+
|
|
4
|
+
This update focuses on fixing Countermeasures bugs
|
|
5
|
+
|
|
6
|
+
The `countermeasures` is custom callback function to invoke when a lock is triggered.
|
|
7
|
+
|
|
8
|
+
- Fixed [#66](https://github.com/MichaelXF/js-confuser/issues/66)
|
|
9
|
+
- - RGF to properly handle the countermeasures function
|
|
10
|
+
|
|
11
|
+
- Added additional code to prevent an infinite loop from occurring
|
|
12
|
+
|
|
13
|
+
- Slight improvements to RGF
|
|
14
|
+
|
|
15
|
+
# `1.5.6`
|
|
16
|
+
Website changed and RGF fixes
|
|
17
|
+
|
|
18
|
+
The website is back at a different domain now: [https://master--hungry-shannon-c1ce6b.netlify.app/](https://master--hungry-shannon-c1ce6b.netlify.app/)
|
|
19
|
+
|
|
20
|
+
This update focuses on fixing RGF bugs
|
|
21
|
+
|
|
22
|
+
- Fixed [#64](https://github.com/MichaelXF/js-confuser/issues/64)
|
|
23
|
+
- - RGF to properly handle Arrow functions and function expressions
|
|
24
|
+
|
|
25
|
+
- RGF will no longer change getter/setter methods
|
|
26
|
+
|
|
27
|
+
- RGF will no longer change class methods
|
|
28
|
+
|
|
29
|
+
- RGF now works when using `mangled` variable names
|
|
30
|
+
|
|
31
|
+
- Minify will remove unreachable code following a Throw statement
|
|
32
|
+
|
|
1
33
|
# `1.5.5`
|
|
2
34
|
Updates
|
|
3
35
|
|
|
4
36
|
- Fixed [#53](https://github.com/MichaelXF/js-confuser/issues/53)
|
|
5
|
-
- - Shuffle to not use common
|
|
37
|
+
- - Shuffle to not use common variable names like `x`
|
|
6
38
|
|
|
7
39
|
- Fixed [#60](https://github.com/MichaelXF/js-confuser/issues/60)
|
|
8
40
|
- - Rename Variables to properly handle function parameters
|
|
@@ -447,7 +479,7 @@ Available now on NPM: https://www.npmjs.com/package/js-confuser
|
|
|
447
479
|
# `1.1.7`
|
|
448
480
|
Website is Live
|
|
449
481
|
|
|
450
|
-
- [
|
|
482
|
+
- [https://master--hungry-shannon-c1ce6b.netlify.app/](https://master--hungry-shannon-c1ce6b.netlify.app/) is live!
|
|
451
483
|
- Check out the [js-confuser-website](https://github.com/MichaelXF/js-confuser-website) repo for more info
|
|
452
484
|
|
|
453
485
|
- **⚠️ Breaking change**: `Rename Globals` is now enabled by default
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# JS Confuser
|
|
2
2
|
|
|
3
|
-
JS-Confuser is a JavaScript obfuscation tool to make your programs _impossible_ to read. [Try the web version](https://
|
|
3
|
+
JS-Confuser is a JavaScript obfuscation tool to make your programs _impossible_ to read. [Try the web version](https://master--hungry-shannon-c1ce6b.netlify.app/).
|
|
4
4
|
|
|
5
|
-
[](https://npmjs.com/package/js-confuser) [](https://github.com/MichaelXF/js-confuser) [](https://
|
|
5
|
+
[](https://npmjs.com/package/js-confuser) [](https://github.com/MichaelXF/js-confuser) [](https://master--hungry-shannon-c1ce6b.netlify.app/)
|
|
6
6
|
|
|
7
7
|
## Key features
|
|
8
8
|
|
|
@@ -224,7 +224,7 @@ class Flatten extends _transform.default {
|
|
|
224
224
|
|
|
225
225
|
var call = (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(resultName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)("_", (0, _gen.AssignmentExpression)("=", identifier, (0, _gen.ArrayExpression)([(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), (0, _gen.ArrayExpression)([...newParamNodes]), (0, _gen.Identifier)(resultName)])))]); // result.pop()
|
|
226
226
|
|
|
227
|
-
var pop = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), (0, _gen.
|
|
227
|
+
var pop = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), (0, _gen.Literal)("pop"), true), []); // var result = newFn.call([...refs], ...arguments)
|
|
228
228
|
// modified1 = result.pop();
|
|
229
229
|
// modified2 = result.pop();
|
|
230
230
|
// ...modifiedN = result.pop();...
|
|
@@ -103,8 +103,10 @@ class VariableAnalysis extends _transform.default {
|
|
|
103
103
|
var definingContexts = info.spec.isDefined ? (0, _insert.getAllDefiningContexts)(o, p) : (0, _insert.getReferencingContexts)(o, p, info);
|
|
104
104
|
(0, _assert.ok)(definingContexts.length);
|
|
105
105
|
definingContexts.forEach(definingContext => {
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
// ok(
|
|
107
|
+
// isContext(definingContext),
|
|
108
|
+
// `${definingContext.type} is not a context`
|
|
109
|
+
// );
|
|
108
110
|
if (isDefined) {
|
|
109
111
|
// Add to defined Map
|
|
110
112
|
if (!this.defined.has(definingContext)) {
|
|
@@ -148,7 +148,7 @@ class Integrity extends _transform.default {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
return () => {
|
|
151
|
-
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode();
|
|
151
|
+
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(object, parents);
|
|
152
152
|
|
|
153
153
|
object.$eval = () => {
|
|
154
154
|
var functionName = this.generateIdentifier();
|
|
@@ -178,7 +178,11 @@ class Integrity extends _transform.default {
|
|
|
178
178
|
ifStatement.alternate = (0, _gen.BlockStatement)(object.__hiddenCountermeasures);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]);
|
|
181
|
+
object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]); // Make sure the countermeasures activation variable is present
|
|
182
|
+
|
|
183
|
+
if (this.lock.counterMeasuresActivated) {
|
|
184
|
+
object.body.body.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.lock.counterMeasuresActivated)));
|
|
185
|
+
}
|
|
182
186
|
|
|
183
187
|
if (object.type == "ArrowFunctionExpression") {
|
|
184
188
|
object.type = "FunctionExpression";
|
|
@@ -43,6 +43,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
43
43
|
* Applies browser & date locks.
|
|
44
44
|
*/
|
|
45
45
|
class Lock extends _transform.default {
|
|
46
|
+
/**
|
|
47
|
+
* This is a boolean variable injected into the source code determining wether the countermeasures function has been called.
|
|
48
|
+
* This is used to prevent infinite loops from happening
|
|
49
|
+
*/
|
|
46
50
|
constructor(o) {
|
|
47
51
|
super(o, _order.ObfuscateOrder.Lock); // Removed feature
|
|
48
52
|
// if (this.options.lock.startDate && this.options.lock.endDate) {
|
|
@@ -55,6 +59,8 @@ class Lock extends _transform.default {
|
|
|
55
59
|
|
|
56
60
|
_defineProperty(this, "iosDetectFn", void 0);
|
|
57
61
|
|
|
62
|
+
_defineProperty(this, "counterMeasuresActivated", void 0);
|
|
63
|
+
|
|
58
64
|
_defineProperty(this, "made", void 0);
|
|
59
65
|
|
|
60
66
|
if (this.options.lock.integrity) {
|
|
@@ -70,34 +76,29 @@ class Lock extends _transform.default {
|
|
|
70
76
|
|
|
71
77
|
apply(tree) {
|
|
72
78
|
if (typeof this.options.lock.countermeasures === "string" && (0, _compare.isValidIdentifier)(this.options.lock.countermeasures)) {
|
|
73
|
-
var defined = new Set();
|
|
74
79
|
(0, _traverse.default)(tree, (object, parents) => {
|
|
75
|
-
if (object.type == "Identifier") {
|
|
80
|
+
if (object.type == "Identifier" && object.name === this.options.lock.countermeasures) {
|
|
76
81
|
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
77
82
|
|
|
78
83
|
if (info.spec.isDefined) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
|
|
84
|
-
} else {
|
|
85
|
-
var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
|
|
86
|
-
|
|
87
|
-
if (definingContext != tree) {
|
|
88
|
-
throw new Error("Countermeasures function must be defined at the global level");
|
|
89
|
-
}
|
|
84
|
+
if (this.counterMeasuresNode) {
|
|
85
|
+
throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
|
|
86
|
+
} else {
|
|
87
|
+
var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
if (definingContext != tree) {
|
|
90
|
+
throw new Error("Countermeasures function must be defined at the global level");
|
|
91
|
+
}
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
chain = [parents[0], parents.slice(1)];
|
|
95
|
-
} else if (info.isVariableDeclaration) {
|
|
96
|
-
chain = [parents[1], parents.slice(2)];
|
|
97
|
-
}
|
|
93
|
+
var chain = [object, parents];
|
|
98
94
|
|
|
99
|
-
|
|
95
|
+
if (info.isFunctionDeclaration) {
|
|
96
|
+
chain = [parents[0], parents.slice(1)];
|
|
97
|
+
} else if (info.isVariableDeclaration) {
|
|
98
|
+
chain = [parents[1], parents.slice(2)];
|
|
100
99
|
}
|
|
100
|
+
|
|
101
|
+
this.counterMeasuresNode = chain;
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
}
|
|
@@ -111,7 +112,7 @@ class Lock extends _transform.default {
|
|
|
111
112
|
super.apply(tree);
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
getCounterMeasuresCode() {
|
|
115
|
+
getCounterMeasuresCode(object, parents) {
|
|
115
116
|
var opt = this.options.lock.countermeasures;
|
|
116
117
|
|
|
117
118
|
if (opt === false) {
|
|
@@ -120,8 +121,13 @@ class Lock extends _transform.default {
|
|
|
120
121
|
|
|
121
122
|
|
|
122
123
|
if (typeof opt === "string") {
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
if (!this.counterMeasuresActivated) {
|
|
125
|
+
this.counterMeasuresActivated = this.getPlaceholder();
|
|
126
|
+
(0, _insert.prepend)(parents[parents.length - 1] || object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.counterMeasuresActivated)));
|
|
127
|
+
} // Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
return [(0, _gen.ExpressionStatement)((0, _gen.LogicalExpression)("||", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.SequenceExpression)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.Literal)(true)), (0, _gen.CallExpression)((0, _template.default)(opt).single().expression, [])])))];
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
var type = (0, _random.choice)(["crash", "exit"]);
|
|
@@ -239,7 +245,7 @@ class Lock extends _transform.default {
|
|
|
239
245
|
// A very simple mechanism inspired from https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/src/custom-code-helpers/self-defending/templates/SelfDefendingNoEvalTemplate.ts
|
|
240
246
|
// regExp checks for a newline, formatters add these
|
|
241
247
|
var callExpression = (0, _template.default)("\n (\n function(){\n // Breaks JSNice.org, beautifier.io\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n return test()\n }\n\n return namedFunction();\n }\n )()\n ").single().expression;
|
|
242
|
-
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode() || [], null));
|
|
248
|
+
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
243
249
|
break;
|
|
244
250
|
|
|
245
251
|
case "nativeFunction":
|
|
@@ -270,23 +276,24 @@ class Lock extends _transform.default {
|
|
|
270
276
|
test = (0, _template.default)("".concat(fn, ".toString().split(\"{ [native code] }\").length <= 1")).single().expression;
|
|
271
277
|
}
|
|
272
278
|
|
|
273
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
|
|
279
|
+
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
274
280
|
}
|
|
275
281
|
|
|
276
282
|
break;
|
|
277
283
|
|
|
278
284
|
case "startDate":
|
|
279
285
|
test = (0, _gen.BinaryExpression)("<", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.startDate)));
|
|
280
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
|
|
286
|
+
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
281
287
|
break;
|
|
282
288
|
|
|
283
289
|
case "endDate":
|
|
284
290
|
test = (0, _gen.BinaryExpression)(">", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.endDate)));
|
|
285
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
|
|
291
|
+
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
286
292
|
break;
|
|
287
293
|
|
|
288
294
|
case "context":
|
|
289
|
-
var prop = (0, _random.choice)(this.options.lock.context);
|
|
295
|
+
var prop = (0, _random.choice)(this.options.lock.context);
|
|
296
|
+
var code = this.getCounterMeasuresCode(object, parents) || []; // Todo: Alternative to `this`
|
|
290
297
|
|
|
291
298
|
if (!this.globalVar) {
|
|
292
299
|
offset = 1;
|
|
@@ -295,12 +302,13 @@ class Lock extends _transform.default {
|
|
|
295
302
|
}
|
|
296
303
|
|
|
297
304
|
test = (0, _gen.UnaryExpression)("!", (0, _gen.MemberExpression)((0, _gen.Identifier)(this.globalVar), (0, _gen.Literal)(prop), true));
|
|
298
|
-
nodes.push((0, _gen.IfStatement)(test,
|
|
305
|
+
nodes.push((0, _gen.IfStatement)(test, code, null));
|
|
299
306
|
break;
|
|
300
307
|
|
|
301
308
|
case "osLock":
|
|
302
309
|
var navigatorUserAgent = (0, _template.default)("window.navigator.userAgent.toLowerCase()").single().expression;
|
|
303
310
|
(0, _assert.ok)(this.options.lock.osLock);
|
|
311
|
+
var code = this.getCounterMeasuresCode(object, parents) || [];
|
|
304
312
|
this.options.lock.osLock.forEach(osName => {
|
|
305
313
|
var agentMatcher = {
|
|
306
314
|
windows: "Win",
|
|
@@ -338,7 +346,7 @@ class Lock extends _transform.default {
|
|
|
338
346
|
});
|
|
339
347
|
test = (0, _gen.UnaryExpression)("!", { ...test
|
|
340
348
|
});
|
|
341
|
-
nodes.push((0, _gen.IfStatement)(test,
|
|
349
|
+
nodes.push((0, _gen.IfStatement)(test, code, null));
|
|
342
350
|
break;
|
|
343
351
|
|
|
344
352
|
case "browserLock":
|
|
@@ -360,7 +368,7 @@ class Lock extends _transform.default {
|
|
|
360
368
|
});
|
|
361
369
|
test = (0, _gen.UnaryExpression)("!", { ...test
|
|
362
370
|
});
|
|
363
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
|
|
371
|
+
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
364
372
|
break;
|
|
365
373
|
|
|
366
374
|
case "domainLock":
|
|
@@ -392,7 +400,7 @@ class Lock extends _transform.default {
|
|
|
392
400
|
test = (0, _gen.LogicalExpression)("||", (0, _gen.BinaryExpression)("==", (0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)("location")), (0, _gen.Literal)("undefined")), test);
|
|
393
401
|
}
|
|
394
402
|
|
|
395
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
|
|
403
|
+
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
396
404
|
}
|
|
397
405
|
|
|
398
406
|
break;
|
|
@@ -53,7 +53,7 @@ class Minify extends _transform.default {
|
|
|
53
53
|
var earlyReturn = body.length;
|
|
54
54
|
var fnDecs = [];
|
|
55
55
|
body.forEach((stmt, i) => {
|
|
56
|
-
if (stmt.type
|
|
56
|
+
if (stmt.type === "ReturnStatement" || stmt.type === "BreakStatement" || stmt.type === "ContinueStatement" || stmt.type === "ThrowStatement") {
|
|
57
57
|
if (earlyReturn > i + 1) {
|
|
58
58
|
earlyReturn = i + 1;
|
|
59
59
|
}
|
|
@@ -136,7 +136,7 @@ class Minify extends _transform.default {
|
|
|
136
136
|
if (!lastDec || lastDec.kind !== x.kind || !lastDec.declarations.length) {
|
|
137
137
|
lastDec = x;
|
|
138
138
|
} else {
|
|
139
|
-
lastDec.declarations.push(...x.declarations);
|
|
139
|
+
lastDec.declarations.push(...(0, _insert.clone)(x.declarations));
|
|
140
140
|
remove.unshift(i);
|
|
141
141
|
}
|
|
142
142
|
} else {
|
|
@@ -17,8 +17,6 @@ var _identifiers = require("../../util/identifiers");
|
|
|
17
17
|
|
|
18
18
|
var _label = _interopRequireDefault(require("../label"));
|
|
19
19
|
|
|
20
|
-
var _antiDestructuring = _interopRequireDefault(require("../es5/antiDestructuring"));
|
|
21
|
-
|
|
22
20
|
var _compare = require("../../util/compare");
|
|
23
21
|
|
|
24
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -179,11 +177,6 @@ class Preparation extends _transform.default {
|
|
|
179
177
|
this.before.push(new _label.default(o));
|
|
180
178
|
this.before.push(new ExplicitIdentifiers(o));
|
|
181
179
|
this.before.push(new ExplicitDeclarations(o));
|
|
182
|
-
|
|
183
|
-
if (this.options.es5) {
|
|
184
|
-
this.before.push(new _antiDestructuring.default(o));
|
|
185
|
-
} // this.before.push(new NameConflicts(o));
|
|
186
|
-
|
|
187
180
|
}
|
|
188
181
|
|
|
189
182
|
match() {
|
package/dist/transforms/rgf.js
CHANGED
|
@@ -25,6 +25,8 @@ var _identifiers = require("../util/identifiers");
|
|
|
25
25
|
|
|
26
26
|
var _insert = require("../util/insert");
|
|
27
27
|
|
|
28
|
+
var _random = require("../util/random");
|
|
29
|
+
|
|
28
30
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
29
31
|
|
|
30
32
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
@@ -69,13 +71,52 @@ class RGF extends _transform.default {
|
|
|
69
71
|
var collect = [];
|
|
70
72
|
var queue = [];
|
|
71
73
|
var names = new Map();
|
|
74
|
+
var referenceSignatures = {};
|
|
72
75
|
var definingNodes = new Map();
|
|
73
76
|
(0, _traverse.walk)(contextObject, contextParents, (object, parents) => {
|
|
74
77
|
if (object !== contextObject && (0, _insert.isFunction)(object) && !object.$requiresEval && !object.async && !object.generator && (0, _insert.getVarContext)(parents[0], parents.slice(1)) === contextObject) {
|
|
78
|
+
var _this$options$lock;
|
|
79
|
+
|
|
80
|
+
// Discard getter/setter methods
|
|
81
|
+
if (parents[0].type === "Property" && parents[0].value === object) {
|
|
82
|
+
if (parents[0].method || parents[0].kind === "get" || parents[0].kind === "set") {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
} // Discard class methods
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
|
|
89
|
+
return;
|
|
90
|
+
} // Avoid applying to the countermeasures function
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if (typeof ((_this$options$lock = this.options.lock) === null || _this$options$lock === void 0 ? void 0 : _this$options$lock.countermeasures) === "string") {
|
|
94
|
+
// function countermeasures(){...}
|
|
95
|
+
if (object.type === "FunctionDeclaration" && object.id.type === "Identifier" && object.id.name === this.options.lock.countermeasures) {
|
|
96
|
+
return;
|
|
97
|
+
} // var countermeasures = function(){...}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if (parents[0].type === "VariableDeclarator" && parents[0].init === object && parents[0].id.type === "Identifier" && parents[0].id.name === this.options.lock.countermeasures) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
75
105
|
var defined = new Set(),
|
|
76
106
|
referenced = new Set();
|
|
77
107
|
var isBound = false;
|
|
78
|
-
|
|
108
|
+
/**
|
|
109
|
+
* The fnTraverses serves two important purposes
|
|
110
|
+
*
|
|
111
|
+
* - Identify all the variables referenced and defined here
|
|
112
|
+
* - Identify is the 'this' keyword is used anywhere
|
|
113
|
+
*
|
|
114
|
+
* @param o
|
|
115
|
+
* @param p
|
|
116
|
+
* @returns
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
const fnTraverser = (o, p) => {
|
|
79
120
|
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
80
121
|
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
81
122
|
|
|
@@ -83,7 +124,7 @@ class RGF extends _transform.default {
|
|
|
83
124
|
return;
|
|
84
125
|
}
|
|
85
126
|
|
|
86
|
-
if (info.spec.isDefined) {
|
|
127
|
+
if (info.spec.isDefined && (0, _insert.getDefiningContext)(o, p) === object) {
|
|
87
128
|
defined.add(o.name);
|
|
88
129
|
} else {
|
|
89
130
|
referenced.add(o.name);
|
|
@@ -93,7 +134,10 @@ class RGF extends _transform.default {
|
|
|
93
134
|
if (o.type == "ThisExpression" || o.type == "Super") {
|
|
94
135
|
isBound = true;
|
|
95
136
|
}
|
|
96
|
-
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
(0, _traverse.walk)(object.params, [object, ...parents], fnTraverser);
|
|
140
|
+
(0, _traverse.walk)(object.body, [object, ...parents], fnTraverser);
|
|
97
141
|
|
|
98
142
|
if (!isBound) {
|
|
99
143
|
var _object$id;
|
|
@@ -159,6 +203,7 @@ class RGF extends _transform.default {
|
|
|
159
203
|
if (object.type == "FunctionDeclaration" && typeof object.id.name === "string") {
|
|
160
204
|
var index = names.size;
|
|
161
205
|
names.set(object.id.name, index);
|
|
206
|
+
referenceSignatures[index] = (0, _random.getRandomString)(10);
|
|
162
207
|
definingNodes.set(object.id.name, object.id);
|
|
163
208
|
}
|
|
164
209
|
}
|
|
@@ -166,9 +211,10 @@ class RGF extends _transform.default {
|
|
|
166
211
|
|
|
167
212
|
if (!queue.length) {
|
|
168
213
|
return;
|
|
169
|
-
}
|
|
214
|
+
} // An array containing all the function declarations
|
|
215
|
+
|
|
170
216
|
|
|
171
|
-
var referenceArray =
|
|
217
|
+
var referenceArray = "_" + (0, _random.getRandomString)(10);
|
|
172
218
|
(0, _traverse.walk)(contextObject, contextParents, (o, p) => {
|
|
173
219
|
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name)) {
|
|
174
220
|
var index = names.get(o.name);
|
|
@@ -185,7 +231,19 @@ class RGF extends _transform.default {
|
|
|
185
231
|
|
|
186
232
|
if (pointingTo == shouldBe) {
|
|
187
233
|
this.log(o.name, "->", "".concat(referenceArray, "[").concat(index, "]"));
|
|
188
|
-
|
|
234
|
+
var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(referenceArray), (0, _gen.Literal)(index), true); // Allow re-assignment to the RGF function
|
|
235
|
+
|
|
236
|
+
if (p[0] && p[0].type === "AssignmentExpression" && p[0].left === o) {
|
|
237
|
+
// fn = ...
|
|
238
|
+
this.replace(o, memberExpression);
|
|
239
|
+
} else {
|
|
240
|
+
// fn()
|
|
241
|
+
// fn
|
|
242
|
+
// In most cases the identifier is being used like this (call expression, or referenced to be called later)
|
|
243
|
+
// Replace it with a simple wrapper function that will pass on the reference array
|
|
244
|
+
var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)(memberExpression, [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
|
|
245
|
+
this.replace(o, conditionalExpression);
|
|
246
|
+
}
|
|
189
247
|
}
|
|
190
248
|
}
|
|
191
249
|
}
|
|
@@ -202,6 +260,7 @@ class RGF extends _transform.default {
|
|
|
202
260
|
var name = object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name;
|
|
203
261
|
var hasName = !!name;
|
|
204
262
|
var params = object.params.map(x => x.name) || [];
|
|
263
|
+
var signature = referenceSignatures[names.get(name)];
|
|
205
264
|
var embeddedName = name || this.getPlaceholder(); // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
|
|
206
265
|
// RGF runs early and needs completed code before converting to a string.
|
|
207
266
|
// (^ the variables haven't been renamed yet)
|
|
@@ -222,7 +281,7 @@ class RGF extends _transform.default {
|
|
|
222
281
|
};
|
|
223
282
|
var tree = {
|
|
224
283
|
type: "Program",
|
|
225
|
-
body: [embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedName), (0, _gen.
|
|
284
|
+
body: [embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedName), (0, _gen.Literal)("call"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.SpreadElement)((0, _template.default)("Array.prototype.slice.call(arguments, 1)").single().expression)]))]
|
|
226
285
|
};
|
|
227
286
|
tree.__hiddenDeclarations = (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(referenceArray));
|
|
228
287
|
tree.__hiddenDeclarations.hidden = true;
|
|
@@ -241,8 +300,17 @@ class RGF extends _transform.default {
|
|
|
241
300
|
var toString = (0, _compiler.compileJsSync)(tree, this.options);
|
|
242
301
|
var newFunction = (0, _gen.NewExpression)((0, _gen.Identifier)("Function"), [(0, _gen.Literal)(referenceArray), (0, _gen.Literal)(toString)]);
|
|
243
302
|
|
|
244
|
-
|
|
245
|
-
|
|
303
|
+
function applySignature(fn) {
|
|
304
|
+
if (!signature) {
|
|
305
|
+
return fn;
|
|
306
|
+
} // This code marks the function object with a unique property
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
return (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("fn", fn)), (0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.MemberExpression)((0, _gen.Identifier)("fn"), (0, _gen.Literal)(signature), true), (0, _gen.Literal)(true))), (0, _gen.ReturnStatement)((0, _gen.Identifier)("fn"))]), []);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (object.type === "FunctionDeclaration") {
|
|
313
|
+
arrayExpression.elements[names.get(name)] = applySignature(newFunction);
|
|
246
314
|
|
|
247
315
|
if (Array.isArray(parents[0])) {
|
|
248
316
|
parents[0].splice(parents[0].indexOf(object), 1);
|
|
@@ -250,7 +318,9 @@ class RGF extends _transform.default {
|
|
|
250
318
|
this.error(new Error("Error deleting function declaration: " + parents.map(x => x.type).join(",")));
|
|
251
319
|
}
|
|
252
320
|
} else {
|
|
253
|
-
|
|
321
|
+
// The wrapper function passes the reference array around
|
|
322
|
+
var wrapperFunction = (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)(newFunction, (0, _gen.Literal)("call"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]);
|
|
323
|
+
this.replace(object, applySignature(wrapperFunction));
|
|
254
324
|
}
|
|
255
325
|
});
|
|
256
326
|
};
|
|
@@ -45,28 +45,8 @@ class StringSplitting extends _transform.default {
|
|
|
45
45
|
this.vars = [];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
apply(tree) {
|
|
49
|
-
super.apply(tree);
|
|
50
|
-
|
|
51
|
-
if (this.vars.length) {
|
|
52
|
-
(0, _random.shuffle)(this.adders);
|
|
53
|
-
(0, _random.shuffle)(this.vars);
|
|
54
|
-
var body = tree.body;
|
|
55
|
-
this.adders.forEach(nodes => {
|
|
56
|
-
nodes.forEach(x => body.unshift(x));
|
|
57
|
-
});
|
|
58
|
-
var variableDeclaration = {
|
|
59
|
-
type: "VariableDeclaration",
|
|
60
|
-
declarations: [],
|
|
61
|
-
kind: "var"
|
|
62
|
-
};
|
|
63
|
-
this.vars.forEach(node => variableDeclaration.declarations.push(node));
|
|
64
|
-
body.unshift(variableDeclaration);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
48
|
match(object, parents) {
|
|
69
|
-
return object.type == "Literal" && typeof object.value === "string" && !(0, _stringConcealing.isModuleSource)(object, parents) && !(0, _compare.isDirective)(object, parents);
|
|
49
|
+
return object.type == "Literal" && typeof object.value === "string" && object.value.length >= 8 && !(0, _stringConcealing.isModuleSource)(object, parents) && !(0, _compare.isDirective)(object, parents);
|
|
70
50
|
}
|
|
71
51
|
|
|
72
52
|
transform(object, parents) {
|
|
@@ -92,7 +72,6 @@ class StringSplitting extends _transform.default {
|
|
|
92
72
|
var last = chunks.pop();
|
|
93
73
|
chunks.forEach((chunk, i) => {
|
|
94
74
|
if (i == 0) {
|
|
95
|
-
(0, _assert.ok)(i == 0);
|
|
96
75
|
parent = binaryExpression = (0, _gen.BinaryExpression)("+", (0, _gen.Literal)(chunk), (0, _gen.Literal)(""));
|
|
97
76
|
} else {
|
|
98
77
|
binaryExpression.left = (0, _gen.BinaryExpression)("+", (0, _insert.clone)(binaryExpression.left), (0, _gen.Literal)(chunk));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-confuser",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.7",
|
|
4
4
|
"description": "JavaScript Obfuscation Tool.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"bugs": {
|
|
46
46
|
"url": "https://github.com/MichaelXF/js-confuser/issues"
|
|
47
47
|
},
|
|
48
|
-
"homepage": "https://
|
|
48
|
+
"homepage": "https://master--hungry-shannon-c1ce6b.netlify.app/",
|
|
49
49
|
"jest": {
|
|
50
50
|
"coverageReporters": [
|
|
51
51
|
"html"
|
|
@@ -328,8 +328,8 @@ export default class Flatten extends Transform {
|
|
|
328
328
|
var pop = CallExpression(
|
|
329
329
|
MemberExpression(
|
|
330
330
|
MemberExpression(Identifier(resultName), Identifier(propName), false),
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
Literal("pop"),
|
|
332
|
+
true
|
|
333
333
|
),
|
|
334
334
|
[]
|
|
335
335
|
);
|
|
@@ -93,10 +93,10 @@ export default class VariableAnalysis extends Transform {
|
|
|
93
93
|
ok(definingContexts.length);
|
|
94
94
|
|
|
95
95
|
definingContexts.forEach((definingContext) => {
|
|
96
|
-
ok(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
);
|
|
96
|
+
// ok(
|
|
97
|
+
// isContext(definingContext),
|
|
98
|
+
// `${definingContext.type} is not a context`
|
|
99
|
+
// );
|
|
100
100
|
|
|
101
101
|
if (isDefined) {
|
|
102
102
|
// Add to defined Map
|
|
@@ -195,7 +195,10 @@ export default class Integrity extends Transform {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
return () => {
|
|
198
|
-
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(
|
|
198
|
+
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(
|
|
199
|
+
object,
|
|
200
|
+
parents
|
|
201
|
+
);
|
|
199
202
|
|
|
200
203
|
object.$eval = () => {
|
|
201
204
|
var functionName = this.generateIdentifier();
|
|
@@ -258,6 +261,15 @@ export default class Integrity extends Transform {
|
|
|
258
261
|
ifStatement,
|
|
259
262
|
]);
|
|
260
263
|
|
|
264
|
+
// Make sure the countermeasures activation variable is present
|
|
265
|
+
if (this.lock.counterMeasuresActivated) {
|
|
266
|
+
object.body.body.unshift(
|
|
267
|
+
VariableDeclaration(
|
|
268
|
+
VariableDeclarator(this.lock.counterMeasuresActivated)
|
|
269
|
+
)
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
261
273
|
if (object.type == "ArrowFunctionExpression") {
|
|
262
274
|
object.type = "FunctionExpression";
|
|
263
275
|
object.expression = false;
|