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.
Files changed (143) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +346 -165
  4. package/dist/constants.js +6 -2
  5. package/dist/index.js +9 -21
  6. package/dist/obfuscator.js +19 -31
  7. package/dist/options.js +5 -5
  8. package/dist/order.js +1 -3
  9. package/dist/presets.js +6 -7
  10. package/dist/probability.js +2 -4
  11. package/dist/templates/bufferToString.js +13 -0
  12. package/dist/templates/crash.js +3 -3
  13. package/dist/templates/es5.js +18 -0
  14. package/dist/templates/functionLength.js +16 -0
  15. package/dist/transforms/calculator.js +77 -21
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
  18. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  19. package/dist/transforms/deadCode.js +33 -25
  20. package/dist/transforms/dispatcher.js +8 -4
  21. package/dist/transforms/es5/antiDestructuring.js +2 -0
  22. package/dist/transforms/es5/es5.js +31 -34
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
  24. package/dist/transforms/finalizer.js +82 -0
  25. package/dist/transforms/flatten.js +229 -148
  26. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  27. package/dist/transforms/identifier/globalConcealing.js +10 -83
  28. package/dist/transforms/identifier/movedDeclarations.js +35 -88
  29. package/dist/transforms/identifier/renameVariables.js +124 -59
  30. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  31. package/dist/transforms/lock/lock.js +0 -37
  32. package/dist/transforms/minify.js +60 -57
  33. package/dist/transforms/opaquePredicates.js +1 -1
  34. package/dist/transforms/preparation/preparation.js +2 -2
  35. package/dist/transforms/preparation.js +231 -0
  36. package/dist/transforms/renameLabels.js +1 -1
  37. package/dist/transforms/rgf.js +139 -247
  38. package/dist/transforms/stack.js +128 -26
  39. package/dist/transforms/string/encoding.js +150 -179
  40. package/dist/transforms/string/stringCompression.js +14 -15
  41. package/dist/transforms/string/stringConcealing.js +25 -8
  42. package/dist/transforms/string/stringEncoding.js +13 -24
  43. package/dist/transforms/transform.js +12 -19
  44. package/dist/traverse.js +24 -10
  45. package/dist/util/gen.js +17 -1
  46. package/dist/util/identifiers.js +37 -3
  47. package/dist/util/insert.js +35 -4
  48. package/dist/util/random.js +15 -0
  49. package/docs/ControlFlowFlattening.md +595 -0
  50. package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
  51. package/{Integrity.md → docs/Integrity.md} +2 -2
  52. package/docs/RGF.md +419 -0
  53. package/package.json +5 -5
  54. package/src/constants.ts +3 -0
  55. package/src/index.ts +2 -2
  56. package/src/obfuscator.ts +19 -31
  57. package/src/options.ts +14 -103
  58. package/src/order.ts +1 -5
  59. package/src/presets.ts +6 -7
  60. package/src/probability.ts +2 -3
  61. package/src/templates/bufferToString.ts +68 -0
  62. package/src/templates/crash.ts +15 -19
  63. package/src/templates/es5.ts +131 -0
  64. package/src/templates/functionLength.ts +14 -0
  65. package/src/transforms/calculator.ts +122 -59
  66. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  67. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
  68. package/src/transforms/deadCode.ts +383 -26
  69. package/src/transforms/dispatcher.ts +9 -4
  70. package/src/transforms/es5/antiDestructuring.ts +2 -0
  71. package/src/transforms/es5/es5.ts +32 -77
  72. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
  73. package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
  74. package/src/transforms/flatten.ts +357 -300
  75. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  76. package/src/transforms/identifier/globalConcealing.ts +14 -103
  77. package/src/transforms/identifier/movedDeclarations.ts +49 -102
  78. package/src/transforms/identifier/renameVariables.ts +149 -78
  79. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  80. package/src/transforms/lock/lock.ts +1 -42
  81. package/src/transforms/minify.ts +91 -75
  82. package/src/transforms/opaquePredicates.ts +2 -2
  83. package/src/transforms/preparation.ts +238 -0
  84. package/src/transforms/renameLabels.ts +2 -2
  85. package/src/transforms/rgf.ts +213 -405
  86. package/src/transforms/stack.ts +156 -36
  87. package/src/transforms/string/encoding.ts +115 -212
  88. package/src/transforms/string/stringCompression.ts +27 -18
  89. package/src/transforms/string/stringConcealing.ts +39 -9
  90. package/src/transforms/string/stringEncoding.ts +18 -18
  91. package/src/transforms/transform.ts +21 -23
  92. package/src/traverse.ts +23 -4
  93. package/src/types.ts +2 -1
  94. package/src/util/gen.ts +28 -3
  95. package/src/util/identifiers.ts +43 -2
  96. package/src/util/insert.ts +38 -3
  97. package/src/util/random.ts +13 -0
  98. package/test/code/Cash.test.ts +1 -1
  99. package/test/code/Dynamic.test.ts +12 -10
  100. package/test/code/ES6.src.js +146 -0
  101. package/test/code/ES6.test.ts +28 -2
  102. package/test/index.test.ts +2 -1
  103. package/test/probability.test.ts +44 -0
  104. package/test/templates/template.test.ts +1 -1
  105. package/test/transforms/antiTooling.test.ts +22 -0
  106. package/test/transforms/calculator.test.ts +40 -0
  107. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
  108. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  109. package/test/transforms/deadCode.test.ts +66 -15
  110. package/test/transforms/dispatcher.test.ts +20 -1
  111. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  112. package/test/transforms/flatten.test.ts +399 -86
  113. package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
  114. package/test/transforms/identifier/renameVariables.test.ts +119 -0
  115. package/test/transforms/lock/antiDebug.test.ts +2 -2
  116. package/test/transforms/lock/lock.test.ts +1 -48
  117. package/test/transforms/minify.test.ts +104 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +261 -381
  120. package/test/transforms/stack.test.ts +143 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +82 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/identifiers.test.ts +113 -1
  127. package/test/util/insert.test.ts +57 -3
  128. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  129. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  130. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  131. package/src/transforms/eval.ts +0 -89
  132. package/src/transforms/hideInitializingCode.ts +0 -432
  133. package/src/transforms/identifier/nameRecycling.ts +0 -280
  134. package/src/transforms/label.ts +0 -64
  135. package/src/transforms/preparation/nameConflicts.ts +0 -102
  136. package/src/transforms/preparation/preparation.ts +0 -176
  137. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  138. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  139. package/test/transforms/eval.test.ts +0 -131
  140. package/test/transforms/hideInitializingCode.test.ts +0 -336
  141. package/test/transforms/identifier/nameRecycling.test.ts +0 -205
  142. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  143. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -15,9 +15,7 @@ var _order = require("../order");
15
15
 
16
16
  var _probability = require("../probability");
17
17
 
18
- var _template = _interopRequireDefault(require("../templates/template"));
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,286 +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 (0, _insert.isVarContext)(object) && object.type !== "ArrowFunctionExpression";
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(contextObject, contextParents) {
63
- return () => {
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
- if (value !== "all" && !isGlobal) {
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
- 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
- }
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
- var defined = new Set(),
106
- referenced = new Set();
107
- var isBound = false;
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
- if (info.spec.isDefined && (0, _insert.getDefiningContext)(o, p) === object) {
128
- defined.add(o.name);
129
- } else {
130
- referenced.add(o.name);
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 (o.type == "ThisExpression" || o.type == "Super") {
135
- isBound = true;
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
- if (hit) {
187
- miss = 0;
188
- } else {
189
- miss++;
190
- }
167
+ var obfuscator = new _obfuscator.default({ ...this.options,
168
+ stringEncoding: false,
169
+ compact: true
170
+ });
191
171
 
192
- if (miss > start) {
193
- break;
194
- }
172
+ if (obfuscator.options.lock) {
173
+ delete obfuscator.options.lock.countermeasures;
195
174
  }
196
175
 
197
- queue = [];
198
- collect.forEach(o => {
199
- if (!o.references.size) {
200
- var [object, parents] = o.location;
201
- queue.push([object, parents]);
202
-
203
- if (object.type == "FunctionDeclaration" && typeof object.id.name === "string") {
204
- var index = names.size;
205
- names.set(object.id.name, index);
206
- referenceSignatures[index] = (0, _random.getRandomString)(10);
207
- definingNodes.set(object.id.name, object.id);
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
- if (!queue.length) {
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"))]))]), 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
- hideInitializingCode: false,
275
- stringEncoding: false
276
- });
277
- var transforms = Object.values(obfuscator.transforms).filter(x => x.priority > this.priority);
278
- var embeddedFunction = { ...object,
279
- type: "FunctionDeclaration",
280
- id: (0, _gen.Identifier)(embeddedName)
281
- };
282
- var tree = {
283
- type: "Program",
284
- body: [embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedName), (0, _gen.Literal)("call"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.SpreadElement)((0, _template.default)("Array.prototype.slice.call(arguments, 1)").single().expression)]))]
285
- };
286
- tree.__hiddenDeclarations = (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(referenceArray));
287
- tree.__hiddenDeclarations.hidden = true;
288
- tree.__hiddenDeclarations.declarations[0].id.hidden = true;
289
- transforms.forEach(transform => {
290
- transform.apply(tree);
291
- }); // Find eval callbacks
292
-
293
- (0, _traverse.default)(tree, (o, p) => {
294
- if (o.$eval) {
295
- return () => {
296
- o.$eval(o, p);
297
- };
298
- }
299
- });
300
- var toString = (0, _compiler.compileJsSync)(tree, this.options);
301
- 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
302
196
 
303
- function applySignature(fn) {
304
- if (!signature) {
305
- return fn;
306
- } // This code marks the function object with a unique property
197
+ var newFunctionExpressionIndex = this.arrayExpressionElements.length; // Add it to the array
307
198
 
199
+ this.arrayExpressionElements.push(newFunctionExpression); // The member expression to retrieve this function
308
200
 
309
- return (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("fn", fn)), (0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.MemberExpression)((0, _gen.Identifier)("fn"), (0, _gen.Literal)(signature), true), (0, _gen.Literal)(true))), (0, _gen.ReturnStatement)((0, _gen.Identifier)("fn"))]), []);
310
- }
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
311
204
 
312
- if (object.type === "FunctionDeclaration") {
313
- arrayExpression.elements[names.get(name)] = applySignature(newFunction);
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)
314
207
 
315
- if (Array.isArray(parents[0])) {
316
- parents[0].splice(parents[0].indexOf(object), 1);
317
- } else {
318
- this.error(new Error("Error deleting function declaration: " + parents.map(x => x.type).join(",")));
319
- }
320
- } else {
321
- // The wrapper function passes the reference array around
322
- var wrapperFunction = (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)(newFunction, (0, _gen.Literal)("call"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]);
323
- this.replace(object, applySignature(wrapperFunction));
324
- }
325
- });
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
+ }
326
218
  };
327
219
  }
328
220