js-confuser 1.7.2 → 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 (96) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/CHANGELOG.md +35 -0
  3. package/README.md +20 -4
  4. package/dist/constants.js +7 -2
  5. package/dist/index.js +8 -0
  6. package/dist/options.js +12 -2
  7. package/dist/templates/bufferToString.js +26 -5
  8. package/dist/templates/core.js +35 -0
  9. package/dist/templates/crash.js +8 -39
  10. package/dist/templates/es5.js +1 -1
  11. package/dist/templates/functionLength.js +1 -1
  12. package/dist/templates/globals.js +1 -1
  13. package/dist/templates/template.js +173 -68
  14. package/dist/transforms/antiTooling.js +1 -1
  15. package/dist/transforms/calculator.js +2 -2
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +8 -2
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +1 -1
  18. package/dist/transforms/deadCode.js +34 -24
  19. package/dist/transforms/dispatcher.js +8 -4
  20. package/dist/transforms/es5/antiClass.js +11 -11
  21. package/dist/transforms/es5/antiDestructuring.js +1 -1
  22. package/dist/transforms/es5/antiES6Object.js +2 -2
  23. package/dist/transforms/es5/antiTemplate.js +1 -1
  24. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +2 -2
  25. package/dist/transforms/identifier/globalAnalysis.js +13 -0
  26. package/dist/transforms/identifier/globalConcealing.js +41 -6
  27. package/dist/transforms/identifier/renameVariables.js +7 -0
  28. package/dist/transforms/lock/antiDebug.js +2 -2
  29. package/dist/transforms/lock/integrity.js +9 -9
  30. package/dist/transforms/lock/lock.js +106 -20
  31. package/dist/transforms/minify.js +1 -1
  32. package/dist/transforms/opaquePredicates.js +2 -2
  33. package/dist/transforms/preparation.js +12 -0
  34. package/dist/transforms/rgf.js +32 -3
  35. package/dist/transforms/shuffle.js +3 -3
  36. package/dist/transforms/stack.js +8 -2
  37. package/dist/transforms/string/encoding.js +6 -3
  38. package/dist/transforms/string/stringCompression.js +34 -3
  39. package/dist/transforms/string/stringConcealing.js +7 -6
  40. package/dist/transforms/transform.js +26 -4
  41. package/dist/util/guard.js +5 -0
  42. package/dist/util/random.js +26 -0
  43. package/docs/Countermeasures.md +13 -6
  44. package/docs/Integrity.md +35 -28
  45. package/docs/RGF.md +6 -1
  46. package/docs/RenameVariables.md +116 -0
  47. package/docs/TamperProtection.md +100 -0
  48. package/docs/Template.md +117 -0
  49. package/package.json +1 -1
  50. package/src/constants.ts +5 -0
  51. package/src/index.ts +7 -5
  52. package/src/options.ts +47 -7
  53. package/src/templates/bufferToString.ts +34 -4
  54. package/src/templates/core.ts +29 -0
  55. package/src/templates/crash.ts +6 -38
  56. package/src/templates/es5.ts +1 -1
  57. package/src/templates/functionLength.ts +1 -1
  58. package/src/templates/globals.ts +1 -1
  59. package/src/templates/template.ts +185 -86
  60. package/src/transforms/antiTooling.ts +1 -1
  61. package/src/transforms/calculator.ts +4 -2
  62. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +10 -3
  63. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +1 -1
  64. package/src/transforms/deadCode.ts +74 -26
  65. package/src/transforms/dispatcher.ts +9 -5
  66. package/src/transforms/es5/antiClass.ts +15 -11
  67. package/src/transforms/es5/antiDestructuring.ts +1 -1
  68. package/src/transforms/es5/antiES6Object.ts +2 -2
  69. package/src/transforms/es5/antiTemplate.ts +1 -1
  70. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +2 -6
  71. package/src/transforms/identifier/globalAnalysis.ts +18 -1
  72. package/src/transforms/identifier/globalConcealing.ts +94 -11
  73. package/src/transforms/identifier/renameVariables.ts +16 -1
  74. package/src/transforms/lock/antiDebug.ts +2 -2
  75. package/src/transforms/lock/integrity.ts +13 -11
  76. package/src/transforms/lock/lock.ts +122 -30
  77. package/src/transforms/minify.ts +1 -1
  78. package/src/transforms/opaquePredicates.ts +2 -2
  79. package/src/transforms/preparation.ts +16 -0
  80. package/src/transforms/rgf.ts +46 -8
  81. package/src/transforms/shuffle.ts +3 -3
  82. package/src/transforms/stack.ts +9 -3
  83. package/src/transforms/string/encoding.ts +10 -7
  84. package/src/transforms/string/stringCompression.ts +81 -9
  85. package/src/transforms/string/stringConcealing.ts +10 -6
  86. package/src/transforms/transform.ts +35 -47
  87. package/src/types.ts +2 -0
  88. package/src/util/guard.ts +10 -0
  89. package/src/util/random.ts +81 -1
  90. package/test/code/Cash.test.ts +84 -1
  91. package/test/compare.test.ts +5 -5
  92. package/test/options.test.ts +18 -0
  93. package/test/templates/template.test.ts +211 -1
  94. package/test/transforms/identifier/globalConcealing.test.ts +70 -0
  95. package/test/transforms/identifier/renameVariables.test.ts +75 -1
  96. package/test/transforms/lock/tamperProtection.test.ts +336 -0
@@ -15,7 +15,7 @@ jobs:
15
15
 
16
16
  strategy:
17
17
  matrix:
18
- node-version: [14.15, 16.10, 18.0]
18
+ node-version: [14.15, 16.10, 18.0, 20.16]
19
19
  # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
20
20
 
21
21
  steps:
package/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ # `1.7.3`
2
+ Tamper Protection
3
+
4
+ ### `Tamper Protection`
5
+
6
+ Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls.
7
+
8
+ [Learn more here.](/docs/TamperProtection.md)
9
+
10
+ ---
11
+
12
+ - Rename Variables improvements:
13
+
14
+ - A new exposed function, `__JS_CONFUSER_VAR__`, can be used to access renamed variables. [Learn more here](/docs/RenameVariables.md).
15
+
16
+
17
+ ```js
18
+ // Input
19
+ var name = "John Doe";
20
+ eval("console.log(" + __JS_CONFUSER_VAR__(name) + ")");
21
+
22
+ // Output
23
+ var CA1HU0 = 'John Doe';
24
+ eval('console.log(' + 'CA1HU0' + ')');
25
+ ```
26
+
27
+ - Improved the `Zero Width` identifier generator (Thanks @doctor8296!)
28
+
29
+ - Pad the `String Concealing` array with more fake strings
30
+
31
+ - Improve `String Compression`
32
+
33
+ - New Web UI sneak peak: https://new--confuser.netlify.app/
34
+
35
+
1
36
  # `1.7.2`
2
37
  Updates
3
38
 
package/README.md CHANGED
@@ -183,6 +183,8 @@ var qFaI6S = function () {
183
183
  qFaI6S();
184
184
  ```
185
185
 
186
+ [Learn mode here.](https://github.com/MichaelXF/js-confuser/blob/master/docs/RenameVariables.md)
187
+
186
188
  ### `renameGlobals`
187
189
 
188
190
  Renames top-level variables, turn this off for web-related scripts. Enabled by default. (`true/false`)
@@ -390,6 +392,8 @@ Use a number to control the percentage of strings.
390
392
 
391
393
  String Encoding transforms a string into an encoded representation. (`true/false/0-1`)
392
394
 
395
+ **⚠️ Warning: Significantly increases file size! It is not recommended for most use cases.**
396
+
393
397
  Use a number to control the percentage of strings.
394
398
 
395
399
  `"console"` -> `'\x63\x6f\x6e\x73\x6f\x6c\x65'`
@@ -577,9 +581,16 @@ Creates a calculator function to handle arithmetic and logical expressions. (`tr
577
581
 
578
582
  Adds `debugger` statements throughout the code. Additionally adds a background function for DevTools detection. (`true/false/0-1`)
579
583
 
580
- ### `lock.context`
584
+ ### `lock.tamperProtection`
581
585
 
582
- Properties that must be present on the `window` object (or `global` for NodeJS). (`string[]`)
586
+ Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls. (`true/false`)
587
+
588
+ **⚠️ Tamper Protection requires eval and ran in a non-strict mode environment!**
589
+
590
+ - **This can break your code.**
591
+ - **Due to the security concerns of arbitrary code execution, you must enable this yourself.**
592
+
593
+ [Learn more here](https://github.com/MichaelXF/js-confuser/blob/master/TamperProtection.md).
583
594
 
584
595
  ### `lock.startDate`
585
596
 
@@ -629,10 +640,14 @@ Integrity ensures the source code is unchanged. (`true/false/0-1`)
629
640
 
630
641
  A custom callback function to invoke when a lock is triggered. (`string/false`)
631
642
 
632
- [Learn more about the countermeasures function](https://github.com/MichaelXF/js-confuser/blob/master/docs/Countermeasures.md).
643
+ [Learn more here.](https://github.com/MichaelXF/js-confuser/blob/master/docs/Countermeasures.md)
633
644
 
634
645
  Otherwise, the obfuscator falls back to crashing the process.
635
646
 
647
+ ### `lock.context`
648
+
649
+ Properties that must be present on the `window` object (or `global` for NodeJS). (`string[]`)
650
+
636
651
  ### `movedDeclarations`
637
652
 
638
653
  Moves variable declarations to the top of the context. (`true/false`)
@@ -785,6 +800,7 @@ You must enable locks yourself, and configure them to your needs.
785
800
  lock: {
786
801
  integrity: true,
787
802
  selfDefending: true,
803
+ tamperProtection: true,
788
804
  domainLock: ["mywebsite.com"],
789
805
  osLock: ["windows", "linux"],
790
806
  browserLock: ["firefox"],
@@ -813,7 +829,7 @@ These features are experimental or a security concern.
813
829
  // set to false for web-related scripts
814
830
  renameGlobals: false,
815
831
 
816
- // experimental
832
+ // custom implementation
817
833
  identifierGenerator: function(){
818
834
  return "myvar_" + (counter++);
819
835
  },
package/dist/constants.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.reservedKeywords = exports.reservedIdentifiers = exports.predictableFunctionTag = exports.placeholderVariablePrefix = exports.noRenameVariablePrefix = exports.criticalFunctionTag = void 0;
6
+ exports.variableFunctionName = exports.reservedKeywords = exports.reservedIdentifiers = exports.predictableFunctionTag = exports.placeholderVariablePrefix = exports.noRenameVariablePrefix = exports.criticalFunctionTag = void 0;
7
7
  /**
8
8
  * Keywords disallowed for variable names in ES5 and under.
9
9
  */
@@ -26,4 +26,9 @@ const predictableFunctionTag = exports.predictableFunctionTag = "__JS_PREDICT__"
26
26
  * Tells the obfuscator this function is critical for the Obfuscated code.
27
27
  * - Example: string decryption function
28
28
  */
29
- const criticalFunctionTag = exports.criticalFunctionTag = "__JS_CRITICAL__";
29
+ const criticalFunctionTag = exports.criticalFunctionTag = "__JS_CRITICAL__";
30
+
31
+ /**
32
+ * Allows the user to grab the variable name of a renamed variable.
33
+ */
34
+ const variableFunctionName = exports.variableFunctionName = "__JS_CONFUSER_VAR__";
package/dist/index.js CHANGED
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "Obfuscator", {
9
9
  return _obfuscator.default;
10
10
  }
11
11
  });
12
+ Object.defineProperty(exports, "Template", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _template.default;
16
+ }
17
+ });
12
18
  Object.defineProperty(exports, "Transform", {
13
19
  enumerable: true,
14
20
  get: function () {
@@ -28,6 +34,7 @@ var _compiler = _interopRequireWildcard(require("./compiler"));
28
34
  var _parser = _interopRequireWildcard(require("./parser"));
29
35
  var _obfuscator = _interopRequireDefault(require("./obfuscator"));
30
36
  var _transform = _interopRequireDefault(require("./transforms/transform"));
37
+ var _template = _interopRequireDefault(require("./templates/template"));
31
38
  var _object = require("./util/object");
32
39
  var _presets = _interopRequireDefault(require("./presets"));
33
40
  var assert = _interopRequireWildcard(require("assert"));
@@ -156,6 +163,7 @@ JsConfuser.debugTransformations = debugTransformations;
156
163
  JsConfuser.debugObfuscation = debugObfuscation;
157
164
  JsConfuser.Obfuscator = _obfuscator.default;
158
165
  JsConfuser.Transform = _transform.default;
166
+ JsConfuser.Template = _template.default;
159
167
  if (typeof window !== "undefined") {
160
168
  window["JsConfuser"] = JsConfuser;
161
169
  }
package/dist/options.js CHANGED
@@ -9,6 +9,7 @@ var _assert = require("assert");
9
9
  var _presets = _interopRequireDefault(require("./presets"));
10
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
11
  const validProperties = new Set(["preset", "target", "indent", "compact", "hexadecimalNumbers", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "controlFlowFlattening", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "stack", "verbose", "globalVariables", "debugComments", "preserveFunctionLength"]);
12
+ const validLockProperties = new Set(["selfDefending", "antiDebug", "context", "tamperProtection", "startDate", "endDate", "domainLock", "osLock", "browserLock", "integrity", "countermeasures"]);
12
13
  const validOses = new Set(["windows", "linux", "osx", "ios", "android"]);
13
14
  const validBrowsers = new Set(["firefox", "chrome", "iexplorer", "edge", "safari", "opera"]);
14
15
  function validateOptions(options) {
@@ -31,6 +32,13 @@ function validateOptions(options) {
31
32
  throw new TypeError('browserLock can only be used when target="browser"');
32
33
  }
33
34
  if (options.lock) {
35
+ (0, _assert.ok)(typeof options.lock === "object", "options.lock must be an object");
36
+ Object.keys(options.lock).forEach(key => {
37
+ if (!validLockProperties.has(key)) {
38
+ throw new TypeError("Invalid lock option: '" + key + "'");
39
+ }
40
+ });
41
+
34
42
  // Validate browser-lock option
35
43
  if (options.lock.browserLock && typeof options.lock.browserLock !== "undefined") {
36
44
  (0, _assert.ok)(Array.isArray(options.lock.browserLock), "browserLock must be an array");
@@ -93,8 +101,10 @@ async function correctOptions(options) {
93
101
  if (options.globalVariables && !(options.globalVariables instanceof Set)) {
94
102
  options.globalVariables = new Set(Object.keys(options.globalVariables));
95
103
  }
96
- if (options.lock && options.lock.selfDefending) {
97
- options.compact = true; // self defending forcibly enables this
104
+ if (options.lock) {
105
+ if (options.lock.selfDefending) {
106
+ options.compact = true; // self defending forcibly enables this
107
+ }
98
108
  }
99
109
 
100
110
  // options.globalVariables outlines generic globals that should be present in the execution context
@@ -3,11 +3,33 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.GetGlobalTemplate = exports.BufferToStringTemplate = void 0;
6
+ exports.createGetGlobalTemplate = exports.BufferToStringTemplate = void 0;
7
7
  var _constants = require("../constants");
8
8
  var _template = _interopRequireDefault(require("./template"));
9
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
- const GetGlobalTemplate = exports.GetGlobalTemplate = (0, _template.default)(`
10
+ const createGetGlobalTemplate = (transform, object, parents) => {
11
+ var _options$lock;
12
+ var options = transform.options;
13
+ if ((_options$lock = options.lock) !== null && _options$lock !== void 0 && _options$lock.tamperProtection) {
14
+ return new _template.default(`
15
+ function {getGlobalFnName}(){
16
+ var localVar = false;
17
+ eval(${transform.jsConfuserVar("localVar")} + " = true")
18
+ if (!localVar) {
19
+ {countermeasures}
20
+ }
21
+
22
+ const root = eval("this");
23
+ return root;
24
+ }
25
+ `).setDefaultVariables({
26
+ countermeasures: transform.lockTransform.getCounterMeasuresCode(object, parents)
27
+ });
28
+ }
29
+ return GetGlobalTemplate;
30
+ };
31
+ exports.createGetGlobalTemplate = createGetGlobalTemplate;
32
+ const GetGlobalTemplate = new _template.default(`
11
33
  function ${_constants.placeholderVariablePrefix}CFG__getGlobalThis${_constants.predictableFunctionTag}(){
12
34
  return globalThis
13
35
  }
@@ -51,9 +73,8 @@ const GetGlobalTemplate = exports.GetGlobalTemplate = (0, _template.default)(`
51
73
  return bestMatch || this;
52
74
  }
53
75
  `);
54
- const BufferToStringTemplate = exports.BufferToStringTemplate = (0, _template.default)(`
55
-
56
- ${GetGlobalTemplate.source}
76
+ const BufferToStringTemplate = exports.BufferToStringTemplate = new _template.default(`
77
+ {GetGlobalTemplate}
57
78
 
58
79
  var __globalObject = {getGlobalFnName}() || {};
59
80
  var __TextDecoder = __globalObject["TextDecoder"];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.IndexOfTemplate = void 0;
7
+ var _template = _interopRequireDefault(require("./template"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ const IndexOfTemplate = exports.IndexOfTemplate = new _template.default(`
10
+ function indexOf(str, substr) {
11
+ const len = str.length;
12
+ const sublen = substr.length;
13
+ let count = 0;
14
+
15
+ if (sublen > len) {
16
+ return -1;
17
+ }
18
+
19
+ for (let i = 0; i <= len - sublen; i++) {
20
+ for (let j = 0; j < sublen; j++) {
21
+ if (str[i + j] === substr[j]) {
22
+ count++;
23
+ if (count === sublen) {
24
+ return i;
25
+ }
26
+ } else {
27
+ count = 0;
28
+ break;
29
+ }
30
+ }
31
+ }
32
+
33
+ return -1;
34
+ }
35
+ `);
@@ -3,16 +3,17 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.CrashTemplate3 = exports.CrashTemplate2 = exports.CrashTemplate1 = void 0;
6
+ exports.CrashTemplate2 = exports.CrashTemplate1 = void 0;
7
7
  var _template = _interopRequireDefault(require("./template"));
8
8
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
- const CrashTemplate1 = exports.CrashTemplate1 = (0, _template.default)(`
10
- var {var} = "a";
11
- while(1){
12
- {var} = {var} += "a";
9
+ const CrashTemplate1 = exports.CrashTemplate1 = new _template.default(`
10
+ var {var} = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_\`{|}~"';
11
+ while(true){
12
+ {var} = {var};
13
+ if(!{var}) break;
13
14
  }
14
15
  `);
15
- const CrashTemplate2 = exports.CrashTemplate2 = (0, _template.default)(`
16
+ const CrashTemplate2 = exports.CrashTemplate2 = new _template.default(`
16
17
  while(true) {
17
18
  var {var} = 99;
18
19
  for({var} = 99; {var} == {var}; {var} *= {var}) {
@@ -24,36 +25,4 @@ while(true) {
24
25
  if({var} === 100) {
25
26
  {var}--
26
27
  }
27
- };`);
28
- const CrashTemplate3 = exports.CrashTemplate3 = (0, _template.default)(`
29
- try {
30
- function {$2}(y, x){
31
- return x;
32
- }
33
-
34
- var {$1} = {$2}(this, function () {
35
- var {$3} = function () {
36
- var regExp = {$3}
37
- .constructor('return /" + this + "/')()
38
- .constructor('^([^ ]+( +[^ ]+)+)+[^ ]}');
39
-
40
- return !regExp.call({$1});
41
- };
42
-
43
- return {$3}();
44
- });
45
-
46
- {$1}();
47
- } catch ( {$1}e ) {
48
- while({$1}e ? {$1}e : !{$1}e){
49
- var {$1}b;
50
- var {$1}c = 0;
51
- ({$1}e ? !{$1}e : {$1}e) ? (function({$1}e){
52
- {$1}c = {$1}e ? 0 : !{$1}e ? 1 : 0;
53
- })({$1}e) : {$1}b = 1;
54
-
55
- if({$1}b&&{$1}c){break;}
56
- if({$1}b){continue;}
57
- }
58
- }
59
- `);
28
+ };`);
@@ -11,7 +11,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
11
11
  *
12
12
  * Source: https://vanillajstoolkit.com/polyfills/
13
13
  */
14
- const ES5Template = exports.ES5Template = (0, _template.default)(`
14
+ const ES5Template = exports.ES5Template = new _template.default(`
15
15
  if (!Array.prototype.forEach) {
16
16
  Array.prototype.forEach = function forEach (callback, thisArg) {
17
17
  if (typeof callback !== 'function') {
@@ -9,7 +9,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
9
9
  /**
10
10
  * Helper function to set `function.length` property.
11
11
  */
12
- const FunctionLengthTemplate = exports.FunctionLengthTemplate = (0, _template.default)(`
12
+ const FunctionLengthTemplate = exports.FunctionLengthTemplate = new _template.default(`
13
13
  function {name}(functionObject, functionLength){
14
14
  {ObjectDefineProperty}(functionObject, "length", {
15
15
  "value": functionLength,
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ObjectDefineProperty = void 0;
7
7
  var _template = _interopRequireDefault(require("./template"));
8
8
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
- const ObjectDefineProperty = exports.ObjectDefineProperty = (0, _template.default)(`Object["defineProperty"]`);
9
+ const ObjectDefineProperty = exports.ObjectDefineProperty = new _template.default(`Object["defineProperty"]`);
@@ -3,57 +3,135 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = Template;
6
+ exports.default = void 0;
7
7
  var _parser = require("../parser");
8
8
  var _assert = require("assert");
9
9
  var _random = require("../util/random");
10
- var _constants = require("../constants");
11
- function Template() {
12
- for (var _len = arguments.length, templates = new Array(_len), _key = 0; _key < _len; _key++) {
13
- templates[_key] = arguments[_key];
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();
14
86
  }
15
- (0, _assert.ok)(templates.length);
16
- var requiredVariables = new Set();
17
- var providedVariables = {};
18
- var defaultVariables = Object.create(null);
19
-
20
- // This may picked up "$mb[pP`x]" from String Encoding function
21
- // ignoreMissingVariables() prevents this
22
- var matches = templates[0].match(/{[$A-z0-9_]+}/g);
23
- if (matches !== null) {
24
- matches.forEach(variable => {
25
- var name = variable.slice(1, -1);
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);
26
96
 
27
- // $ variables are for default variables
28
- if (name.startsWith("$")) {
29
- defaultVariables[name] = _constants.placeholderVariablePrefix + "td_" + Object.keys(defaultVariables).length;
30
- } else {
31
- requiredVariables.add(name);
32
- }
33
- });
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
+ });
104
+ }
34
105
  }
35
- function fill() {
36
- let variables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Object.create(null);
37
- var userVariables = {
38
- ...providedVariables,
106
+
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,
39
118
  ...variables
40
119
  };
41
120
 
42
121
  // Validate all variables were passed in
43
- for (var requiredVariable of requiredVariables) {
44
- if (typeof userVariables[requiredVariable] === "undefined") {
45
- throw new Error(templates[0] + " missing variable: " + requiredVariable + " from " + JSON.stringify(userVariables));
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));
46
125
  }
47
126
  }
48
- var template = (0, _random.choice)(templates);
127
+ var template = (0, _random.choice)(this.templates);
49
128
  var output = template;
50
- var allVariables = {
51
- ...defaultVariables,
52
- ...userVariables
53
- };
54
129
  Object.keys(allVariables).forEach(name => {
55
130
  var bracketName = "{" + name.replace("$", "\\$") + "}";
56
131
  var value = allVariables[name] + "";
132
+ if (typeof allVariables[name] !== "string") {
133
+ value = name;
134
+ }
57
135
  var reg = new RegExp(bracketName, "g");
58
136
  output = output.replace(reg, value);
59
137
  });
@@ -62,45 +140,72 @@ function Template() {
62
140
  template
63
141
  };
64
142
  }
65
- function compile(variables) {
143
+
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
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] : {};
66
188
  var {
67
189
  output,
68
190
  template
69
- } = fill(variables);
191
+ } = this.interpolateTemplate(variables);
192
+ var program;
70
193
  try {
71
- var program = (0, _parser.parseSnippet)(output);
72
- return program.body;
194
+ program = (0, _parser.parseSnippet)(output);
73
195
  } catch (e) {
74
- console.error(e);
75
- console.error(template);
76
- console.error({
77
- ...providedVariables,
78
- ...variables
79
- });
80
- throw new Error("Template failed to parse: OUTPUT= " + output + " SOURCE= " + template);
196
+ throw new Error(output + "\n" + "Template failed to parse: " + e.message);
81
197
  }
198
+ this.interpolateAST(program, variables);
199
+ return program.body;
82
200
  }
83
- function single(variables) {
84
- 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
+ }
85
208
  return nodes[0];
86
209
  }
87
- function variables(newVariables) {
88
- Object.assign(providedVariables, newVariables);
89
- return obj;
90
- }
91
- function ignoreMissingVariables() {
92
- defaultVariables = Object.create(null);
93
- requiredVariables.clear();
94
- return obj;
95
- }
96
- var obj = {
97
- fill,
98
- compile,
99
- single,
100
- templates,
101
- variables,
102
- ignoreMissingVariables,
103
- source: templates[0]
104
- };
105
- return obj;
106
- }
210
+ }
211
+ exports.default = Template;
@@ -23,7 +23,7 @@ class AntiTooling extends _transform.default {
23
23
  apply(tree) {
24
24
  super.apply(tree);
25
25
  if (typeof this.fnName === "string") {
26
- (0, _insert.prepend)(tree, (0, _template.default)(`
26
+ (0, _insert.prepend)(tree, new _template.default(`
27
27
  function {fnName}(){
28
28
  }
29
29
  `).single({