js-confuser 1.5.6 → 1.5.8
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 +28 -0
- package/dist/options.js +4 -4
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +16 -2
- package/dist/transforms/identifier/nameRecycling.js +8 -2
- package/dist/transforms/identifier/renameVariables.js +9 -0
- package/dist/transforms/lock/antiDebug.js +1 -1
- package/dist/transforms/lock/integrity.js +6 -2
- package/dist/transforms/lock/lock.js +40 -32
- package/dist/transforms/preparation/preparation.js +0 -7
- package/dist/transforms/rgf.js +32 -3
- package/dist/transforms/string/stringConcealing.js +77 -40
- package/dist/transforms/transform.js +1 -1
- package/package.json +2 -2
- package/src/options.ts +10 -4
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +16 -1
- package/src/transforms/identifier/nameRecycling.ts +14 -3
- package/src/transforms/identifier/renameVariables.ts +19 -0
- package/src/transforms/lock/antiDebug.ts +1 -1
- package/src/transforms/lock/integrity.ts +13 -1
- package/src/transforms/lock/lock.ts +81 -44
- package/src/transforms/preparation/preparation.ts +2 -21
- package/src/transforms/rgf.ts +39 -3
- package/src/transforms/string/stringConcealing.ts +120 -56
- package/src/transforms/transform.ts +1 -1
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +36 -0
- package/test/transforms/identifier/nameRecycling.test.ts +39 -0
- package/test/transforms/identifier/renameVariables.test.ts +38 -0
- package/test/transforms/lock/countermeasures.test.ts +18 -0
- package/test/transforms/rgf.test.ts +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
# `1.5.8`
|
|
2
|
+
Several fixes
|
|
3
|
+
|
|
4
|
+
- Fixed [#46](https://github.com/MichaelXF/js-confuser/issues/46)
|
|
5
|
+
- - Updated the validation on `lock` options
|
|
6
|
+
|
|
7
|
+
- Fixed [#68](https://github.com/MichaelXF/js-confuser/issues/68)
|
|
8
|
+
- - Name Recycling fixed to not break certain function declarations
|
|
9
|
+
|
|
10
|
+
- Fixed [#69](https://github.com/MichaelXF/js-confuser/issues/69), [#70](https://github.com/MichaelXF/js-confuser/issues/70) and [#71](https://github.com/MichaelXF/js-confuser/issues/71)
|
|
11
|
+
- - Import statements to be properly handled
|
|
12
|
+
|
|
13
|
+
- Slight improvements to String Concealing
|
|
14
|
+
|
|
15
|
+
# `1.5.7`
|
|
16
|
+
Countermeasures function fixes
|
|
17
|
+
|
|
18
|
+
This update focuses on fixing Countermeasures bugs
|
|
19
|
+
|
|
20
|
+
The `countermeasures` is custom callback function to invoke when a lock is triggered.
|
|
21
|
+
|
|
22
|
+
- Fixed [#66](https://github.com/MichaelXF/js-confuser/issues/66)
|
|
23
|
+
- - RGF to properly handle the countermeasures function
|
|
24
|
+
|
|
25
|
+
- Added additional code to prevent an infinite loop from occurring
|
|
26
|
+
|
|
27
|
+
- Slight improvements to RGF
|
|
28
|
+
|
|
1
29
|
# `1.5.6`
|
|
2
30
|
Website changed and RGF fixes
|
|
3
31
|
|
package/dist/options.js
CHANGED
|
@@ -40,24 +40,24 @@ function validateOptions(options) {
|
|
|
40
40
|
|
|
41
41
|
if (options.lock) {
|
|
42
42
|
// Validate browser-lock option
|
|
43
|
-
if (typeof options.lock.browserLock !== "undefined") {
|
|
43
|
+
if (options.lock.browserLock && typeof options.lock.browserLock !== "undefined") {
|
|
44
44
|
(0, _assert.ok)(Array.isArray(options.lock.browserLock), "browserLock must be an array");
|
|
45
45
|
(0, _assert.ok)(!options.lock.browserLock.find(browserName => !validBrowsers.has(browserName)), 'Invalid browser name. Allowed: "firefox", "chrome", "iexplorer", "edge", "safari", "opera"');
|
|
46
46
|
} // Validate os-lock option
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
if (typeof options.lock.osLock !== "undefined") {
|
|
49
|
+
if (options.lock.osLock && typeof options.lock.osLock !== "undefined") {
|
|
50
50
|
(0, _assert.ok)(Array.isArray(options.lock.osLock), "osLock must be an array");
|
|
51
51
|
(0, _assert.ok)(!options.lock.osLock.find(osName => !validOses.has(osName)), 'Invalid OS name. Allowed: "windows", "linux", "osx", "ios", "android"');
|
|
52
52
|
} // Validate domain-lock option
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
if (typeof options.lock.domainLock !== "undefined") {
|
|
55
|
+
if (options.lock.domainLock && typeof options.lock.domainLock !== "undefined") {
|
|
56
56
|
(0, _assert.ok)(Array.isArray(options.lock.domainLock), "domainLock must be an array");
|
|
57
57
|
} // Validate context option
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
if (typeof options.lock.context !== "undefined") {
|
|
60
|
+
if (options.lock.context && typeof options.lock.context !== "undefined") {
|
|
61
61
|
(0, _assert.ok)(Array.isArray(options.lock.context), "context must be an array");
|
|
62
62
|
} // Validate start-date option
|
|
63
63
|
|
|
@@ -31,6 +31,8 @@ var _expressionObfuscation = _interopRequireDefault(require("./expressionObfusca
|
|
|
31
31
|
|
|
32
32
|
var _switchCaseObfuscation = _interopRequireDefault(require("./switchCaseObfuscation"));
|
|
33
33
|
|
|
34
|
+
var _stringConcealing = require("../string/stringConcealing");
|
|
35
|
+
|
|
34
36
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
35
37
|
|
|
36
38
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
@@ -181,6 +183,14 @@ class ControlFlowFlattening extends _transform.default {
|
|
|
181
183
|
illegalFnNames.forEach(illegal => {
|
|
182
184
|
fnNames.delete(illegal);
|
|
183
185
|
});
|
|
186
|
+
var importDeclarations = [];
|
|
187
|
+
|
|
188
|
+
for (var stmt of body) {
|
|
189
|
+
if (stmt.type === "ImportDeclaration") {
|
|
190
|
+
importDeclarations.push(stmt);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
184
194
|
var fraction = 0.9;
|
|
185
195
|
|
|
186
196
|
if (body.length > 20) {
|
|
@@ -237,7 +247,7 @@ class ControlFlowFlattening extends _transform.default {
|
|
|
237
247
|
body: [...currentBody]
|
|
238
248
|
});
|
|
239
249
|
(0, _traverse.walk)(currentBody, [], (o, p) => {
|
|
240
|
-
if (o.type == "Literal" && typeof o.value == "string" && !o.regex && Math.random() / (Object.keys(stringBank).length / 2 + 1) > 0.5) {
|
|
250
|
+
if (o.type == "Literal" && typeof o.value == "string" && !(0, _stringConcealing.isModuleSource)(o, p) && !o.regex && Math.random() / (Object.keys(stringBank).length / 2 + 1) > 0.5) {
|
|
241
251
|
needsStringBankVar = true;
|
|
242
252
|
|
|
243
253
|
if (!stringBankByLabels[currentLabel]) {
|
|
@@ -260,7 +270,7 @@ class ControlFlowFlattening extends _transform.default {
|
|
|
260
270
|
};
|
|
261
271
|
|
|
262
272
|
body.forEach((stmt, i) => {
|
|
263
|
-
if (functionDeclarations.has(stmt)) {
|
|
273
|
+
if (functionDeclarations.has(stmt) || stmt.type === "ImportDeclaration") {
|
|
264
274
|
return;
|
|
265
275
|
}
|
|
266
276
|
|
|
@@ -708,6 +718,10 @@ class ControlFlowFlattening extends _transform.default {
|
|
|
708
718
|
var discriminant = (0, _template.default)("".concat(stateVars.join("+"))).single().expression;
|
|
709
719
|
body.length = 0;
|
|
710
720
|
|
|
721
|
+
for (var importDeclaration of importDeclarations) {
|
|
722
|
+
body.push(importDeclaration);
|
|
723
|
+
}
|
|
724
|
+
|
|
711
725
|
if (functionDeclarations.size) {
|
|
712
726
|
functionDeclarations.forEach(x => {
|
|
713
727
|
if (!x.id || illegalFnNames.has(x.id.name)) {
|
|
@@ -87,7 +87,6 @@ class NameRecycling extends _transform.default {
|
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
lastReferenceMap.set(o.name, i);
|
|
91
90
|
var comparingContext = info.spec.isDefined ? (0, _insert.getDefiningContext)(o, p) : (0, _insert.getReferencingContexts)(o, p).find(x => (0, _insert.isVarContext)(x));
|
|
92
91
|
|
|
93
92
|
if (comparingContext !== context) {
|
|
@@ -101,7 +100,12 @@ class NameRecycling extends _transform.default {
|
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
if (info.spec.isDefined) {
|
|
104
|
-
|
|
103
|
+
// Function Declarations can be used before they're defined, if so, don't change this
|
|
104
|
+
if (info.isFunctionDeclaration && lastReferenceMap.has(o.name)) {
|
|
105
|
+
illegal.add(o.name);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (defined.has(o.name) || (0, _traverse.getBlock)(o, p) !== object || info.isImportSpecifier) {
|
|
105
109
|
illegal.add(o.name);
|
|
106
110
|
}
|
|
107
111
|
|
|
@@ -111,6 +115,8 @@ class NameRecycling extends _transform.default {
|
|
|
111
115
|
referencedHere.add(o.name);
|
|
112
116
|
}
|
|
113
117
|
}
|
|
118
|
+
|
|
119
|
+
lastReferenceMap.set(o.name, i);
|
|
114
120
|
};
|
|
115
121
|
}
|
|
116
122
|
}); // console.log(i, definedHere);
|
|
@@ -165,6 +165,15 @@ class RenameVariables extends _transform.default {
|
|
|
165
165
|
if (newName && typeof newName === "string") {
|
|
166
166
|
if (o.$renamed) {
|
|
167
167
|
return;
|
|
168
|
+
} // Strange behavior where the `local` and `imported` objects are the same
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if (info.isImportSpecifier) {
|
|
172
|
+
var importSpecifierIndex = p.findIndex(x => x.type === "ImportSpecifier");
|
|
173
|
+
|
|
174
|
+
if (importSpecifierIndex != -1 && p[importSpecifierIndex].imported === (p[importSpecifierIndex - 1] || o) && p[importSpecifierIndex].imported && p[importSpecifierIndex].imported.type === "Identifier") {
|
|
175
|
+
p[importSpecifierIndex].imported = (0, _insert.clone)(p[importSpecifierIndex - 1] || o);
|
|
176
|
+
}
|
|
168
177
|
} // console.log(o.name, "->", newName);
|
|
169
178
|
|
|
170
179
|
|
|
@@ -43,7 +43,7 @@ class AntiDebug extends _transform.default {
|
|
|
43
43
|
var startTimeName = this.getPlaceholder();
|
|
44
44
|
var endTimeName = this.getPlaceholder();
|
|
45
45
|
var isDevName = this.getPlaceholder();
|
|
46
|
-
var functionDeclaration = (0, _gen.FunctionDeclaration)(fnName, [], [...(0, _template.default)("\n var ".concat(startTimeName, " = new Date();\n debugger;\n var ").concat(endTimeName, " = new Date();\n var ").concat(isDevName, " = ").concat(endTimeName, "-").concat(startTimeName, " > 1000;\n ")).compile(), (0, _gen.IfStatement)((0, _gen.Identifier)(isDevName), this.options.lock.countermeasures ? this.lock.getCounterMeasuresCode() : [(0, _gen.WhileStatement)((0, _gen.Identifier)(isDevName), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(startTimeName), (0, _gen.Identifier)(endTimeName)))])], null)]);
|
|
46
|
+
var functionDeclaration = (0, _gen.FunctionDeclaration)(fnName, [], [...(0, _template.default)("\n var ".concat(startTimeName, " = new Date();\n debugger;\n var ").concat(endTimeName, " = new Date();\n var ").concat(isDevName, " = ").concat(endTimeName, "-").concat(startTimeName, " > 1000;\n ")).compile(), (0, _gen.IfStatement)((0, _gen.Identifier)(isDevName), this.options.lock.countermeasures ? this.lock.getCounterMeasuresCode(tree.body, [tree]) : [(0, _gen.WhileStatement)((0, _gen.Identifier)(isDevName), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(startTimeName), (0, _gen.Identifier)(endTimeName)))])], null)]);
|
|
47
47
|
tree.body.unshift(...DevToolsDetection.compile({
|
|
48
48
|
functionName: fnName
|
|
49
49
|
}));
|
|
@@ -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;
|
|
@@ -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
|
@@ -75,6 +75,8 @@ class RGF extends _transform.default {
|
|
|
75
75
|
var definingNodes = new Map();
|
|
76
76
|
(0, _traverse.walk)(contextObject, contextParents, (object, parents) => {
|
|
77
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
|
+
|
|
78
80
|
// Discard getter/setter methods
|
|
79
81
|
if (parents[0].type === "Property" && parents[0].value === object) {
|
|
80
82
|
if (parents[0].method || parents[0].kind === "get" || parents[0].kind === "set") {
|
|
@@ -85,12 +87,36 @@ class RGF extends _transform.default {
|
|
|
85
87
|
|
|
86
88
|
if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
|
|
87
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
|
+
}
|
|
88
103
|
}
|
|
89
104
|
|
|
90
105
|
var defined = new Set(),
|
|
91
106
|
referenced = new Set();
|
|
92
107
|
var isBound = false;
|
|
93
|
-
|
|
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) => {
|
|
94
120
|
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
95
121
|
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
96
122
|
|
|
@@ -98,7 +124,7 @@ class RGF extends _transform.default {
|
|
|
98
124
|
return;
|
|
99
125
|
}
|
|
100
126
|
|
|
101
|
-
if (info.spec.isDefined) {
|
|
127
|
+
if (info.spec.isDefined && (0, _insert.getDefiningContext)(o, p) === object) {
|
|
102
128
|
defined.add(o.name);
|
|
103
129
|
} else {
|
|
104
130
|
referenced.add(o.name);
|
|
@@ -108,7 +134,10 @@ class RGF extends _transform.default {
|
|
|
108
134
|
if (o.type == "ThisExpression" || o.type == "Super") {
|
|
109
135
|
isBound = true;
|
|
110
136
|
}
|
|
111
|
-
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
(0, _traverse.walk)(object.params, [object, ...parents], fnTraverser);
|
|
140
|
+
(0, _traverse.walk)(object.body, [object, ...parents], fnTraverser);
|
|
112
141
|
|
|
113
142
|
if (!isBound) {
|
|
114
143
|
var _object$id;
|
|
@@ -70,17 +70,20 @@ class StringConcealing extends _transform.default {
|
|
|
70
70
|
|
|
71
71
|
_defineProperty(this, "encoding", Object.create(null));
|
|
72
72
|
|
|
73
|
+
_defineProperty(this, "gen", void 0);
|
|
74
|
+
|
|
73
75
|
_defineProperty(this, "hasAllEncodings", void 0);
|
|
74
76
|
|
|
75
77
|
this.set = new Set();
|
|
76
78
|
this.index = Object.create(null);
|
|
77
79
|
this.arrayExpression = (0, _gen.ArrayExpression)([]);
|
|
78
|
-
this.hasAllEncodings = false;
|
|
80
|
+
this.hasAllEncodings = false;
|
|
81
|
+
this.gen = this.getGenerator(); // Pad array with useless strings
|
|
79
82
|
|
|
80
|
-
var dead = (0, _random.getRandomInteger)(
|
|
83
|
+
var dead = (0, _random.getRandomInteger)(5, 15);
|
|
81
84
|
|
|
82
85
|
for (var i = 0; i < dead; i++) {
|
|
83
|
-
var str = (0, _random.getRandomString)((0, _random.getRandomInteger)(
|
|
86
|
+
var str = (0, _random.getRandomString)((0, _random.getRandomInteger)(5, 40));
|
|
84
87
|
var fn = this.transform((0, _gen.Literal)(str), []);
|
|
85
88
|
|
|
86
89
|
if (fn) {
|
|
@@ -104,7 +107,7 @@ class StringConcealing extends _transform.default {
|
|
|
104
107
|
(0, _insert.append)(tree, (0, _template.default)("\n \n function ".concat(getterFn, "(x, y, z, a = ").concat(decodeFn, ", b = ").concat(cacheName, "){\n if ( z ) {\n return y[").concat(cacheName, "[z]] = ").concat(getterFn, "(x, y);\n } else if ( y ) {\n [b, y] = [a(b), x || z]\n }\n \n return y ? x[b[y]] : ").concat(cacheName, "[x] || (z=(b[x], a), ").concat(cacheName, "[x] = z(").concat(this.arrayName, "[x]))\n }\n \n ")).single());
|
|
105
108
|
});
|
|
106
109
|
var flowIntegrity = this.getPlaceholder();
|
|
107
|
-
(0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(cacheName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)(flowIntegrity, (0, _gen.Literal)(0)), (0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("a", this.arrayExpression)), (0, _template.default)("return (".concat(flowIntegrity, " ? a
|
|
110
|
+
(0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(cacheName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)(flowIntegrity, (0, _gen.Literal)(0)), (0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("a", this.arrayExpression)), (0, _template.default)("return (".concat(flowIntegrity, " ? a[\"pop\"]() : ").concat(flowIntegrity, "++, a)")).single()]), []))]));
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
match(object, parents) {
|
|
@@ -117,7 +120,7 @@ class StringConcealing extends _transform.default {
|
|
|
117
120
|
transform(object, parents) {
|
|
118
121
|
return () => {
|
|
119
122
|
// Empty strings are discarded
|
|
120
|
-
if (!object.value || this.ignore.has(object.value)) {
|
|
123
|
+
if (!object.value || this.ignore.has(object.value) || object.value.length == 0) {
|
|
121
124
|
return;
|
|
122
125
|
}
|
|
123
126
|
|
|
@@ -143,53 +146,87 @@ class StringConcealing extends _transform.default {
|
|
|
143
146
|
|
|
144
147
|
if (encoder.decode(encoded) != object.value) {
|
|
145
148
|
this.ignore.add(object.value);
|
|
146
|
-
this.warn(object.value.slice(0, 100));
|
|
149
|
+
this.warn(type, object.value.slice(0, 100));
|
|
147
150
|
return;
|
|
148
|
-
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
var index = -1;
|
|
149
154
|
|
|
155
|
+
if (!this.set.has(object.value)) {
|
|
156
|
+
this.arrayExpression.elements.push((0, _gen.Literal)(encoded));
|
|
157
|
+
index = this.arrayExpression.elements.length - 1;
|
|
158
|
+
this.index[object.value] = [index, fnName];
|
|
159
|
+
this.set.add(object.value);
|
|
160
|
+
} else {
|
|
161
|
+
[index, fnName] = this.index[object.value];
|
|
162
|
+
(0, _assert.ok)(typeof index === "number");
|
|
163
|
+
}
|
|
150
164
|
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
(0, _assert.ok)(index != -1, "index == -1");
|
|
166
|
+
var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
|
|
153
167
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
[index, fnName] = this.index[object.value];
|
|
161
|
-
(0, _assert.ok)(typeof index === "number");
|
|
162
|
-
}
|
|
168
|
+
if (Math.random() > 0.5) {
|
|
169
|
+
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("apply"), false), [(0, _gen.ThisExpression)(), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
|
|
170
|
+
} // use `.call`
|
|
171
|
+
else if (Math.random() > 0.5) {
|
|
172
|
+
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.ThisExpression)(), (0, _gen.Literal)(index)]);
|
|
173
|
+
}
|
|
163
174
|
|
|
164
|
-
|
|
165
|
-
var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
|
|
175
|
+
var referenceType = "call";
|
|
166
176
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
else if (Math.random() > 0.5) {
|
|
171
|
-
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.ThisExpression)(), (0, _gen.Literal)(index)]);
|
|
172
|
-
}
|
|
177
|
+
if (parents.length && Math.random() < 0.5 / this.variablesMade) {
|
|
178
|
+
referenceType = "constantReference";
|
|
179
|
+
}
|
|
173
180
|
|
|
174
|
-
|
|
181
|
+
var newExpr = callExpr;
|
|
175
182
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
if (referenceType === "constantReference") {
|
|
184
|
+
// Define the string earlier, reference the name here
|
|
185
|
+
this.variablesMade++;
|
|
186
|
+
var constantReferenceType = (0, _random.choice)(["variable", "array", "object"]);
|
|
187
|
+
var place = (0, _random.choice)(parents.filter(node => (0, _traverse.isBlock)(node)));
|
|
180
188
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
189
|
+
if (!place) {
|
|
190
|
+
this.error(new Error("No lexical block to insert code"));
|
|
191
|
+
}
|
|
184
192
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
193
|
+
switch (constantReferenceType) {
|
|
194
|
+
case "variable":
|
|
195
|
+
var name = this.getPlaceholder();
|
|
196
|
+
(0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(name, callExpr)));
|
|
197
|
+
newExpr = (0, _gen.Identifier)(name);
|
|
198
|
+
break;
|
|
199
|
+
|
|
200
|
+
case "array":
|
|
201
|
+
if (!place.$stringConcealingArray) {
|
|
202
|
+
place.$stringConcealingArray = (0, _gen.ArrayExpression)([]);
|
|
203
|
+
place.$stringConcealingArrayName = this.getPlaceholder();
|
|
204
|
+
(0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(place.$stringConcealingArrayName, place.$stringConcealingArray)));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
var arrayIndex = place.$stringConcealingArray.elements.length;
|
|
208
|
+
place.$stringConcealingArray.elements.push(callExpr);
|
|
209
|
+
var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(place.$stringConcealingArrayName), (0, _gen.Literal)(arrayIndex), true);
|
|
210
|
+
newExpr = memberExpression;
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case "object":
|
|
214
|
+
if (!place.$stringConcealingObject) {
|
|
215
|
+
place.$stringConcealingObject = (0, _gen.ObjectExpression)([]);
|
|
216
|
+
place.$stringConcealingObjectName = this.getPlaceholder();
|
|
217
|
+
(0, _insert.prepend)(place, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(place.$stringConcealingObjectName, place.$stringConcealingObject)));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
var propName = this.gen.generate();
|
|
221
|
+
var property = (0, _gen.Property)((0, _gen.Literal)(propName), callExpr, true);
|
|
222
|
+
place.$stringConcealingObject.properties.push(property);
|
|
223
|
+
var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(place.$stringConcealingObjectName), (0, _gen.Literal)(propName), true);
|
|
224
|
+
newExpr = memberExpression;
|
|
225
|
+
break;
|
|
191
226
|
}
|
|
192
227
|
}
|
|
228
|
+
|
|
229
|
+
this.replaceIdentifierOrLiteral(object, newExpr, parents);
|
|
193
230
|
};
|
|
194
231
|
}
|
|
195
232
|
|