js-confuser 1.7.1 → 1.7.3

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 (153) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/CHANGELOG.md +73 -0
  3. package/README.md +32 -31
  4. package/dist/compiler.js +2 -8
  5. package/dist/constants.js +22 -10
  6. package/dist/index.js +15 -30
  7. package/dist/obfuscator.js +15 -62
  8. package/dist/options.js +33 -40
  9. package/dist/order.js +4 -7
  10. package/dist/parser.js +5 -13
  11. package/dist/precedence.js +6 -8
  12. package/dist/presets.js +4 -6
  13. package/dist/probability.js +13 -24
  14. package/dist/templates/bufferToString.js +121 -5
  15. package/dist/templates/core.js +35 -0
  16. package/dist/templates/crash.js +22 -11
  17. package/dist/templates/es5.js +125 -6
  18. package/dist/templates/functionLength.js +24 -6
  19. package/dist/templates/globals.js +9 -0
  20. package/dist/templates/template.js +189 -43
  21. package/dist/transforms/antiTooling.js +26 -22
  22. package/dist/transforms/calculator.js +19 -55
  23. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +242 -333
  24. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  25. package/dist/transforms/deadCode.js +542 -31
  26. package/dist/transforms/dispatcher.js +112 -112
  27. package/dist/transforms/es5/antiClass.js +70 -44
  28. package/dist/transforms/es5/antiDestructuring.js +14 -38
  29. package/dist/transforms/es5/antiES6Object.js +39 -48
  30. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  31. package/dist/transforms/es5/antiTemplate.js +10 -19
  32. package/dist/transforms/es5/es5.js +7 -40
  33. package/dist/transforms/extraction/classExtraction.js +83 -0
  34. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  35. package/dist/transforms/extraction/objectExtraction.js +24 -56
  36. package/dist/transforms/finalizer.js +6 -20
  37. package/dist/transforms/flatten.js +51 -99
  38. package/dist/transforms/identifier/globalAnalysis.js +21 -26
  39. package/dist/transforms/identifier/globalConcealing.js +72 -56
  40. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  41. package/dist/transforms/identifier/renameVariables.js +36 -68
  42. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  43. package/dist/transforms/lock/antiDebug.js +20 -25
  44. package/dist/transforms/lock/integrity.js +53 -52
  45. package/dist/transforms/lock/lock.js +161 -126
  46. package/dist/transforms/minify.js +77 -108
  47. package/dist/transforms/opaquePredicates.js +12 -49
  48. package/dist/transforms/preparation.js +28 -49
  49. package/dist/transforms/renameLabels.js +5 -22
  50. package/dist/transforms/rgf.js +125 -72
  51. package/dist/transforms/shuffle.js +42 -47
  52. package/dist/transforms/stack.js +41 -98
  53. package/dist/transforms/string/encoding.js +76 -27
  54. package/dist/transforms/string/stringCompression.js +75 -68
  55. package/dist/transforms/string/stringConcealing.js +127 -135
  56. package/dist/transforms/string/stringEncoding.js +6 -26
  57. package/dist/transforms/string/stringSplitting.js +5 -30
  58. package/dist/transforms/transform.js +76 -104
  59. package/dist/traverse.js +11 -18
  60. package/dist/util/compare.js +27 -29
  61. package/dist/util/gen.js +32 -86
  62. package/dist/util/guard.js +5 -1
  63. package/dist/util/identifiers.js +9 -72
  64. package/dist/util/insert.js +27 -77
  65. package/dist/util/math.js +0 -3
  66. package/dist/util/object.js +3 -7
  67. package/dist/util/random.js +31 -36
  68. package/dist/util/scope.js +6 -3
  69. package/docs/Countermeasures.md +13 -6
  70. package/docs/Integrity.md +35 -28
  71. package/docs/RGF.md +6 -1
  72. package/docs/RenameVariables.md +116 -0
  73. package/docs/TamperProtection.md +100 -0
  74. package/docs/Template.md +117 -0
  75. package/package.json +3 -3
  76. package/src/constants.ts +17 -0
  77. package/src/index.ts +7 -5
  78. package/src/options.ts +60 -7
  79. package/src/order.ts +2 -2
  80. package/src/templates/bufferToString.ts +79 -11
  81. package/src/templates/core.ts +29 -0
  82. package/src/templates/crash.ts +6 -38
  83. package/src/templates/es5.ts +1 -1
  84. package/src/templates/functionLength.ts +21 -3
  85. package/src/templates/globals.ts +3 -0
  86. package/src/templates/template.ts +205 -46
  87. package/src/transforms/antiTooling.ts +33 -11
  88. package/src/transforms/calculator.ts +4 -2
  89. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +12 -5
  90. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  91. package/src/transforms/deadCode.ts +74 -42
  92. package/src/transforms/dispatcher.ts +99 -73
  93. package/src/transforms/es5/antiClass.ts +25 -12
  94. package/src/transforms/es5/antiDestructuring.ts +1 -1
  95. package/src/transforms/es5/antiES6Object.ts +2 -2
  96. package/src/transforms/es5/antiTemplate.ts +1 -1
  97. package/src/transforms/extraction/classExtraction.ts +168 -0
  98. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +11 -16
  99. package/src/transforms/extraction/objectExtraction.ts +4 -15
  100. package/src/transforms/flatten.ts +20 -5
  101. package/src/transforms/identifier/globalAnalysis.ts +18 -1
  102. package/src/transforms/identifier/globalConcealing.ts +119 -72
  103. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  104. package/src/transforms/identifier/renameVariables.ts +16 -1
  105. package/src/transforms/lock/antiDebug.ts +2 -2
  106. package/src/transforms/lock/integrity.ts +13 -11
  107. package/src/transforms/lock/lock.ts +122 -30
  108. package/src/transforms/minify.ts +28 -13
  109. package/src/transforms/opaquePredicates.ts +2 -2
  110. package/src/transforms/preparation.ts +16 -0
  111. package/src/transforms/rgf.ts +139 -12
  112. package/src/transforms/shuffle.ts +3 -3
  113. package/src/transforms/stack.ts +19 -4
  114. package/src/transforms/string/encoding.ts +88 -51
  115. package/src/transforms/string/stringCompression.ts +86 -17
  116. package/src/transforms/string/stringConcealing.ts +148 -118
  117. package/src/transforms/string/stringEncoding.ts +1 -2
  118. package/src/transforms/string/stringSplitting.ts +1 -2
  119. package/src/transforms/transform.ts +63 -46
  120. package/src/types.ts +2 -0
  121. package/src/util/compare.ts +39 -5
  122. package/src/util/gen.ts +10 -3
  123. package/src/util/guard.ts +10 -0
  124. package/src/util/insert.ts +17 -0
  125. package/src/util/random.ts +81 -1
  126. package/src/util/scope.ts +14 -2
  127. package/test/code/Cash.test.ts +94 -5
  128. package/test/code/StrictMode.src.js +65 -0
  129. package/test/code/StrictMode.test.js +37 -0
  130. package/test/compare.test.ts +62 -2
  131. package/test/options.test.ts +129 -55
  132. package/test/templates/template.test.ts +211 -1
  133. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  134. package/test/transforms/dispatcher.test.ts +55 -0
  135. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  136. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  137. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  138. package/test/transforms/identifier/globalConcealing.test.ts +89 -0
  139. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  140. package/test/transforms/identifier/renameVariables.test.ts +75 -1
  141. package/test/transforms/lock/tamperProtection.test.ts +336 -0
  142. package/test/transforms/minify.test.ts +37 -0
  143. package/test/transforms/rgf.test.ts +50 -0
  144. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  145. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  146. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  147. package/dist/transforms/eval.js +0 -84
  148. package/dist/transforms/hexadecimalNumbers.js +0 -63
  149. package/dist/transforms/hideInitializingCode.js +0 -270
  150. package/dist/transforms/identifier/nameRecycling.js +0 -218
  151. package/dist/transforms/label.js +0 -67
  152. package/dist/transforms/preparation/nameConflicts.js +0 -116
  153. package/dist/transforms/preparation/preparation.js +0 -188
@@ -4,15 +4,134 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.ES5Template = void 0;
7
-
8
7
  var _template = _interopRequireDefault(require("./template"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
9
  /**
13
10
  * Provides ES5 polyfills for Array methods
14
11
  *
15
12
  * Source: https://vanillajstoolkit.com/polyfills/
16
13
  */
17
- const ES5Template = (0, _template.default)("\nif (!Array.prototype.forEach) {\n Array.prototype.forEach = function forEach (callback, thisArg) {\n if (typeof callback !== 'function') {\n throw new TypeError(callback + ' is not a function');\n }\n var array = this;\n thisArg = thisArg || this;\n for (var i = 0, l = array.length; i !== l; ++i) {\n callback.call(thisArg, array[i], i, array);\n }\n };\n}\nif (!Array.prototype.filter)\n Array.prototype.filter = function(func, thisArg) {\n\t'use strict';\n\tif ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )\n\t\tthrow new TypeError();\n\n\tvar len = this.length >>> 0,\n\t\tres = new Array(len), // preallocate array\n\t\tt = this, c = 0, i = -1;\n\tif (thisArg === undefined)\n\t while (++i !== len)\n\t\t// checks to see if the key was set\n\t\tif (i in this)\n\t\t if (func(t[i], i, t))\n\t\t\tres[c++] = t[i];\n\telse\n\t while (++i !== len)\n\t\t// checks to see if the key was set\n\t\tif (i in this)\n\t\t if (func.call(thisArg, t[i], i, t))\n\t\t\tres[c++] = t[i];\n\n\tres.length = c; // shrink down array to proper size\n\treturn res;\n};\nif (!Array.prototype.map) {\n Array.prototype.map = function(callback, thisArg) {\n var T, A, k;\n\n if (this == null) {\n throw new TypeError('this is null or not defined');\n }\n\n // 1. Let O be the result of calling ToObject passing the |this|\n // value as the argument.\n var O = Object(this);\n\n // 2. Let lenValue be the result of calling the Get internal\n // method of O with the argument \"length\".\n // 3. Let len be ToUint32(lenValue).\n var len = O.length >>> 0;\n\n // 4. If IsCallable(callback) is false, throw a TypeError exception.\n // See: http://es5.github.com/#x9.11\n if (typeof callback !== 'function') {\n throw new TypeError(callback + ' is not a function');\n }\n\n // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 1) {\n T = arguments[1];\n }\n\n // 6. Let A be a new array created as if by the expression new Array(len)\n // where Array is the standard built-in constructor with that name and\n // len is the value of len.\n A = new Array(len);\n\n // 7. Let k be 0\n k = 0;\n\n // 8. Repeat, while k < len\n while (k < len) {\n\n var kValue, mappedValue;\n\n // a. Let Pk be ToString(k).\n // This is implicit for LHS operands of the in operator\n // b. Let kPresent be the result of calling the HasProperty internal\n // method of O with argument Pk.\n // This step can be combined with c\n // c. If kPresent is true, then\n if (k in O) {\n\n // i. Let kValue be the result of calling the Get internal\n // method of O with argument Pk.\n kValue = O[k];\n\n // ii. Let mappedValue be the result of calling the Call internal\n // method of callback with T as the this value and argument\n // list containing kValue, k, and O.\n mappedValue = callback.call(T, kValue, k, O);\n\n // iii. Call the DefineOwnProperty internal method of A with arguments\n // Pk, Property Descriptor\n // { Value: mappedValue,\n // Writable: true,\n // Enumerable: true,\n // Configurable: true },\n // and false.\n\n // In browsers that support Object.defineProperty, use the following:\n // Object.defineProperty(A, k, {\n // value: mappedValue,\n // writable: true,\n // enumerable: true,\n // configurable: true\n // });\n\n // For best browser support, use the following:\n A[k] = mappedValue;\n }\n // d. Increase k by 1.\n k++;\n }\n\n // 9. return A\n return A;\n };\n}\n");
18
- exports.ES5Template = ES5Template;
14
+ const ES5Template = exports.ES5Template = new _template.default(`
15
+ if (!Array.prototype.forEach) {
16
+ Array.prototype.forEach = function forEach (callback, thisArg) {
17
+ if (typeof callback !== 'function') {
18
+ throw new TypeError(callback + ' is not a function');
19
+ }
20
+ var array = this;
21
+ thisArg = thisArg || this;
22
+ for (var i = 0, l = array.length; i !== l; ++i) {
23
+ callback.call(thisArg, array[i], i, array);
24
+ }
25
+ };
26
+ }
27
+ if (!Array.prototype.filter)
28
+ Array.prototype.filter = function(func, thisArg) {
29
+ 'use strict';
30
+ if ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )
31
+ throw new TypeError();
32
+
33
+ var len = this.length >>> 0,
34
+ res = new Array(len), // preallocate array
35
+ t = this, c = 0, i = -1;
36
+ if (thisArg === undefined)
37
+ while (++i !== len)
38
+ // checks to see if the key was set
39
+ if (i in this)
40
+ if (func(t[i], i, t))
41
+ res[c++] = t[i];
42
+ else
43
+ while (++i !== len)
44
+ // checks to see if the key was set
45
+ if (i in this)
46
+ if (func.call(thisArg, t[i], i, t))
47
+ res[c++] = t[i];
48
+
49
+ res.length = c; // shrink down array to proper size
50
+ return res;
51
+ };
52
+ if (!Array.prototype.map) {
53
+ Array.prototype.map = function(callback, thisArg) {
54
+ var T, A, k;
55
+
56
+ if (this == null) {
57
+ throw new TypeError('this is null or not defined');
58
+ }
59
+
60
+ // 1. Let O be the result of calling ToObject passing the |this|
61
+ // value as the argument.
62
+ var O = Object(this);
63
+
64
+ // 2. Let lenValue be the result of calling the Get internal
65
+ // method of O with the argument "length".
66
+ // 3. Let len be ToUint32(lenValue).
67
+ var len = O.length >>> 0;
68
+
69
+ // 4. If IsCallable(callback) is false, throw a TypeError exception.
70
+ // See: http://es5.github.com/#x9.11
71
+ if (typeof callback !== 'function') {
72
+ throw new TypeError(callback + ' is not a function');
73
+ }
74
+
75
+ // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
76
+ if (arguments.length > 1) {
77
+ T = arguments[1];
78
+ }
79
+
80
+ // 6. Let A be a new array created as if by the expression new Array(len)
81
+ // where Array is the standard built-in constructor with that name and
82
+ // len is the value of len.
83
+ A = new Array(len);
84
+
85
+ // 7. Let k be 0
86
+ k = 0;
87
+
88
+ // 8. Repeat, while k < len
89
+ while (k < len) {
90
+
91
+ var kValue, mappedValue;
92
+
93
+ // a. Let Pk be ToString(k).
94
+ // This is implicit for LHS operands of the in operator
95
+ // b. Let kPresent be the result of calling the HasProperty internal
96
+ // method of O with argument Pk.
97
+ // This step can be combined with c
98
+ // c. If kPresent is true, then
99
+ if (k in O) {
100
+
101
+ // i. Let kValue be the result of calling the Get internal
102
+ // method of O with argument Pk.
103
+ kValue = O[k];
104
+
105
+ // ii. Let mappedValue be the result of calling the Call internal
106
+ // method of callback with T as the this value and argument
107
+ // list containing kValue, k, and O.
108
+ mappedValue = callback.call(T, kValue, k, O);
109
+
110
+ // iii. Call the DefineOwnProperty internal method of A with arguments
111
+ // Pk, Property Descriptor
112
+ // { Value: mappedValue,
113
+ // Writable: true,
114
+ // Enumerable: true,
115
+ // Configurable: true },
116
+ // and false.
117
+
118
+ // In browsers that support Object.defineProperty, use the following:
119
+ // Object.defineProperty(A, k, {
120
+ // value: mappedValue,
121
+ // writable: true,
122
+ // enumerable: true,
123
+ // configurable: true
124
+ // });
125
+
126
+ // For best browser support, use the following:
127
+ A[k] = mappedValue;
128
+ }
129
+ // d. Increase k by 1.
130
+ k++;
131
+ }
132
+
133
+ // 9. return A
134
+ return A;
135
+ };
136
+ }
137
+ `);
@@ -4,13 +4,31 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.FunctionLengthTemplate = void 0;
7
-
8
7
  var _template = _interopRequireDefault(require("./template"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
9
  /**
13
10
  * Helper function to set `function.length` property.
14
11
  */
15
- const FunctionLengthTemplate = (0, _template.default)("\nfunction {name}(functionObject, functionLength){\n Object[\"defineProperty\"](functionObject, \"length\", {\n \"value\": functionLength,\n \"configurable\": true\n });\n return functionObject;\n}\n");
16
- exports.FunctionLengthTemplate = FunctionLengthTemplate;
12
+ const FunctionLengthTemplate = exports.FunctionLengthTemplate = new _template.default(`
13
+ function {name}(functionObject, functionLength){
14
+ {ObjectDefineProperty}(functionObject, "length", {
15
+ "value": functionLength,
16
+ "configurable": true
17
+ });
18
+ return functionObject;
19
+ }
20
+ `, `
21
+ function {name}(functionObject, functionLength){
22
+ return {ObjectDefineProperty}(functionObject, "length", {
23
+ "value": functionLength,
24
+ "configurable": true
25
+ });
26
+ }
27
+ `, `
28
+ function {name}(functionObject, functionLength){
29
+ return {ObjectDefineProperty}["call"](null, functionObject, "length", {
30
+ "value": functionLength,
31
+ "configurable": true
32
+ });
33
+ }
34
+ `);
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ObjectDefineProperty = void 0;
7
+ var _template = _interopRequireDefault(require("./template"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ const ObjectDefineProperty = exports.ObjectDefineProperty = new _template.default(`Object["defineProperty"]`);
@@ -3,63 +3,209 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = Template;
7
-
6
+ exports.default = void 0;
8
7
  var _parser = require("../parser");
9
-
10
- function Template(template) {
11
- var neededVariables = 0;
12
-
13
- while (template.includes("{$".concat(neededVariables + 1, "}"))) {
14
- neededVariables++;
8
+ var _assert = require("assert");
9
+ var _random = require("../util/random");
10
+ var _traverse = _interopRequireDefault(require("../traverse"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
13
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
14
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
+ /**
16
+ * Templates provides an easy way to parse code snippets into AST subtrees.
17
+ *
18
+ * These AST subtrees can added to the obfuscated code, tailored with variable names.
19
+ *
20
+ * 1. Basic string interpolation
21
+ *
22
+ * ```js
23
+ * var Base64Template = new Template(`
24
+ * function {name}(str){
25
+ * return btoa(str)
26
+ * }
27
+ * `);
28
+ *
29
+ * var functionDeclaration = Base64Template.single({ name: "atob" });
30
+ * ```
31
+ *
32
+ * 2. AST subtree insertion
33
+ *
34
+ * ```js
35
+ * var Base64Template = new Template(`
36
+ * function {name}(str){
37
+ * {getWindow}
38
+ *
39
+ * return {getWindowName}btoa(str)
40
+ * }`)
41
+ *
42
+ * var functionDeclaration = Base64Template.single({
43
+ * name: "atob",
44
+ * getWindowName: "newWindow",
45
+ * getWindow: () => {
46
+ * return acorn.parse("var newWindow = {}").body[0];
47
+ * }
48
+ * });
49
+ * ```
50
+ *
51
+ * Here, the `getWindow` variable is a function that returns an AST subtree. This must be a `Node[]` array or Template.
52
+ * Optionally, the function can be replaced with just the `Node[]` array or Template if it's already computed.
53
+ *
54
+ * 3. Template subtree insertion
55
+ *
56
+ * ```js
57
+ * var NewWindowTemplate = new Template(`
58
+ * var newWindow = {};
59
+ * `);
60
+ *
61
+ * var Base64Template = new Template(`
62
+ * function {name}(str){
63
+ * {NewWindowTemplate}
64
+ *
65
+ * return newWindow.btoa(str)
66
+ * }`)
67
+ *
68
+ * var functionDeclaration = Base64Template.single({
69
+ * name: "atob",
70
+ * NewWindowTemplate: NewWindowTemplate
71
+ * });
72
+ * ```
73
+ */
74
+ class Template {
75
+ constructor() {
76
+ _defineProperty(this, "templates", void 0);
77
+ _defineProperty(this, "defaultVariables", void 0);
78
+ _defineProperty(this, "requiredVariables", void 0);
79
+ for (var _len = arguments.length, templates = new Array(_len), _key = 0; _key < _len; _key++) {
80
+ templates[_key] = arguments[_key];
81
+ }
82
+ this.templates = templates;
83
+ this.defaultVariables = Object.create(null);
84
+ this.requiredVariables = new Set();
85
+ this.findRequiredVariables();
15
86
  }
87
+ setDefaultVariables(defaultVariables) {
88
+ this.defaultVariables = defaultVariables;
89
+ return this;
90
+ }
91
+ findRequiredVariables() {
92
+ var matches = this.templates[0].match(/{[$A-z0-9_]+}/g);
93
+ if (matches !== null) {
94
+ matches.forEach(variable => {
95
+ var name = variable.slice(1, -1);
16
96
 
17
- var vars = Object.create(null);
18
- new Array(neededVariables + 1).fill(0).forEach((x, i) => {
19
- vars["\\$" + i] = "temp_" + i;
20
- });
21
-
22
- function fill(variables) {
23
- if (!variables) {
24
- variables = Object.create(null);
97
+ // $ variables are for default variables
98
+ if (name.startsWith("$")) {
99
+ throw new Error("Default variables are no longer supported.");
100
+ } else {
101
+ this.requiredVariables.add(name);
102
+ }
103
+ });
25
104
  }
105
+ }
26
106
 
27
- var cloned = template;
28
- var keys = { ...variables,
29
- ...vars
107
+ /**
108
+ * Interpolates the template with the given variables.
109
+ *
110
+ * Prepares the template string for AST parsing.
111
+ *
112
+ * @param variables
113
+ */
114
+ interpolateTemplate() {
115
+ let variables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
116
+ var allVariables = {
117
+ ...this.defaultVariables,
118
+ ...variables
30
119
  };
31
- Object.keys(keys).forEach(name => {
32
- var bracketName = "{" + name + "}";
33
- var value = keys[name] + "";
120
+
121
+ // Validate all variables were passed in
122
+ for (var requiredVariable of this.requiredVariables) {
123
+ if (typeof allVariables[requiredVariable] === "undefined") {
124
+ throw new Error(this.templates[0] + " missing variable: " + requiredVariable + " from " + JSON.stringify(allVariables));
125
+ }
126
+ }
127
+ var template = (0, _random.choice)(this.templates);
128
+ var output = template;
129
+ Object.keys(allVariables).forEach(name => {
130
+ var bracketName = "{" + name.replace("$", "\\$") + "}";
131
+ var value = allVariables[name] + "";
132
+ if (typeof allVariables[name] !== "string") {
133
+ value = name;
134
+ }
34
135
  var reg = new RegExp(bracketName, "g");
35
- cloned = cloned.replace(reg, value);
136
+ output = output.replace(reg, value);
36
137
  });
37
- return cloned;
138
+ return {
139
+ output,
140
+ template
141
+ };
38
142
  }
39
143
 
40
- function compile(variables) {
41
- var code = fill(variables);
144
+ /**
145
+ * Finds the variables in the AST and replaces them with the given values.
146
+ *
147
+ * Note: Mutates the AST.
148
+ * @param ast
149
+ * @param variables
150
+ */
151
+ interpolateAST(ast, variables) {
152
+ var allVariables = {
153
+ ...this.defaultVariables,
154
+ ...variables
155
+ };
156
+ var astNames = new Set(Object.keys(allVariables).filter(name => {
157
+ return typeof allVariables[name] !== "string";
158
+ }));
159
+ if (astNames.size === 0) return;
160
+ (0, _traverse.default)(ast, (o, p) => {
161
+ if (o.type === "Identifier" && allVariables[o.name]) {
162
+ return () => {
163
+ var value = allVariables[o.name];
164
+ (0, _assert.ok)(typeof value !== "string");
165
+ var insertNodes = typeof value === "function" ? value() : value;
166
+ if (insertNodes instanceof Template) {
167
+ insertNodes = insertNodes.compile(allVariables);
168
+ }
169
+ if (!Array.isArray(insertNodes)) {
170
+ // Replace with expression
42
171
 
172
+ Object.assign(o, insertNodes);
173
+ } else {
174
+ // Insert multiple statements/declarations
175
+ var expressionStatement = p[0];
176
+ var body = p[1];
177
+ (0, _assert.ok)(expressionStatement.type === "ExpressionStatement");
178
+ (0, _assert.ok)(Array.isArray(body));
179
+ var index = body.indexOf(expressionStatement);
180
+ body.splice(index, 1, ...insertNodes);
181
+ }
182
+ };
183
+ }
184
+ });
185
+ }
186
+ compile() {
187
+ let variables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
188
+ var {
189
+ output,
190
+ template
191
+ } = this.interpolateTemplate(variables);
192
+ var program;
43
193
  try {
44
- var program = (0, _parser.parseSnippet)(code);
45
- return program.body;
194
+ program = (0, _parser.parseSnippet)(output);
46
195
  } catch (e) {
47
- console.error(e);
48
- console.error(template);
49
- throw new Error("Template failed to parse");
196
+ throw new Error(output + "\n" + "Template failed to parse: " + e.message);
50
197
  }
198
+ this.interpolateAST(program, variables);
199
+ return program.body;
51
200
  }
52
-
53
- function single(variables) {
54
- var nodes = compile(variables);
201
+ single() {
202
+ let variables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
203
+ var nodes = this.compile(variables);
204
+ if (nodes.length !== 1) {
205
+ nodes = nodes.filter(node => node.type !== "EmptyStatement");
206
+ (0, _assert.ok)(nodes.length === 1, `Expected single node, got ${nodes.map(node => node.type).join(", ")}`);
207
+ }
55
208
  return nodes[0];
56
209
  }
57
-
58
- var obj = {
59
- fill,
60
- compile,
61
- single,
62
- source: template
63
- };
64
- return obj;
65
- }
210
+ }
211
+ exports.default = Template;
@@ -4,35 +4,41 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _order = require("../order");
9
-
8
+ var _template = _interopRequireDefault(require("../templates/template"));
10
9
  var _traverse = require("../traverse");
11
-
12
10
  var _gen = require("../util/gen");
13
-
14
- var _random = require("../util/random");
15
-
11
+ var _insert = require("../util/insert");
16
12
  var _transform = _interopRequireDefault(require("./transform"));
17
-
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
15
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
16
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
20
17
  // JsNice.org tries to separate sequence expressions into multiple lines, this stops that.
21
18
  class AntiTooling extends _transform.default {
22
19
  constructor(o) {
23
20
  super(o, _order.ObfuscateOrder.AntiTooling);
21
+ _defineProperty(this, "fnName", void 0);
22
+ }
23
+ apply(tree) {
24
+ super.apply(tree);
25
+ if (typeof this.fnName === "string") {
26
+ (0, _insert.prepend)(tree, new _template.default(`
27
+ function {fnName}(){
28
+ }
29
+ `).single({
30
+ fnName: this.fnName
31
+ }));
32
+ }
24
33
  }
25
-
26
34
  match(object, parents) {
27
35
  return (0, _traverse.isBlock)(object) || object.type == "SwitchCase";
28
36
  }
29
-
30
37
  transform(object, parents) {
31
38
  return () => {
32
39
  var exprs = [];
33
40
  var deleteExprs = [];
34
41
  var body = object.type == "SwitchCase" ? object.consequent : object.body;
35
-
36
42
  const end = () => {
37
43
  function flatten(expr) {
38
44
  if (expr.type == "ExpressionStatement") {
@@ -43,25 +49,26 @@ class AntiTooling extends _transform.default {
43
49
  flattened.push(expr);
44
50
  }
45
51
  }
46
-
47
52
  var flattened = [];
48
53
  exprs.forEach(flatten);
49
-
50
54
  if (flattened.length > 1) {
51
- flattened[0] = { ...flattened[0]
55
+ flattened[0] = {
56
+ ...flattened[0]
52
57
  };
53
- this.replace(exprs[0], (0, _gen.ExpressionStatement)((0, _gen.UnaryExpression)((0, _random.choice)(["typeof", "void", "!"]), (0, _gen.SequenceExpression)(flattened))));
58
+ if (!this.fnName) {
59
+ this.fnName = this.getPlaceholder();
60
+ }
61
+
62
+ // (expr1,expr2,expr3) -> F(expr1, expr2, expr3)
63
+ this.replace(exprs[0], (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.fnName), [...flattened])));
54
64
  deleteExprs.push(...exprs.slice(1));
55
65
  }
56
-
57
66
  exprs = [];
58
67
  };
59
-
60
68
  body.forEach((stmt, i) => {
61
69
  if (stmt.hidden || stmt.directive) {
62
70
  return;
63
71
  }
64
-
65
72
  if (stmt.type == "ExpressionStatement") {
66
73
  exprs.push(stmt);
67
74
  } else {
@@ -71,14 +78,11 @@ class AntiTooling extends _transform.default {
71
78
  end();
72
79
  deleteExprs.forEach(expr => {
73
80
  var index = body.indexOf(expr);
74
-
75
81
  if (index !== -1) {
76
82
  body.splice(index, 1);
77
83
  }
78
84
  });
79
85
  };
80
86
  }
81
-
82
87
  }
83
-
84
88
  exports.default = AntiTooling;