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
package/dist/transforms/rgf.js
CHANGED
|
@@ -15,9 +15,7 @@ var _order = require("../order");
|
|
|
15
15
|
|
|
16
16
|
var _probability = require("../probability");
|
|
17
17
|
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
var _traverse = _interopRequireWildcard(require("../traverse"));
|
|
18
|
+
var _traverse = require("../traverse");
|
|
21
19
|
|
|
22
20
|
var _gen = require("../util/gen");
|
|
23
21
|
|
|
@@ -25,16 +23,12 @@ var _identifiers = require("../util/identifiers");
|
|
|
25
23
|
|
|
26
24
|
var _insert = require("../util/insert");
|
|
27
25
|
|
|
28
|
-
var _random = require("../util/random");
|
|
29
|
-
|
|
30
26
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
31
27
|
|
|
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); }
|
|
33
|
-
|
|
34
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
35
|
-
|
|
36
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
37
29
|
|
|
30
|
+
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; }
|
|
31
|
+
|
|
38
32
|
/**
|
|
39
33
|
* Converts function to `new Function("..code..")` syntax as an alternative to `eval`. Eval is disabled in many environments.
|
|
40
34
|
*
|
|
@@ -43,285 +37,184 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
43
37
|
* Rigorous checks are in place to only include pure functions.
|
|
44
38
|
*
|
|
45
39
|
* `flatten` can attempt to make function reference-less. Recommended to have flatten enabled with RGF.
|
|
46
|
-
*
|
|
47
|
-
* | Mode | Description |
|
|
48
|
-
* | --- | --- |
|
|
49
|
-
* | `"all"` | Applies to all scopes |
|
|
50
|
-
* | `true` | Applies to the top level only |
|
|
51
|
-
* | `false` | Feature disabled |
|
|
52
40
|
*/
|
|
53
41
|
class RGF extends _transform.default {
|
|
42
|
+
// Array of all the `new Function` calls
|
|
43
|
+
// The name of the array holding all the `new Function` expressions
|
|
54
44
|
constructor(o) {
|
|
55
45
|
super(o, _order.ObfuscateOrder.RGF);
|
|
46
|
+
|
|
47
|
+
_defineProperty(this, "arrayExpressionElements", void 0);
|
|
48
|
+
|
|
49
|
+
_defineProperty(this, "arrayExpressionName", void 0);
|
|
50
|
+
|
|
51
|
+
this.arrayExpressionName = this.getPlaceholder() + "_rgf";
|
|
52
|
+
this.arrayExpressionElements = [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
apply(tree) {
|
|
56
|
+
super.apply(tree); // Only add the array if there were converted functions
|
|
57
|
+
|
|
58
|
+
if (this.arrayExpressionElements.length > 0) {
|
|
59
|
+
(0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.ArrayExpression)(this.arrayExpressionElements))));
|
|
60
|
+
}
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
match(object, parents) {
|
|
59
|
-
return (
|
|
64
|
+
return (object.type === "FunctionDeclaration" || object.type === "FunctionExpression") && // Does not apply to Arrow functions
|
|
65
|
+
!object.async && // Does not apply to async/generator functions
|
|
66
|
+
!object.generator;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
transform(
|
|
63
|
-
|
|
64
|
-
var isGlobal = contextObject.type == "Program";
|
|
65
|
-
var value = (0, _probability.ComputeProbabilityMap)(this.options.rgf, x => x, isGlobal);
|
|
69
|
+
transform(object, parents) {
|
|
70
|
+
var _this$options$lock, _object$id;
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
// Discard getter/setter methods
|
|
73
|
+
if (parents[0].type === "Property" && parents[0].value === object) {
|
|
74
|
+
if (parents[0].method || parents[0].kind === "get" || parents[0].kind === "set") {
|
|
68
75
|
return;
|
|
69
76
|
}
|
|
77
|
+
} // Discard class methods
|
|
70
78
|
|
|
71
|
-
var collect = [];
|
|
72
|
-
var queue = [];
|
|
73
|
-
var names = new Map();
|
|
74
|
-
var referenceSignatures = {};
|
|
75
|
-
var definingNodes = new Map();
|
|
76
|
-
(0, _traverse.walk)(contextObject, contextParents, (object, parents) => {
|
|
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
79
|
|
|
80
|
+
if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
|
|
81
|
+
return;
|
|
82
|
+
} // Avoid applying to the countermeasures function
|
|
87
83
|
|
|
88
|
-
if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
|
|
89
|
-
return;
|
|
90
|
-
} // Avoid applying to the countermeasures function
|
|
91
84
|
|
|
85
|
+
if (typeof ((_this$options$lock = this.options.lock) === null || _this$options$lock === void 0 ? void 0 : _this$options$lock.countermeasures) === "string") {
|
|
86
|
+
// function countermeasures(){...}
|
|
87
|
+
if (object.type === "FunctionDeclaration" && object.id.type === "Identifier" && object.id.name === this.options.lock.countermeasures) {
|
|
88
|
+
return;
|
|
89
|
+
} // var countermeasures = function(){...}
|
|
92
90
|
|
|
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
91
|
|
|
92
|
+
if (parents[0].type === "VariableDeclarator" && parents[0].init === object && parents[0].id.type === "Identifier" && parents[0].id.name === this.options.lock.countermeasures) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
} // Check user option
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
|
|
98
|
+
if (!(0, _probability.ComputeProbabilityMap)(this.options.rgf, x => x, object === null || object === void 0 ? void 0 : (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name)) return; // Discard functions that use 'eval' function
|
|
99
|
+
|
|
100
|
+
if (object.$requiresEval) return; // Check for 'this', 'arguments' (not allowed!)
|
|
101
|
+
|
|
102
|
+
var isIllegal = false;
|
|
103
|
+
(0, _traverse.walk)(object, parents, (o, p) => {
|
|
104
|
+
if (o.type === "ThisExpression" || o.type === "Super" || o.type === "Identifier" && o.name === "arguments") {
|
|
105
|
+
isIllegal = true;
|
|
106
|
+
return "EXIT";
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
if (isIllegal) return;
|
|
110
|
+
return () => {
|
|
111
|
+
// Make sure function is 'reference-less'
|
|
112
|
+
var definedMap = new Map();
|
|
113
|
+
var isReferenceLess = true;
|
|
114
|
+
var identifierPreventingTransformation;
|
|
115
|
+
(0, _traverse.walk)(object, parents, (o, p) => {
|
|
116
|
+
if (o.type === "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
117
|
+
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
118
|
+
|
|
119
|
+
if (!info.spec.isReferenced) {
|
|
120
|
+
return;
|
|
103
121
|
}
|
|
104
122
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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) => {
|
|
120
|
-
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
121
|
-
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
122
|
-
|
|
123
|
-
if (!info.spec.isReferenced) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
123
|
+
if (info.spec.isDefined) {
|
|
124
|
+
// Add to defined map
|
|
125
|
+
var definingContext = (0, _insert.getDefiningContext)(o, p);
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
if (!definedMap.has(definingContext)) {
|
|
128
|
+
definedMap.set(definingContext, new Set([o.name]));
|
|
129
|
+
} else {
|
|
130
|
+
definedMap.get(definingContext).add(o.name);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
// This approach is dirty and does not account for hoisted FunctionDeclarations
|
|
134
|
+
var isDefinedAbove = false;
|
|
135
|
+
|
|
136
|
+
for (var pNode of p) {
|
|
137
|
+
if (definedMap.has(pNode)) {
|
|
138
|
+
if (definedMap.get(pNode).has(o.name)) {
|
|
139
|
+
isDefinedAbove = true;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
131
142
|
}
|
|
132
143
|
}
|
|
133
144
|
|
|
134
|
-
if (
|
|
135
|
-
|
|
145
|
+
if (!isDefinedAbove) {
|
|
146
|
+
isReferenceLess = false;
|
|
147
|
+
identifierPreventingTransformation = o.name;
|
|
148
|
+
return "EXIT";
|
|
136
149
|
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
(0, _traverse.walk)(object.params, [object, ...parents], fnTraverser);
|
|
140
|
-
(0, _traverse.walk)(object.body, [object, ...parents], fnTraverser);
|
|
141
|
-
|
|
142
|
-
if (!isBound) {
|
|
143
|
-
var _object$id;
|
|
144
|
-
|
|
145
|
-
defined.forEach(identifier => {
|
|
146
|
-
referenced.delete(identifier);
|
|
147
|
-
});
|
|
148
|
-
object.params.forEach(param => {
|
|
149
|
-
referenced.delete(param.name);
|
|
150
|
-
});
|
|
151
|
-
collect.push({
|
|
152
|
-
location: [object, parents],
|
|
153
|
-
references: referenced,
|
|
154
|
-
name: (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name
|
|
155
|
-
});
|
|
156
150
|
}
|
|
157
151
|
}
|
|
158
|
-
});
|
|
152
|
+
}); // This function is not 'reference-less', cannot be RGF'd
|
|
153
|
+
|
|
154
|
+
if (!isReferenceLess) {
|
|
155
|
+
if (object.id) {
|
|
156
|
+
var _object$id2;
|
|
157
|
+
|
|
158
|
+
this.log("".concat(object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name, "() cannot be transformed because of ").concat(identifierPreventingTransformation));
|
|
159
|
+
}
|
|
159
160
|
|
|
160
|
-
if (!collect.length) {
|
|
161
161
|
return;
|
|
162
|
-
}
|
|
162
|
+
} // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
|
|
163
|
+
// RGF runs early and needs completed code before converting to a string.
|
|
164
|
+
// (^ the variables haven't been renamed yet)
|
|
163
165
|
|
|
164
|
-
var miss = 0;
|
|
165
|
-
var start = collect.length * 2;
|
|
166
|
-
|
|
167
|
-
while (true) {
|
|
168
|
-
var hit = false;
|
|
169
|
-
collect.forEach(_ref => {
|
|
170
|
-
let {
|
|
171
|
-
name,
|
|
172
|
-
references: references1,
|
|
173
|
-
location: location1
|
|
174
|
-
} = _ref;
|
|
175
|
-
|
|
176
|
-
if (!references1.size && name) {
|
|
177
|
-
collect.forEach(o => {
|
|
178
|
-
if (o.location[0] !== location1[0] && o.references.size && o.references.delete(name)) {
|
|
179
|
-
// console.log(collect);
|
|
180
|
-
hit = true;
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
166
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
167
|
+
var obfuscator = new _obfuscator.default({ ...this.options,
|
|
168
|
+
stringEncoding: false,
|
|
169
|
+
compact: true
|
|
170
|
+
});
|
|
191
171
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
172
|
+
if (obfuscator.options.lock) {
|
|
173
|
+
delete obfuscator.options.lock.countermeasures;
|
|
195
174
|
}
|
|
196
175
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
176
|
+
var transforms = obfuscator.array.filter(x => x.priority > this.priority);
|
|
177
|
+
var embeddedFunctionName = this.getPlaceholder();
|
|
178
|
+
var embeddedFunction = {
|
|
179
|
+
type: "FunctionDeclaration",
|
|
180
|
+
id: (0, _gen.Identifier)(embeddedFunctionName),
|
|
181
|
+
body: (0, _gen.BlockStatement)([...object.body.body]),
|
|
182
|
+
params: object.params,
|
|
183
|
+
async: false,
|
|
184
|
+
generator: false
|
|
185
|
+
};
|
|
186
|
+
var tree = {
|
|
187
|
+
type: "Program",
|
|
188
|
+
body: [embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedFunctionName), (0, _gen.Literal)("apply"), true), [(0, _gen.ThisExpression)(), (0, _gen.Identifier)("arguments")]))]
|
|
189
|
+
};
|
|
190
|
+
transforms.forEach(transform => {
|
|
191
|
+
transform.apply(tree);
|
|
210
192
|
});
|
|
193
|
+
var toString = (0, _compiler.compileJsSync)(tree, obfuscator.options); // new Function(code)
|
|
211
194
|
|
|
212
|
-
|
|
213
|
-
return;
|
|
214
|
-
} // An array containing all the function declarations
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
var referenceArray = "_" + (0, _random.getRandomString)(10);
|
|
218
|
-
(0, _traverse.walk)(contextObject, contextParents, (o, p) => {
|
|
219
|
-
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name)) {
|
|
220
|
-
var index = names.get(o.name);
|
|
221
|
-
|
|
222
|
-
if (typeof index === "number") {
|
|
223
|
-
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
224
|
-
|
|
225
|
-
if (info.spec.isReferenced && !info.spec.isDefined) {
|
|
226
|
-
var location = (0, _identifiers.getDefiningIdentifier)(o, p);
|
|
227
|
-
|
|
228
|
-
if (location) {
|
|
229
|
-
var pointingTo = location[0];
|
|
230
|
-
var shouldBe = definingNodes.get(o.name); // console.log(pointingTo, shouldBe);
|
|
231
|
-
|
|
232
|
-
if (pointingTo == shouldBe) {
|
|
233
|
-
this.log(o.name, "->", "".concat(referenceArray, "[").concat(index, "]"));
|
|
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)( // clone() is required!
|
|
245
|
-
(0, _gen.CallExpression)((0, _insert.clone)(memberExpression), [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), (0, _insert.clone)(memberExpression));
|
|
246
|
-
this.replace(o, conditionalExpression);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
var arrayExpression = (0, _gen.ArrayExpression)([]);
|
|
255
|
-
var variableDeclaration = (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)((0, _gen.Identifier)(referenceArray), arrayExpression)]);
|
|
256
|
-
(0, _insert.prepend)(contextObject, variableDeclaration);
|
|
257
|
-
queue.forEach(_ref2 => {
|
|
258
|
-
var _object$id2;
|
|
259
|
-
|
|
260
|
-
let [object, parents] = _ref2;
|
|
261
|
-
var name = object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name;
|
|
262
|
-
var signature = referenceSignatures[names.get(name)];
|
|
263
|
-
var embeddedName = name || this.getPlaceholder(); // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
|
|
264
|
-
// RGF runs early and needs completed code before converting to a string.
|
|
265
|
-
// (^ the variables haven't been renamed yet)
|
|
266
|
-
|
|
267
|
-
var obfuscator = new _obfuscator.default({ ...this.options,
|
|
268
|
-
rgf: false,
|
|
269
|
-
globalVariables: new Set([...this.options.globalVariables, referenceArray]),
|
|
270
|
-
lock: {
|
|
271
|
-
integrity: false
|
|
272
|
-
},
|
|
273
|
-
eval: false,
|
|
274
|
-
stringEncoding: false
|
|
275
|
-
});
|
|
276
|
-
var transforms = obfuscator.array.filter(x => x.priority > this.priority);
|
|
277
|
-
var embeddedFunction = { ...object,
|
|
278
|
-
type: "FunctionDeclaration",
|
|
279
|
-
id: (0, _gen.Identifier)(embeddedName)
|
|
280
|
-
};
|
|
281
|
-
var tree = {
|
|
282
|
-
type: "Program",
|
|
283
|
-
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)]))]
|
|
284
|
-
};
|
|
285
|
-
tree.__hiddenDeclarations = (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(referenceArray));
|
|
286
|
-
tree.__hiddenDeclarations.hidden = true;
|
|
287
|
-
tree.__hiddenDeclarations.declarations[0].id.hidden = true;
|
|
288
|
-
transforms.forEach(transform => {
|
|
289
|
-
transform.apply(tree);
|
|
290
|
-
}); // Find eval callbacks
|
|
291
|
-
|
|
292
|
-
(0, _traverse.default)(tree, (o, p) => {
|
|
293
|
-
if (o.$eval) {
|
|
294
|
-
return () => {
|
|
295
|
-
o.$eval(o, p);
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
var toString = (0, _compiler.compileJsSync)(tree, this.options);
|
|
300
|
-
var newFunction = (0, _gen.NewExpression)((0, _gen.Identifier)("Function"), [(0, _gen.Literal)(referenceArray), (0, _gen.Literal)(toString)]);
|
|
195
|
+
var newFunctionExpression = (0, _gen.NewExpression)((0, _gen.Identifier)("Function"), [(0, _gen.Literal)(toString)]); // The index where this function is placed in the array
|
|
301
196
|
|
|
302
|
-
|
|
303
|
-
if (!signature) {
|
|
304
|
-
return fn;
|
|
305
|
-
} // This code marks the function object with a unique property
|
|
197
|
+
var newFunctionExpressionIndex = this.arrayExpressionElements.length; // Add it to the array
|
|
306
198
|
|
|
199
|
+
this.arrayExpressionElements.push(newFunctionExpression); // The member expression to retrieve this function
|
|
307
200
|
|
|
308
|
-
|
|
309
|
-
|
|
201
|
+
var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.Literal)(newFunctionExpressionIndex), true); // Replace based on type
|
|
202
|
+
// (1) Function Declaration:
|
|
203
|
+
// - Replace body with call to new function
|
|
310
204
|
|
|
311
|
-
|
|
312
|
-
|
|
205
|
+
if (object.type === "FunctionDeclaration") {
|
|
206
|
+
object.body = (0, _gen.BlockStatement)([(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)(memberExpression, (0, _gen.Literal)("apply"), true), [(0, _gen.ThisExpression)(), (0, _gen.Identifier)("arguments")]))]); // The parameters are no longer needed ('arguments' is used to capture them)
|
|
313
207
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
});
|
|
208
|
+
object.params = [];
|
|
209
|
+
return;
|
|
210
|
+
} // (2) Function Expression:
|
|
211
|
+
// - Replace expression with member expression pointing to new function
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
if (object.type === "FunctionExpression") {
|
|
215
|
+
this.replace(object, memberExpression);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
325
218
|
};
|
|
326
219
|
}
|
|
327
220
|
|
package/dist/transforms/stack.js
CHANGED
|
@@ -25,6 +25,10 @@ var _random = require("../util/random");
|
|
|
25
25
|
|
|
26
26
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
27
27
|
|
|
28
|
+
var _constants = require("../constants");
|
|
29
|
+
|
|
30
|
+
var _functionLength = require("../templates/functionLength");
|
|
31
|
+
|
|
28
32
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
29
33
|
|
|
30
34
|
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; }
|
|
@@ -35,6 +39,8 @@ class Stack extends _transform.default {
|
|
|
35
39
|
|
|
36
40
|
_defineProperty(this, "mangledExpressionsMade", void 0);
|
|
37
41
|
|
|
42
|
+
_defineProperty(this, "functionLengthName", void 0);
|
|
43
|
+
|
|
38
44
|
this.mangledExpressionsMade = 0;
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -103,7 +109,13 @@ class Stack extends _transform.default {
|
|
|
103
109
|
setSubscript(param.name, subscripts.size);
|
|
104
110
|
});
|
|
105
111
|
var startingSize = subscripts.size;
|
|
112
|
+
var isIllegal = false;
|
|
106
113
|
(0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
|
|
114
|
+
if (o.type === "Identifier" && o.name === "arguments") {
|
|
115
|
+
isIllegal = true;
|
|
116
|
+
return "EXIT";
|
|
117
|
+
}
|
|
118
|
+
|
|
107
119
|
if (o.type == "Identifier") {
|
|
108
120
|
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
109
121
|
|
|
@@ -118,6 +130,10 @@ class Stack extends _transform.default {
|
|
|
118
130
|
illegal.add(o.name);
|
|
119
131
|
}
|
|
120
132
|
|
|
133
|
+
if (o.name.startsWith(_constants.noRenameVariablePrefix)) {
|
|
134
|
+
illegal.add(o.name);
|
|
135
|
+
}
|
|
136
|
+
|
|
121
137
|
if (info.isClauseParameter || info.isFunctionParameter || (0, _insert.isForInitialize)(o, p)) {
|
|
122
138
|
// this.log(
|
|
123
139
|
// o.name + " is illegal due to clause parameter/function parameter"
|
|
@@ -180,6 +196,7 @@ class Stack extends _transform.default {
|
|
|
180
196
|
}
|
|
181
197
|
}
|
|
182
198
|
});
|
|
199
|
+
if (isIllegal) return;
|
|
183
200
|
illegal.forEach(name => {
|
|
184
201
|
defined.delete(name);
|
|
185
202
|
referenced.delete(name);
|
|
@@ -352,11 +369,35 @@ class Stack extends _transform.default {
|
|
|
352
369
|
|
|
353
370
|
Object.keys(rotateNodes).forEach((index, i) => {
|
|
354
371
|
object.body.body.splice(parseInt(index) + i, 0, rotateNodes[index]);
|
|
355
|
-
}); //
|
|
372
|
+
}); // Preserve function.length property
|
|
373
|
+
|
|
374
|
+
var originalFunctionLength = (0, _insert.computeFunctionLength)(object.params); // Set the params for this function to be the stack array
|
|
356
375
|
|
|
357
376
|
object.params = [(0, _gen.RestElement)((0, _gen.Identifier)(stackName))]; // Ensure the array is correct length
|
|
358
377
|
|
|
359
378
|
(0, _insert.prepend)(object.body, (0, _template.default)("".concat(stackName, "[\"length\"] = ").concat(startingSize)).single());
|
|
379
|
+
|
|
380
|
+
if (originalFunctionLength !== 0) {
|
|
381
|
+
if (!this.functionLengthName) {
|
|
382
|
+
this.functionLengthName = this.getPlaceholder();
|
|
383
|
+
(0, _insert.prepend)(parents[parents.length - 1] || object, _functionLength.FunctionLengthTemplate.single({
|
|
384
|
+
name: this.functionLengthName
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (object.type === "FunctionDeclaration") {
|
|
389
|
+
var body = parents[0];
|
|
390
|
+
|
|
391
|
+
if (Array.isArray(body)) {
|
|
392
|
+
var index = body.indexOf(object);
|
|
393
|
+
body.splice(index, 0, (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [(0, _gen.Identifier)(object.id.name), (0, _gen.Literal)(originalFunctionLength)])));
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
(0, _assert.ok)(object.type === "FunctionExpression" || object.type === "ArrowFunctionExpression");
|
|
397
|
+
this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [{ ...object
|
|
398
|
+
}, (0, _gen.Literal)(originalFunctionLength)]));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
360
401
|
};
|
|
361
402
|
}
|
|
362
403
|
|
|
@@ -195,7 +195,7 @@ class Transform {
|
|
|
195
195
|
getPlaceholder() {
|
|
196
196
|
const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 10).toString(10)).join("");
|
|
197
197
|
|
|
198
|
-
return
|
|
198
|
+
return _constants.placeholderVariablePrefix + genRanHex(10);
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
201
|
* Returns an independent name generator with it's own counter.
|
package/dist/util/gen.js
CHANGED
|
@@ -175,6 +175,7 @@ function BreakStatement(label) {
|
|
|
175
175
|
|
|
176
176
|
function Property(key, value) {
|
|
177
177
|
let computed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
178
|
+
let kind = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "init";
|
|
178
179
|
|
|
179
180
|
if (!key) {
|
|
180
181
|
throw new Error("key is undefined");
|
|
@@ -189,7 +190,7 @@ function Property(key, value) {
|
|
|
189
190
|
key: key,
|
|
190
191
|
computed: computed,
|
|
191
192
|
value: value,
|
|
192
|
-
kind:
|
|
193
|
+
kind: kind,
|
|
193
194
|
method: false,
|
|
194
195
|
shorthand: false
|
|
195
196
|
};
|
package/dist/util/identifiers.js
CHANGED
|
@@ -42,6 +42,22 @@ function validateChain(object, parents) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
function objectPatternCheck(object, parents) {
|
|
47
|
+
var objectPatternIndex = parents.findIndex(x => x.type === "ObjectPattern");
|
|
48
|
+
|
|
49
|
+
if (objectPatternIndex == -1) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var property = parents[objectPatternIndex].properties.find(property => parents[objectPatternIndex - 2] === property);
|
|
54
|
+
|
|
55
|
+
if (property.key === (parents[objectPatternIndex - 3] || object)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
45
61
|
/**
|
|
46
62
|
* Returns detailed information about the given Identifier node.
|
|
47
63
|
* @param object
|
|
@@ -70,11 +86,29 @@ function getIdentifierInfo(object, parents) {
|
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
var varIndex = parents.findIndex(x => x.type == "VariableDeclarator");
|
|
73
|
-
var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration");
|
|
89
|
+
var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration") && objectPatternCheck(object, parents); // Assignment pattern check!
|
|
90
|
+
|
|
91
|
+
if (isVariableDeclaration) {
|
|
92
|
+
var slicedParents = parents.slice(0, varIndex - 1);
|
|
93
|
+
var i = 0;
|
|
94
|
+
|
|
95
|
+
for (var parent of slicedParents) {
|
|
96
|
+
var childNode = slicedParents[i - 1] || object;
|
|
97
|
+
|
|
98
|
+
if (parent.type === "AssignmentPattern" && parent.right === childNode) {
|
|
99
|
+
isVariableDeclaration = false;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
i++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
74
107
|
var forIndex = parents.findIndex(x => x.type == "ForStatement");
|
|
75
108
|
var isForInitializer = forIndex != -1 && parents[forIndex].init == (parents[forIndex - 1] || object);
|
|
76
109
|
var functionIndex = parents.findIndex(x => (0, _insert.isFunction)(x));
|
|
77
110
|
var isFunctionDeclaration = functionIndex != -1 && parents[functionIndex].type == "FunctionDeclaration" && parents[functionIndex].id == object;
|
|
111
|
+
var isNamedFunctionExpression = functionIndex != -1 && parents[functionIndex].type === "FunctionExpression" && parents[functionIndex].id === object;
|
|
78
112
|
var isAFunctionParameter = isFunctionParameter(object, parents);
|
|
79
113
|
var isClauseParameter = false; // Special case for Catch clauses
|
|
80
114
|
|
|
@@ -90,7 +124,7 @@ function getIdentifierInfo(object, parents) {
|
|
|
90
124
|
var isFunctionCall = parent.callee == object; // NewExpression and CallExpression
|
|
91
125
|
|
|
92
126
|
var assignmentIndex = parents.findIndex(p => p.type === "AssignmentExpression");
|
|
93
|
-
var isAssignmentLeft = assignmentIndex !== -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object);
|
|
127
|
+
var isAssignmentLeft = assignmentIndex !== -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object) && objectPatternCheck(object, parents);
|
|
94
128
|
var isAssignmentValue = assignmentIndex !== -1 && parents[assignmentIndex].right === (parents[assignmentIndex - 1] || object);
|
|
95
129
|
var isUpdateExpression = parent.type == "UpdateExpression";
|
|
96
130
|
var isClassDeclaration = (parent.type == "ClassDeclaration" || parent.type == "ClassExpression") && parent.id == object;
|
|
@@ -227,7 +261,7 @@ function getIdentifierInfo(object, parents) {
|
|
|
227
261
|
/**
|
|
228
262
|
* Is the Identifier defined, i.e a variable declaration, function declaration, parameter, or class definition
|
|
229
263
|
*/
|
|
230
|
-
isDefined: isVariableDeclaration || isFunctionDeclaration || isAFunctionParameter || isClassDeclaration || isClauseParameter || isMethodDefinition || isImportSpecifier,
|
|
264
|
+
isDefined: isVariableDeclaration || isFunctionDeclaration || isNamedFunctionExpression || isAFunctionParameter || isClassDeclaration || isClauseParameter || isMethodDefinition || isImportSpecifier,
|
|
231
265
|
|
|
232
266
|
/**
|
|
233
267
|
* Is the Identifier modified, either by an `AssignmentExpression` or `UpdateExpression`
|