js-confuser 1.5.9 → 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/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- 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 +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _order = require("../order");
|
|
9
|
+
|
|
10
|
+
var _gen = require("../util/gen");
|
|
11
|
+
|
|
12
|
+
var _stringEncoding = _interopRequireDefault(require("./string/stringEncoding"));
|
|
13
|
+
|
|
14
|
+
var _transform = _interopRequireDefault(require("./transform"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
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; }
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The Finalizer is the last transformation before the code is ready to be generated.
|
|
22
|
+
*
|
|
23
|
+
* Hexadecimal numbers:
|
|
24
|
+
* - Convert integer literals into `Identifier` nodes with the name being a hexadecimal number
|
|
25
|
+
*
|
|
26
|
+
* BigInt support:
|
|
27
|
+
* - Convert BigInt literals into `Identifier` nodes with the name being the raw BigInt string value + "n"
|
|
28
|
+
*
|
|
29
|
+
* String Encoding:
|
|
30
|
+
* - Convert String literals into `Identifier` nodes with the name being a unicode escaped string
|
|
31
|
+
*/
|
|
32
|
+
class Finalizer extends _transform.default {
|
|
33
|
+
constructor(o) {
|
|
34
|
+
super(o, _order.ObfuscateOrder.Finalizer);
|
|
35
|
+
|
|
36
|
+
_defineProperty(this, "stringEncoding", void 0);
|
|
37
|
+
|
|
38
|
+
this.stringEncoding = new _stringEncoding.default(o);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
isNumberLiteral(object) {
|
|
42
|
+
return object.type === "Literal" && typeof object.value === "number" && Math.floor(object.value) === object.value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
isBigIntLiteral(object) {
|
|
46
|
+
return object.type === "Literal" && typeof object.value === "bigint";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
match(object, parents) {
|
|
50
|
+
return object.type === "Literal";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
transform(object, parents) {
|
|
54
|
+
// Hexadecimal Numbers
|
|
55
|
+
if (this.options.hexadecimalNumbers && this.isNumberLiteral(object)) {
|
|
56
|
+
return () => {
|
|
57
|
+
// Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
|
|
58
|
+
// This code handles it regardless
|
|
59
|
+
var isNegative = object.value < 0;
|
|
60
|
+
var hex = Math.abs(object.value).toString(16);
|
|
61
|
+
var newStr = (isNegative ? "-" : "") + "0x" + hex;
|
|
62
|
+
this.replace(object, (0, _gen.Identifier)(newStr));
|
|
63
|
+
};
|
|
64
|
+
} // BigInt support
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if (this.isBigIntLiteral(object)) {
|
|
68
|
+
// https://github.com/MichaelXF/js-confuser/issues/79
|
|
69
|
+
return () => {
|
|
70
|
+
// Use an Identifier with the raw string
|
|
71
|
+
this.replace(object, (0, _gen.Identifier)(object.raw));
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (this.options.stringEncoding && this.stringEncoding.match(object, parents)) {
|
|
76
|
+
return this.stringEncoding.transform(object, parents);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
exports.default = Finalizer;
|
|
@@ -11,7 +11,7 @@ var _constants = require("../constants");
|
|
|
11
11
|
|
|
12
12
|
var _order = require("../order");
|
|
13
13
|
|
|
14
|
-
var _traverse =
|
|
14
|
+
var _traverse = require("../traverse");
|
|
15
15
|
|
|
16
16
|
var _gen = require("../util/gen");
|
|
17
17
|
|
|
@@ -23,71 +23,87 @@ var _random = require("../util/random");
|
|
|
23
23
|
|
|
24
24
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
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); }
|
|
26
|
+
var _functionLength = require("../templates/functionLength");
|
|
29
27
|
|
|
30
|
-
function
|
|
28
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
29
|
|
|
32
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; }
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
|
-
*
|
|
33
|
+
* Flatten takes functions and isolates them from their original scope, and brings it to the top level of the program.
|
|
34
|
+
*
|
|
35
|
+
* An additional `flatObject` parameter is passed in, giving access to the original scoped variables.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
37
|
+
* The `flatObject` uses `get` and `set` properties to allow easy an AST transformation:
|
|
38
38
|
*
|
|
39
39
|
* ```js
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* // Input
|
|
41
|
+
* function myFunction(myParam){
|
|
42
|
+
* modified = true;
|
|
43
|
+
* if(reference) {
|
|
44
|
+
*
|
|
45
|
+
* }
|
|
46
|
+
* ...
|
|
47
|
+
* console.log(myParam);
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* // Output
|
|
51
|
+
* function myFunction_flat([myParam], flatObject){
|
|
52
|
+
* flatObject["set_modified"] = true;
|
|
53
|
+
* if(flatObject["get_reference"]) {
|
|
54
|
+
*
|
|
55
|
+
* }
|
|
56
|
+
* ...
|
|
57
|
+
* console.log(myParam)
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* function myFunction(){
|
|
61
|
+
* var flatObject = {
|
|
62
|
+
* set set_modified(v) { modified = v }
|
|
63
|
+
* get get_reference() { return reference }
|
|
64
|
+
* }
|
|
65
|
+
* return myFunction_flat([...arguments], flatObject)
|
|
42
66
|
* }
|
|
43
67
|
* ```
|
|
44
68
|
*
|
|
45
69
|
* Flatten is used to make functions eligible for the RGF transformation.
|
|
70
|
+
*
|
|
71
|
+
* - `myFunction_flat` is now eligible because it does not rely on outside scoped variables
|
|
46
72
|
*/
|
|
47
73
|
class Flatten extends _transform.default {
|
|
74
|
+
// Array of FunctionDeclaration nodes
|
|
48
75
|
constructor(o) {
|
|
49
76
|
super(o, _order.ObfuscateOrder.Flatten);
|
|
50
77
|
|
|
78
|
+
_defineProperty(this, "isDebug", false);
|
|
79
|
+
|
|
51
80
|
_defineProperty(this, "definedNames", void 0);
|
|
52
81
|
|
|
53
82
|
_defineProperty(this, "flattenedFns", void 0);
|
|
54
83
|
|
|
55
84
|
_defineProperty(this, "gen", void 0);
|
|
56
85
|
|
|
86
|
+
_defineProperty(this, "functionLengthName", void 0);
|
|
87
|
+
|
|
57
88
|
this.definedNames = new Map();
|
|
58
89
|
this.flattenedFns = [];
|
|
59
|
-
this.gen = this.getGenerator();
|
|
90
|
+
this.gen = this.getGenerator("mangled");
|
|
91
|
+
|
|
92
|
+
if (this.isDebug) {
|
|
93
|
+
console.warn("Flatten debug mode");
|
|
94
|
+
}
|
|
60
95
|
}
|
|
61
96
|
|
|
62
97
|
apply(tree) {
|
|
63
|
-
(0, _traverse.default)(tree, (o, p) => {
|
|
64
|
-
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
65
|
-
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
66
|
-
|
|
67
|
-
if (info.spec.isReferenced) {
|
|
68
|
-
if (info.spec.isDefined) {
|
|
69
|
-
var c = (0, _insert.getVarContext)(o, p);
|
|
70
|
-
|
|
71
|
-
if (c) {
|
|
72
|
-
if (!this.definedNames.has(c)) {
|
|
73
|
-
this.definedNames.set(c, new Set([o.name]));
|
|
74
|
-
} else {
|
|
75
|
-
this.definedNames.get(c).add(o.name);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
98
|
super.apply(tree);
|
|
83
99
|
|
|
84
100
|
if (this.flattenedFns.length) {
|
|
85
|
-
(0, _insert.prepend)(tree,
|
|
101
|
+
(0, _insert.prepend)(tree, ...this.flattenedFns);
|
|
86
102
|
}
|
|
87
103
|
}
|
|
88
104
|
|
|
89
105
|
match(object, parents) {
|
|
90
|
-
return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.generator && !object.params.find(x => x.type !== "Identifier");
|
|
106
|
+
return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.$requiresEval && !object.generator && !object.params.find(x => x.type !== "Identifier");
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
transform(object, parents) {
|
|
@@ -101,7 +117,7 @@ class Flatten extends _transform.default {
|
|
|
101
117
|
} // Don't change getter/setter methods
|
|
102
118
|
|
|
103
119
|
|
|
104
|
-
if (parents[0].type === "Property" && parents[0].value === object && parents[0].kind !== "init") {
|
|
120
|
+
if (parents[0].type === "Property" && parents[0].value === object && (parents[0].kind !== "init" || parents[0].method)) {
|
|
105
121
|
return;
|
|
106
122
|
}
|
|
107
123
|
}
|
|
@@ -111,76 +127,54 @@ class Flatten extends _transform.default {
|
|
|
111
127
|
var currentFnName = object.type === "FunctionDeclaration" ? (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name : ((_parents$ = parents[0]) === null || _parents$ === void 0 ? void 0 : _parents$.type) === "VariableDeclarator" && ((_parents$0$id = parents[0].id) === null || _parents$0$id === void 0 ? void 0 : _parents$0$id.type) === "Identifier" && ((_parents$0$id2 = parents[0].id) === null || _parents$0$id2 === void 0 ? void 0 : _parents$0$id2.name);
|
|
112
128
|
|
|
113
129
|
if (((_parents$2 = parents[0]) === null || _parents$2 === void 0 ? void 0 : _parents$2.type) === "Property" && (_parents$3 = parents[0]) !== null && _parents$3 !== void 0 && _parents$3.key) {
|
|
114
|
-
var _parents$4, _parents$4$key
|
|
130
|
+
var _parents$4, _parents$4$key;
|
|
115
131
|
|
|
116
|
-
currentFnName = currentFnName || String((
|
|
132
|
+
currentFnName = currentFnName || String((_parents$4 = parents[0]) === null || _parents$4 === void 0 ? void 0 : (_parents$4$key = _parents$4.key) === null || _parents$4$key === void 0 ? void 0 : _parents$4$key.name);
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
if (!currentFnName) currentFnName = "unnamed";
|
|
120
|
-
var
|
|
121
|
-
var references = new Set();
|
|
122
|
-
var modified = new Set();
|
|
136
|
+
var definedMap = new Map();
|
|
123
137
|
var illegal = new Set();
|
|
124
138
|
var isIllegal = false;
|
|
125
|
-
var
|
|
126
|
-
parents.forEach(x => {
|
|
127
|
-
var set = this.definedNames.get(x);
|
|
128
|
-
|
|
129
|
-
if (set) {
|
|
130
|
-
set.forEach(name => definedAbove.add(name));
|
|
131
|
-
}
|
|
132
|
-
});
|
|
139
|
+
var identifierNodes = [];
|
|
133
140
|
(0, _traverse.walk)(object, parents, (o, p) => {
|
|
134
|
-
if (
|
|
135
|
-
|
|
141
|
+
if (o.type === "Identifier" && o.name === "arguments" || o.type === "UnaryExpression" && o.operator === "delete" || o.type == "ThisExpression" || o.type == "Super" || o.type == "MetaProperty") {
|
|
142
|
+
isIllegal = true;
|
|
143
|
+
return "EXIT";
|
|
136
144
|
}
|
|
137
145
|
|
|
138
|
-
if (o.type == "Identifier" && !this.options.globalVariables.has(o.name) && !_constants.reservedIdentifiers.has(o.name)) {
|
|
146
|
+
if (o.type == "Identifier" && o !== object.id && !this.options.globalVariables.has(o.name) && !_constants.reservedIdentifiers.has(o.name)) {
|
|
139
147
|
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
140
148
|
|
|
141
149
|
if (!info.spec.isReferenced) {
|
|
142
150
|
return;
|
|
143
151
|
}
|
|
144
152
|
|
|
145
|
-
if (o.
|
|
153
|
+
if (info.spec.isExported || o.name.startsWith(_constants.noRenameVariablePrefix)) {
|
|
146
154
|
illegal.add(o.name);
|
|
147
|
-
|
|
148
|
-
defined.add(o.name);
|
|
149
|
-
} else if (info.spec.isModified) {
|
|
150
|
-
modified.add(o.name);
|
|
151
|
-
} else {
|
|
152
|
-
references.add(o.name);
|
|
155
|
+
return;
|
|
153
156
|
}
|
|
154
|
-
}
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return "EXIT";
|
|
159
|
-
}
|
|
158
|
+
if (info.spec.isDefined) {
|
|
159
|
+
var definingContext = (0, _insert.getDefiningContext)(o, p);
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
161
|
+
if (!definedMap.has(definingContext)) {
|
|
162
|
+
definedMap.set(definingContext, new Set([o.name]));
|
|
163
|
+
} else {
|
|
164
|
+
definedMap.get(definingContext).add(o.name);
|
|
165
|
+
}
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return "EXIT";
|
|
171
|
-
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
172
169
|
|
|
173
|
-
|
|
174
|
-
isIllegal = true;
|
|
175
|
-
return "EXIT";
|
|
176
|
-
}
|
|
170
|
+
var isDefined = p.find(x => definedMap.has(x) && definedMap.get(x).has(o.name));
|
|
177
171
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
172
|
+
if (!isDefined) {
|
|
173
|
+
identifierNodes.push([o, p, info]);
|
|
174
|
+
}
|
|
181
175
|
}
|
|
182
176
|
|
|
183
|
-
if (o.type == "
|
|
177
|
+
if (o.type == "TryStatement") {
|
|
184
178
|
isIllegal = true;
|
|
185
179
|
return "EXIT";
|
|
186
180
|
}
|
|
@@ -194,82 +188,169 @@ class Flatten extends _transform.default {
|
|
|
194
188
|
return;
|
|
195
189
|
}
|
|
196
190
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
modified.delete(name);
|
|
200
|
-
}); // console.log(object.id.name, illegal, references);
|
|
191
|
+
var newFnName = this.getPlaceholder() + "_flat_" + currentFnName;
|
|
192
|
+
var flatObjectName = this.getPlaceholder() + "_flat_object";
|
|
201
193
|
|
|
202
|
-
|
|
194
|
+
const getFlatObjectMember = propertyName => {
|
|
195
|
+
return (0, _gen.MemberExpression)((0, _gen.Identifier)(flatObjectName), (0, _gen.Literal)(propertyName), true);
|
|
196
|
+
};
|
|
203
197
|
|
|
204
|
-
|
|
205
|
-
|
|
198
|
+
var getterPropNames = Object.create(null);
|
|
199
|
+
var setterPropNames = Object.create(null);
|
|
200
|
+
var typeofPropNames = Object.create(null);
|
|
201
|
+
var callPropNames = Object.create(null);
|
|
202
|
+
|
|
203
|
+
for (var [o, p, info] of identifierNodes) {
|
|
204
|
+
var identifierName = o.name;
|
|
205
|
+
if (p.find(x => definedMap.has(x) && definedMap.get(x).has(identifierName))) continue;
|
|
206
|
+
(0, _assert.ok)(!info.spec.isDefined);
|
|
207
|
+
var type = info.spec.isModified ? "setter" : "getter";
|
|
208
|
+
|
|
209
|
+
switch (type) {
|
|
210
|
+
case "setter":
|
|
211
|
+
var setterPropName = setterPropNames[identifierName];
|
|
212
|
+
|
|
213
|
+
if (typeof setterPropName === "undefined") {
|
|
214
|
+
// No getter function made yet, make it (Try to re-use getter name if available)
|
|
215
|
+
setterPropName = getterPropNames[identifierName] || (this.isDebug ? "set_" + identifierName : this.gen.generate());
|
|
216
|
+
setterPropNames[identifierName] = setterPropName;
|
|
217
|
+
} // If an update expression, ensure a getter function is also available. Ex: a++
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if (p[0].type === "UpdateExpression") {
|
|
221
|
+
getterPropNames[identifierName] = setterPropName;
|
|
222
|
+
} else {
|
|
223
|
+
// If assignment on member expression, ensure a getter function is also available: Ex. myObject.property = ...
|
|
224
|
+
var assignmentIndex = p.findIndex(x => x.type === "AssignmentExpression");
|
|
225
|
+
|
|
226
|
+
if (assignmentIndex !== -1 && p[assignmentIndex].left.type !== "Identifier") {
|
|
227
|
+
getterPropNames[identifierName] = setterPropName;
|
|
228
|
+
}
|
|
229
|
+
} // calls flatObject.set_identifier_value(newValue)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
this.replace(o, getFlatObjectMember(setterPropName));
|
|
233
|
+
break;
|
|
234
|
+
|
|
235
|
+
case "getter":
|
|
236
|
+
var getterPropName = getterPropNames[identifierName];
|
|
237
|
+
|
|
238
|
+
if (typeof getterPropName === "undefined") {
|
|
239
|
+
// No getter function made yet, make it (Try to re-use setter name if available)
|
|
240
|
+
getterPropName = setterPropNames[identifierName] || (this.isDebug ? "get_" + identifierName : this.gen.generate());
|
|
241
|
+
getterPropNames[identifierName] = getterPropName;
|
|
242
|
+
} // Typeof expression check
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
if (p[0].type === "UnaryExpression" && p[0].operator === "typeof" && p[0].argument === o) {
|
|
246
|
+
var typeofPropName = typeofPropNames[identifierName];
|
|
247
|
+
|
|
248
|
+
if (typeof typeofPropName === "undefined") {
|
|
249
|
+
// No typeof getter function made yet, make it (Don't re-use getter/setter names)
|
|
250
|
+
typeofPropName = this.isDebug ? "get_typeof_" + identifierName : this.gen.generate();
|
|
251
|
+
typeofPropNames[identifierName] = typeofPropName;
|
|
252
|
+
} // Replace the entire unary expression not just the identifier node
|
|
253
|
+
// calls flatObject.get_typeof_identifier()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
this.replace(p[0], getFlatObjectMember(typeofPropName));
|
|
257
|
+
break;
|
|
258
|
+
} // Bound call-expression check
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
if (p[0].type === "CallExpression" && p[0].callee === o) {
|
|
262
|
+
var callPropName = callPropNames[identifierName];
|
|
263
|
+
|
|
264
|
+
if (typeof callPropName === "undefined") {
|
|
265
|
+
callPropName = this.isDebug ? "call_" + identifierName : this.gen.generate();
|
|
266
|
+
callPropNames[identifierName] = callPropName;
|
|
267
|
+
} // Replace the entire call expression not just the identifier node
|
|
268
|
+
// calls flatObject.call_identifier(...arguments)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
this.replace(p[0], (0, _gen.CallExpression)(getFlatObjectMember(callPropName), p[0].arguments));
|
|
272
|
+
break;
|
|
273
|
+
} // calls flatObject.get_identifier_value()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
this.replace(o, getFlatObjectMember(getterPropName));
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
} // Create the getter and setter functions
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
var flatObjectProperties = []; // Getter functions
|
|
283
|
+
|
|
284
|
+
for (var identifierName in getterPropNames) {
|
|
285
|
+
var getterPropName = getterPropNames[identifierName];
|
|
286
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(getterPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.Identifier)(identifierName))]), true, "get"));
|
|
287
|
+
} // Get typeof functions
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
for (var identifierName in typeofPropNames) {
|
|
291
|
+
var typeofPropName = typeofPropNames[identifierName];
|
|
292
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(typeofPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)(identifierName)))]), true, "get"));
|
|
293
|
+
} // Call functions
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
for (var identifierName in callPropNames) {
|
|
297
|
+
var callPropName = callPropNames[identifierName];
|
|
298
|
+
var argumentsName = this.getPlaceholder();
|
|
299
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(callPropName), (0, _gen.FunctionExpression)([(0, _gen.RestElement)((0, _gen.Identifier)(argumentsName))], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(identifierName), [(0, _gen.SpreadElement)((0, _gen.Identifier)(argumentsName))]))]), true));
|
|
300
|
+
} // Setter functions
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
for (var identifierName in setterPropNames) {
|
|
304
|
+
var setterPropName = setterPropNames[identifierName];
|
|
305
|
+
var newValueParameterName = this.getPlaceholder();
|
|
306
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(setterPropName), (0, _gen.FunctionExpression)([(0, _gen.Identifier)(newValueParameterName)], [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(identifierName), (0, _gen.Identifier)(newValueParameterName)))]), true, "set"));
|
|
206
307
|
}
|
|
207
308
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
var
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
(0, _insert.getBlockBody)(object.body).push((0, _gen.ReturnStatement)());
|
|
218
|
-
(0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
|
|
219
|
-
return () => {
|
|
220
|
-
// Change return statements from
|
|
221
|
-
// return (argument)
|
|
222
|
-
// to
|
|
223
|
-
// return [ [modifiedRefs], ]
|
|
224
|
-
if (o.type == "ReturnStatement" && (0, _insert.getVarContext)(o, p) === object) {
|
|
225
|
-
var returnObject = (0, _gen.ObjectExpression)(output.map(outputName => (0, _gen.Property)((0, _gen.Literal)(newOutputNames[outputName]), (0, _gen.Identifier)(outputName), true)));
|
|
226
|
-
|
|
227
|
-
if (o.argument && !(o.argument.type == "Identifier" && o.argument.name == "undefined")) {
|
|
228
|
-
returnObject.properties.push((0, _gen.Property)((0, _gen.Literal)(returnOutputName), (0, _insert.clone)(o.argument), true));
|
|
229
|
-
}
|
|
309
|
+
if (!this.isDebug) {
|
|
310
|
+
(0, _random.shuffle)(flatObjectProperties);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
var newBody = (0, _insert.getBlockBody)(object.body); // Remove 'use strict' directive
|
|
314
|
+
|
|
315
|
+
if (newBody.length > 0 && newBody[0].directive) {
|
|
316
|
+
newBody.shift();
|
|
317
|
+
}
|
|
230
318
|
|
|
231
|
-
|
|
319
|
+
var newFunctionDeclaration = (0, _gen.FunctionDeclaration)(newFnName, [(0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(flatObjectName)], newBody);
|
|
320
|
+
newFunctionDeclaration.async = !!object.async;
|
|
321
|
+
newFunctionDeclaration.generator = false;
|
|
322
|
+
this.flattenedFns.push(newFunctionDeclaration);
|
|
323
|
+
var argumentsName = this.getPlaceholder(); // newFn.call([...arguments], flatObject)
|
|
324
|
+
|
|
325
|
+
var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(newFnName), [(0, _gen.Identifier)(argumentsName), (0, _gen.Identifier)(flatObjectName)]);
|
|
326
|
+
var newObjectBody = [// var flatObject = { get(), set() };
|
|
327
|
+
(0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(flatObjectName, (0, _gen.ObjectExpression)(flatObjectProperties))]), (0, _gen.ReturnStatement)(newFunctionDeclaration.async ? (0, _gen.AwaitExpression)(callExpression) : callExpression)];
|
|
328
|
+
object.body = (0, _gen.BlockStatement)(newObjectBody); // Preserve function.length property
|
|
329
|
+
|
|
330
|
+
var originalFunctionLength = (0, _insert.computeFunctionLength)(object.params);
|
|
331
|
+
object.params = [(0, _gen.SpreadElement)((0, _gen.Identifier)(argumentsName))];
|
|
332
|
+
|
|
333
|
+
if (originalFunctionLength !== 0) {
|
|
334
|
+
if (!this.functionLengthName) {
|
|
335
|
+
this.functionLengthName = this.getPlaceholder();
|
|
336
|
+
(0, _insert.prepend)(parents[parents.length - 1] || object, _functionLength.FunctionLengthTemplate.single({
|
|
337
|
+
name: this.functionLengthName
|
|
338
|
+
}));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (object.type === "FunctionDeclaration") {
|
|
342
|
+
var body = parents[0];
|
|
343
|
+
|
|
344
|
+
if (Array.isArray(body)) {
|
|
345
|
+
var index = body.indexOf(object);
|
|
346
|
+
body.splice(index + 1, 0, (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [(0, _gen.Identifier)(object.id.name), (0, _gen.Literal)(originalFunctionLength)])));
|
|
232
347
|
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
var property = (0, _gen.Property)((0, _gen.Identifier)(newName), newFunctionExpression, false);
|
|
240
|
-
property.kind = "set";
|
|
241
|
-
this.flattenedFns.push((0, _gen.VariableDeclarator)(newName, newFunctionExpression));
|
|
242
|
-
var newParamNodes = object.params.map(() => (0, _gen.Identifier)(this.getPlaceholder())); // result.pop()
|
|
243
|
-
|
|
244
|
-
var getOutputMemberExpression = outputName => (0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(propName), true), (0, _gen.Literal)(outputName), true); // newFn.call([...refs], ...arguments, resultObject)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(newName), [(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), (0, _gen.ArrayExpression)([...newParamNodes]), (0, _gen.Identifier)(resultName)]);
|
|
248
|
-
var newObjectBody = [// var resultObject = {};
|
|
249
|
-
(0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(resultName, (0, _gen.ObjectExpression)([]))]), (0, _gen.ExpressionStatement)(newFunctionExpression.async ? (0, _gen.AwaitExpression)(callExpression) : callExpression)];
|
|
250
|
-
var outputReversed = [...output].reverse(); // realVar
|
|
251
|
-
|
|
252
|
-
outputReversed.forEach(outputName => {
|
|
253
|
-
newObjectBody.push((0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(outputName), getOutputMemberExpression(newOutputNames[outputName]))));
|
|
254
|
-
}); // DECOY STATEMENTS
|
|
255
|
-
|
|
256
|
-
var decoyKey = this.gen.generate();
|
|
257
|
-
var decoyNodes = [// if (result.random) throw result.prop.random
|
|
258
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ThrowStatement)((0, _gen.NewExpression)((0, _gen.Identifier)("Error"), [getOutputMemberExpression(this.gen.generate())]))]), // if (result.random) return true;
|
|
259
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Literal)(true))]), // if (result.random) return result;
|
|
260
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), // if (result.random) return result.random;
|
|
261
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(decoyKey), true), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(decoyKey), true))]), // if(result.random1) return result.random2;
|
|
262
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true))]), // if(result.random) return flatFn;
|
|
263
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(newName))]), // if(result.random) flatFn = undefined;
|
|
264
|
-
(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(this.gen.generate()), true), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(newName), (0, _gen.Identifier)("undefined")))]), // if(!result) return;
|
|
265
|
-
(0, _gen.IfStatement)((0, _gen.UnaryExpression)("!", (0, _gen.Identifier)(resultName)), [(0, _gen.ReturnStatement)()])].filter(() => Math.random() > 0.25); // if (result.output) return result.output.returnValue;
|
|
266
|
-
// this is the real return statement, it is always added
|
|
267
|
-
|
|
268
|
-
decoyNodes.push((0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Literal)(propName), true), [(0, _gen.ReturnStatement)(getOutputMemberExpression(returnOutputName))]));
|
|
269
|
-
(0, _random.shuffle)(decoyNodes);
|
|
270
|
-
newObjectBody.push(...decoyNodes);
|
|
271
|
-
object.body = (0, _gen.BlockStatement)(newObjectBody);
|
|
272
|
-
object.params = newParamNodes;
|
|
348
|
+
} else {
|
|
349
|
+
(0, _assert.ok)(object.type === "FunctionExpression");
|
|
350
|
+
this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [{ ...object
|
|
351
|
+
}, (0, _gen.Literal)(originalFunctionLength)]));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
273
354
|
};
|
|
274
355
|
}
|
|
275
356
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _constants = require("../../constants");
|
|
9
|
+
|
|
10
|
+
var _identifiers = require("../../util/identifiers");
|
|
11
|
+
|
|
12
|
+
var _transform = _interopRequireDefault(require("../transform"));
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
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; }
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Global Analysis is responsible for finding all the global variables used in the code.
|
|
20
|
+
*
|
|
21
|
+
* A 'global variable' is one that is:
|
|
22
|
+
* - Referenced
|
|
23
|
+
* - Never defined or overridden
|
|
24
|
+
*/
|
|
25
|
+
class GlobalAnalysis extends _transform.default {
|
|
26
|
+
constructor(o) {
|
|
27
|
+
super(o);
|
|
28
|
+
|
|
29
|
+
_defineProperty(this, "notGlobals", void 0);
|
|
30
|
+
|
|
31
|
+
_defineProperty(this, "globals", void 0);
|
|
32
|
+
|
|
33
|
+
this.globals = Object.create(null);
|
|
34
|
+
this.notGlobals = new Set();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
match(object, parents) {
|
|
38
|
+
return object.type == "Identifier" && !_constants.reservedKeywords.has(object.name);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
transform(object, parents) {
|
|
42
|
+
// no touching `import()` or `import x from ...`
|
|
43
|
+
var importIndex = parents.findIndex(x => x.type == "ImportExpression" || x.type == "ImportDeclaration");
|
|
44
|
+
|
|
45
|
+
if (importIndex !== -1) {
|
|
46
|
+
if (parents[importIndex].source === (parents[importIndex - 1] || object)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
52
|
+
|
|
53
|
+
if (!info.spec.isReferenced) {
|
|
54
|
+
return;
|
|
55
|
+
} // Cannot be defined or overridden
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if (info.spec.isDefined || info.spec.isModified) {
|
|
59
|
+
delete this.globals[object.name];
|
|
60
|
+
this.notGlobals.add(object.name);
|
|
61
|
+
return;
|
|
62
|
+
} // Add to globals
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if (!this.notGlobals.has(object.name)) {
|
|
66
|
+
if (!this.globals[object.name]) {
|
|
67
|
+
this.globals[object.name] = [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.globals[object.name].push([object, parents]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var assignmentIndex = parents.findIndex(x => x.type == "AssignmentExpression");
|
|
74
|
+
var updateIndex = parents.findIndex(x => x.type == "UpdateExpression");
|
|
75
|
+
|
|
76
|
+
if (assignmentIndex != -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object) || updateIndex != -1) {
|
|
77
|
+
var memberIndex = parents.findIndex(x => x.type == "MemberExpression");
|
|
78
|
+
|
|
79
|
+
if (memberIndex == -1 || memberIndex > (assignmentIndex == -1 ? assignmentIndex : updateIndex)) {
|
|
80
|
+
delete this.globals[object.name];
|
|
81
|
+
this.notGlobals.add(object.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
exports.default = GlobalAnalysis;
|