js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.4

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 (91) hide show
  1. package/.prettierrc +4 -0
  2. package/CHANGELOG.md +42 -8
  3. package/Migration.md +23 -8
  4. package/README.md +2 -2
  5. package/dist/constants.js +11 -2
  6. package/dist/index.js +49 -6
  7. package/dist/obfuscator.js +121 -10
  8. package/dist/order.js +0 -1
  9. package/dist/probability.js +1 -96
  10. package/dist/templates/getGlobalTemplate.js +4 -1
  11. package/dist/templates/integrityTemplate.js +1 -1
  12. package/dist/templates/stringCompressionTemplate.js +3 -3
  13. package/dist/templates/tamperProtectionTemplates.js +1 -1
  14. package/dist/templates/template.js +17 -12
  15. package/dist/transforms/controlFlowFlattening.js +112 -83
  16. package/dist/transforms/deadCode.js +21 -22
  17. package/dist/transforms/dispatcher.js +62 -37
  18. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
  19. package/dist/transforms/extraction/objectExtraction.js +1 -2
  20. package/dist/transforms/finalizer.js +1 -1
  21. package/dist/transforms/flatten.js +2 -19
  22. package/dist/transforms/identifier/globalConcealing.js +3 -4
  23. package/dist/transforms/identifier/movedDeclarations.js +12 -5
  24. package/dist/transforms/identifier/renameVariables.js +40 -6
  25. package/dist/transforms/lock/integrity.js +9 -1
  26. package/dist/transforms/lock/lock.js +16 -9
  27. package/dist/transforms/minify.js +64 -27
  28. package/dist/transforms/opaquePredicates.js +6 -7
  29. package/dist/transforms/pack.js +32 -5
  30. package/dist/transforms/plugin.js +20 -39
  31. package/dist/transforms/preparation.js +25 -36
  32. package/dist/transforms/renameLabels.js +1 -2
  33. package/dist/transforms/rgf.js +36 -16
  34. package/dist/transforms/shuffle.js +10 -11
  35. package/dist/transforms/string/stringCompression.js +14 -10
  36. package/dist/transforms/string/stringConcealing.js +7 -5
  37. package/dist/transforms/string/stringEncoding.js +4 -2
  38. package/dist/transforms/string/stringSplitting.js +4 -2
  39. package/dist/transforms/variableMasking.js +3 -2
  40. package/dist/utils/NameGen.js +5 -2
  41. package/dist/utils/PredicateGen.js +62 -0
  42. package/dist/utils/ast-utils.js +24 -9
  43. package/dist/utils/random-utils.js +10 -0
  44. package/dist/validateOptions.js +2 -2
  45. package/index.d.ts +16 -2
  46. package/package.json +2 -2
  47. package/src/constants.ts +15 -5
  48. package/src/index.ts +15 -5
  49. package/src/obfuscationResult.ts +7 -1
  50. package/src/obfuscator.ts +152 -12
  51. package/src/options.ts +26 -8
  52. package/src/order.ts +0 -2
  53. package/src/templates/getGlobalTemplate.ts +5 -1
  54. package/src/templates/integrityTemplate.ts +14 -19
  55. package/src/templates/stringCompressionTemplate.ts +4 -28
  56. package/src/templates/tamperProtectionTemplates.ts +7 -3
  57. package/src/templates/template.ts +5 -3
  58. package/src/transforms/controlFlowFlattening.ts +139 -83
  59. package/src/transforms/deadCode.ts +27 -30
  60. package/src/transforms/dispatcher.ts +24 -5
  61. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
  62. package/src/transforms/extraction/objectExtraction.ts +1 -2
  63. package/src/transforms/finalizer.ts +1 -1
  64. package/src/transforms/flatten.ts +3 -22
  65. package/src/transforms/identifier/globalConcealing.ts +26 -17
  66. package/src/transforms/identifier/movedDeclarations.ts +18 -6
  67. package/src/transforms/identifier/renameVariables.ts +48 -6
  68. package/src/transforms/lock/integrity.ts +11 -1
  69. package/src/transforms/lock/lock.ts +26 -10
  70. package/src/transforms/minify.ts +85 -38
  71. package/src/transforms/opaquePredicates.ts +6 -9
  72. package/src/transforms/pack.ts +41 -5
  73. package/src/transforms/plugin.ts +47 -69
  74. package/src/transforms/preparation.ts +33 -46
  75. package/src/transforms/renameLabels.ts +1 -2
  76. package/src/transforms/rgf.ts +52 -23
  77. package/src/transforms/shuffle.ts +28 -26
  78. package/src/transforms/string/encoding.ts +1 -1
  79. package/src/transforms/string/stringCompression.ts +22 -13
  80. package/src/transforms/string/stringConcealing.ts +13 -7
  81. package/src/transforms/string/stringEncoding.ts +6 -2
  82. package/src/transforms/string/stringSplitting.ts +9 -4
  83. package/src/transforms/variableMasking.ts +2 -2
  84. package/src/utils/NameGen.ts +13 -3
  85. package/src/utils/PredicateGen.ts +61 -0
  86. package/src/utils/ast-utils.ts +16 -9
  87. package/src/utils/random-utils.ts +14 -0
  88. package/src/validateOptions.ts +7 -4
  89. package/src/probability.ts +0 -110
  90. package/src/transforms/functionOutlining.ts +0 -225
  91. package/src/utils/ControlObject.ts +0 -141
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports["default"] = void 0;
8
8
  var t = _interopRequireWildcard(require("@babel/types"));
9
- var _probability = require("../probability");
10
9
  var _randomUtils = require("../utils/random-utils");
11
10
  var _template = _interopRequireDefault(require("../templates/template"));
12
11
  var _order = require("../order");
13
12
  var _staticUtils = require("../utils/static-utils");
14
13
  var _constants = require("../constants");
15
14
  var _node = require("../utils/node");
15
+ var _astUtils = require("../utils/ast-utils");
16
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
17
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
18
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
@@ -29,6 +29,7 @@ var _default = exports["default"] = function _default(_ref) {
29
29
  arrays: 0
30
30
  }
31
31
  });
32
+ var fnName = null;
32
33
  return {
33
34
  visitor: {
34
35
  ArrayExpression: {
@@ -40,23 +41,21 @@ var _default = exports["default"] = function _default(_ref) {
40
41
  return !(0, _staticUtils.isStaticValue)(element);
41
42
  });
42
43
  if (illegalElement) return;
43
- if (!(0, _probability.computeProbabilityMap)(me.options.shuffle)) {
44
+ if (!me.computeProbabilityMap(me.options.shuffle)) {
44
45
  return;
45
46
  }
47
+
48
+ // Create un-shuffling function
49
+ if (!fnName) {
50
+ fnName = me.getPlaceholder() + "_shuffle";
51
+ (0, _astUtils.prependProgram)(path, new _template["default"]("\n function ".concat(fnName, "(arr, shift) {\n for (var i = 0; i < shift; i++) {\n arr[\"push\"](arr[\"shift\"]());\n }\n return arr;\n }\n ")).addSymbols(_constants.PREDICTABLE).single());
52
+ }
46
53
  var shift = (0, _randomUtils.getRandomInteger)(1, Math.min(30, path.node.elements.length * 6));
47
54
  var shiftedElements = _toConsumableArray(path.node.elements);
48
55
  for (var i = 0; i < shift; i++) {
49
56
  shiftedElements.unshift(shiftedElements.pop());
50
57
  }
51
- var block = path.find(function (p) {
52
- return p.isBlock();
53
- });
54
- var functionExpression = new _template["default"]("\n (function(arr) {\n for (var i = 0; i < {shiftNode}; i++) {\n arr.push(arr.shift());\n }\n return arr;\n })\n ").expression({
55
- shiftNode: (0, _node.numericLiteral)(shift)
56
- });
57
- functionExpression[_constants.PREDICTABLE] = true;
58
- var memberExpression = me.getControlObject(block).addProperty(functionExpression);
59
- path.replaceWith(t.callExpression(memberExpression, [t.arrayExpression(shiftedElements)]));
58
+ path.replaceWith(t.callExpression(t.identifier(fnName), [t.arrayExpression(shiftedElements), (0, _node.numericLiteral)(shift)]));
60
59
  path.skip();
61
60
  me.changeData.arrays++;
62
61
  }
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports["default"] = void 0;
8
8
  var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _order = require("../../order");
10
- var _probability = require("../../probability");
11
10
  var _astUtils = require("../../utils/ast-utils");
12
11
  var _node = require("../../utils/node");
13
12
  var _stringCompressionTemplate = require("../../templates/stringCompressionTemplate");
@@ -17,7 +16,7 @@ var _constants = require("../../constants");
17
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
18
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
19
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
20
- var pako = require("pako");
19
+ var LZString = require("lz-string");
21
20
  var _default = exports["default"] = function _default(_ref) {
22
21
  var Plugin = _ref.Plugin;
23
22
  var me = Plugin(_order.Order.StringCompression, {
@@ -25,6 +24,10 @@ var _default = exports["default"] = function _default(_ref) {
25
24
  strings: 0
26
25
  }
27
26
  });
27
+
28
+ // String Compression is only applied to the main obfuscator
29
+ // Any RGF functions will not have string compression due to the size of the decompression function
30
+
28
31
  var _stringDelimiter = "|";
29
32
  return {
30
33
  visitor: {
@@ -37,6 +40,8 @@ var _default = exports["default"] = function _default(_ref) {
37
40
  programPath.traverse({
38
41
  StringLiteral: {
39
42
  exit: function exit(path) {
43
+ // Don't change module imports
44
+ if ((0, _astUtils.isModuleImport)(path)) return;
40
45
  var originalValue = path.node.value;
41
46
 
42
47
  // Must be at least 3 characters long
@@ -47,7 +52,7 @@ var _default = exports["default"] = function _default(_ref) {
47
52
  var index = stringMap.get(originalValue);
48
53
  if (typeof index === "undefined") {
49
54
  // Allow user option to skip compression for certain strings
50
- if (!(0, _probability.computeProbabilityMap)(me.options.stringCompression, originalValue)) {
55
+ if (!me.computeProbabilityMap(me.options.stringCompression, originalValue)) {
51
56
  return;
52
57
  }
53
58
  index = stringMap.size;
@@ -65,9 +70,8 @@ var _default = exports["default"] = function _default(_ref) {
65
70
  var stringPayload = Array.from(stringMap.keys()).join(_stringDelimiter);
66
71
 
67
72
  // Compress the string
68
- var compressedBuffer = pako.deflate(stringPayload);
69
- var compressedBase64 = Buffer.from(compressedBuffer).toString("base64");
70
- var pakoName = me.obfuscator.getStringCompressionLibraryName();
73
+ var compressedString = LZString.compressToUTF16(stringPayload);
74
+ var stringCompressionLibraryName = me.obfuscator.getStringCompressionLibraryName();
71
75
  var insertStringCompressionLibrary = !me.obfuscator.parentObfuscator;
72
76
  (0, _astUtils.prependProgram)(programPath, _stringCompressionTemplate.StringCompressionTemplate.compile({
73
77
  stringFn: stringFn,
@@ -77,15 +81,15 @@ var _default = exports["default"] = function _default(_ref) {
77
81
  return t.stringLiteral(_stringDelimiter);
78
82
  },
79
83
  stringValue: function stringValue() {
80
- return t.stringLiteral(compressedBase64);
84
+ return t.stringLiteral(compressedString);
81
85
  },
82
86
  GetGlobalTemplate: (0, _getGlobalTemplate.createGetGlobalTemplate)(me, programPath),
83
87
  getGlobalFnName: me.getPlaceholder(),
84
- pakoName: pakoName
88
+ StringCompressionLibrary: stringCompressionLibraryName
85
89
  }));
86
90
  if (insertStringCompressionLibrary) {
87
- // RGF function should also clone the entire decompression function
88
- (0, _astUtils.prependProgram)(programPath, _obfuscator["default"].parseCode(_stringCompressionTemplate.PakoInflateMin.replace(/{pako}/g, pakoName)).program.body)[0].get("declarations")[0].get("id").node[_constants.NO_RENAME] = true;
91
+ // RGF functions should not clone the entire decompression function
92
+ (0, _astUtils.prependProgram)(programPath, _obfuscator["default"].parseCode(_stringCompressionTemplate.StringCompressionLibraryMinified.replace(/{StringCompressionLibrary}/g, stringCompressionLibraryName)).program.body)[0].get("declarations")[0].get("id").node[_constants.NO_RENAME] = true;
89
93
  }
90
94
  }
91
95
  }
@@ -8,7 +8,6 @@ exports["default"] = void 0;
8
8
  var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _template = _interopRequireDefault(require("../../templates/template"));
10
10
  var _order = require("../../order");
11
- var _probability = require("../../probability");
12
11
  var _assert = require("assert");
13
12
  var _bufferToStringTemplate = require("../../templates/bufferToStringTemplate");
14
13
  var _getGlobalTemplate = require("../../templates/getGlobalTemplate");
@@ -16,6 +15,7 @@ var _astUtils = require("../../utils/ast-utils");
16
15
  var _randomUtils = require("../../utils/random-utils");
17
16
  var _encoding = require("./encoding");
18
17
  var _node = require("../../utils/node");
18
+ var _constants = require("../../constants");
19
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
20
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
21
21
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
@@ -30,7 +30,8 @@ var _default = exports["default"] = function _default(_ref) {
30
30
  var Plugin = _ref.Plugin;
31
31
  var me = Plugin(_order.Order.StringConcealing, {
32
32
  changeData: {
33
- strings: 0
33
+ strings: 0,
34
+ decryptionFunctions: 0
34
35
  }
35
36
  });
36
37
  var blocks = [];
@@ -72,6 +73,7 @@ var _default = exports["default"] = function _default(_ref) {
72
73
  if (typeof encoding.code === "string") {
73
74
  encoding.code = new _template["default"](encoding.code);
74
75
  }
76
+ me.changeData.decryptionFunctions++;
75
77
  encodingImplementations[encoding.identity] = encoding;
76
78
  return encoding;
77
79
  }
@@ -111,7 +113,7 @@ var _default = exports["default"] = function _default(_ref) {
111
113
  }
112
114
 
113
115
  // Check user setting
114
- if (!(0, _probability.computeProbabilityMap)(me.options.stringConcealing, originalValue)) {
116
+ if (!me.computeProbabilityMap(me.options.stringConcealing, originalValue)) {
115
117
  return;
116
118
  }
117
119
  var block = path.findParent(function (p) {
@@ -192,13 +194,13 @@ var _default = exports["default"] = function _default(_ref) {
192
194
  (0, _assert.ok)(encodingImplementation.code instanceof _template["default"]);
193
195
 
194
196
  // The decoder function
195
- var decoder = encodingImplementation.code.compile({
197
+ var decoder = encodingImplementation.code.addSymbols(_constants.NO_REMOVE).compile({
196
198
  fnName: decodeFnName,
197
199
  __bufferToStringFunction__: bufferToStringName
198
200
  });
199
201
 
200
202
  // The main function to get the string value
201
- var retrieveFunctionDeclaration = new _template["default"]("\n function ".concat(fnName, "(index) {\n return ").concat(decodeFnName, "(").concat(stringArrayName, "[index]);\n }\n ")).single();
203
+ var retrieveFunctionDeclaration = new _template["default"]("\n function ".concat(fnName, "(index) {\n return ").concat(decodeFnName, "(").concat(stringArrayName, "[index]);\n }\n ")).addSymbols(_constants.NO_REMOVE).single();
202
204
  (0, _astUtils.prepend)(block, [].concat(_toConsumableArray(decoder), [retrieveFunctionDeclaration]));
203
205
  }
204
206
  }
@@ -7,8 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports["default"] = void 0;
8
8
  var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _randomUtils = require("../../utils/random-utils");
10
- var _probability = require("../../probability");
11
10
  var _constants = require("../../constants");
11
+ var _astUtils = require("../../utils/ast-utils");
12
12
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
13
13
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
14
14
  function pad(x, len) {
@@ -52,10 +52,12 @@ var _default = exports["default"] = function _default(me) {
52
52
  visitor: {
53
53
  StringLiteral: {
54
54
  exit: function exit(path) {
55
+ // Ignore module imports
56
+ if ((0, _astUtils.isModuleImport)(path)) return;
55
57
  var value = path.node.value;
56
58
 
57
59
  // Allow percentages
58
- if (!(0, _probability.computeProbabilityMap)(me.options.stringEncoding, value)) return;
60
+ if (!me.computeProbabilityMap(me.options.stringEncoding, value)) return;
59
61
  var type = (0, _randomUtils.choice)(["hexadecimal", "unicode"]);
60
62
  var escapedString = (type == "hexadecimal" ? toHexRepresentation : toUnicodeRepresentation)(value);
61
63
  var id = t.identifier("\"".concat(escapedString, "\""));
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports["default"] = void 0;
7
7
  var _randomUtils = require("../../utils/random-utils");
8
- var _probability = require("../../probability");
9
8
  var _types = require("@babel/types");
10
9
  var _assert = require("assert");
11
10
  var _order = require("../../order");
@@ -28,6 +27,9 @@ var _default = exports["default"] = function _default(_ref) {
28
27
  StringLiteral: {
29
28
  exit: function exit(path) {
30
29
  var object = path.node;
30
+
31
+ // Don't change module imports
32
+ if ((0, _astUtils.isModuleImport)(path)) return;
31
33
  var size = Math.round(Math.max(6, object.value.length / (0, _randomUtils.getRandomInteger)(3, 8)));
32
34
  if (object.value.length <= size) {
33
35
  return;
@@ -36,7 +38,7 @@ var _default = exports["default"] = function _default(_ref) {
36
38
  if (!chunks || chunks.length <= 1) {
37
39
  return;
38
40
  }
39
- if (!(0, _probability.computeProbabilityMap)(me.options.stringSplitting, object.value)) {
41
+ if (!me.computeProbabilityMap(me.options.stringSplitting, object.value)) {
40
42
  return;
41
43
  }
42
44
  var binExpr;
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports["default"] = void 0;
8
8
  var t = _interopRequireWildcard(require("@babel/types"));
9
9
  var _template = _interopRequireDefault(require("../templates/template"));
10
- var _probability = require("../probability");
11
10
  var _order = require("../order");
12
11
  var _constants = require("../constants");
13
12
  var _astUtils = require("../utils/ast-utils");
@@ -58,7 +57,7 @@ var _default = exports["default"] = function _default(_ref) {
58
57
  // Do not apply to functions marked unsafe
59
58
  if (fnPath.node[_constants.UNSAFE]) return;
60
59
  var functionName = (0, _astUtils.getFunctionName)(fnPath);
61
- if (!(0, _probability.computeProbabilityMap)(me.options.variableMasking, functionName)) {
60
+ if (!me.computeProbabilityMap(me.options.variableMasking, functionName)) {
62
61
  return;
63
62
  }
64
63
  var stackName = me.getPlaceholder() + "_varMask";
@@ -160,6 +159,8 @@ var _default = exports["default"] = function _default(_ref) {
160
159
  fnPath.traverse({
161
160
  Identifier: function Identifier(path) {
162
161
  if (!(0, _astUtils.isVariableIdentifier)(path)) return;
162
+ if (fnPath.get("id") === path) return; // Skip this function's name (Test #21)
163
+
163
164
  if (_constants.reservedIdentifiers.has(path.node.name)) return;
164
165
  if (me.options.globalVariables.has(path.node.name)) return;
165
166
  if (path.node.name === stackName) return;
@@ -7,8 +7,9 @@ exports.NameGen = void 0;
7
7
  var _assert = require("assert");
8
8
  var _genUtils = require("./gen-utils");
9
9
  var _randomUtils = require("./random-utils");
10
- var _probability = require("../probability");
11
10
  var _constants = require("../constants");
11
+ var _obfuscator = _interopRequireDefault(require("../obfuscator"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
13
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
13
14
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
14
15
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -48,7 +49,7 @@ var NameGen = exports.NameGen = /*#__PURE__*/function () {
48
49
  (0, _assert.ok)(typeof value === "string", "Custom identifier generator must return a string");
49
50
  return value;
50
51
  }
51
- var mode = (0, _probability.computeProbabilityMap)(this.identifierGenerator);
52
+ var mode = _obfuscator["default"].prototype.computeProbabilityMap(this.identifierGenerator);
52
53
  var randomizedLength = (0, _randomUtils.getRandomInteger)(6, 8);
53
54
  switch (mode) {
54
55
  case "randomized":
@@ -72,6 +73,8 @@ var NameGen = exports.NameGen = /*#__PURE__*/function () {
72
73
  return "var_" + this.counter++;
73
74
  case "zeroWidth":
74
75
  return this.zeroWidthGenerator.generate();
76
+ case "chinese":
77
+ return (0, _randomUtils.getRandomChineseString)(randomizedLength);
75
78
  default:
76
79
  throw new Error("Invalid identifier generator mode: " + this.identifierGenerator);
77
80
  }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var t = _interopRequireWildcard(require("@babel/types"));
8
+ var _astUtils = require("./ast-utils");
9
+ var _NameGen = require("./NameGen");
10
+ var _template = _interopRequireDefault(require("../templates/template"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
13
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
14
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
15
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
16
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
17
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
18
+ 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; }
19
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
20
+ 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); }
21
+ var PredicateGen = exports["default"] = /*#__PURE__*/function () {
22
+ function PredicateGen(plugin) {
23
+ _classCallCheck(this, PredicateGen);
24
+ _defineProperty(this, "dummyFunctionName", null);
25
+ _defineProperty(this, "programPath", null);
26
+ this.plugin = plugin;
27
+ }
28
+ return _createClass(PredicateGen, [{
29
+ key: "ensureCreated",
30
+ value: function ensureCreated() {
31
+ if (this.dummyFunctionName) return;
32
+ this.dummyFunctionName = this.plugin.getPlaceholder("dummyFunction");
33
+
34
+ // Insert dummy function
35
+ (0, _astUtils.prepend)(this.programPath, this.plugin.skip(t.functionDeclaration(t.identifier(this.dummyFunctionName), [], t.blockStatement([]))));
36
+ }
37
+ }, {
38
+ key: "generateTrueExpression",
39
+ value: function generateTrueExpression(path) {
40
+ return t.unaryExpression("!", this.generateFalseExpression(path));
41
+ }
42
+ }, {
43
+ key: "generateFalseExpression",
44
+ value: function generateFalseExpression(path) {
45
+ this.programPath = path.find(function (p) {
46
+ return p.isProgram();
47
+ });
48
+ this.ensureCreated();
49
+
50
+ // Overcomplicated way to get a random property name that doesn't exist on the Function
51
+ var randomProperty;
52
+ var nameGen = new _NameGen.NameGen("randomized");
53
+ function PrototypeCollision() {}
54
+ PrototypeCollision(); // Call it for code coverage :D
55
+
56
+ do {
57
+ randomProperty = nameGen.generate();
58
+ } while (!randomProperty || PrototypeCollision[randomProperty] !== undefined);
59
+ return this.plugin.skip(new _template["default"]("\"".concat(randomProperty, "\" in ").concat(this.dummyFunctionName)).expression());
60
+ }
61
+ }]);
62
+ }();
@@ -303,16 +303,29 @@ function prepend(path) {
303
303
  // Preserve import declarations
304
304
  // Filter out import declarations
305
305
  var _body = listParent.get("body");
306
- var lastImportIndex = _body.findIndex(function (path) {
307
- return !path.isImportDeclaration();
308
- });
309
- if (lastImportIndex === 0 || lastImportIndex === -1) {
310
- // No non-import declarations, so we can safely unshift everything
306
+ var afterImport = 0;
307
+ var _iterator4 = _createForOfIteratorHelper(_body),
308
+ _step4;
309
+ try {
310
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
311
+ var stmt = _step4.value;
312
+ if (!stmt.isImportDeclaration()) {
313
+ break;
314
+ }
315
+ afterImport++;
316
+ }
317
+ } catch (err) {
318
+ _iterator4.e(err);
319
+ } finally {
320
+ _iterator4.f();
321
+ }
322
+ if (afterImport === 0) {
323
+ // No import declarations, so we can safely unshift everything
311
324
  return registerPaths(listParent.unshiftContainer("body", nodes));
312
- } else {
313
- // Insert the nodes after the last import declaration
314
- return registerPaths(_body[lastImportIndex - 1].insertAfter(nodes));
315
325
  }
326
+
327
+ // Insert the nodes after the last import declaration
328
+ return registerPaths(_body[afterImport - 1].insertAfter(nodes));
316
329
  }
317
330
  if (listParent.isFunction()) {
318
331
  var body = listParent.get("body");
@@ -326,7 +339,8 @@ function prepend(path) {
326
339
  }
327
340
  if (listParent.isBlock()) {
328
341
  return registerPaths(listParent.unshiftContainer("body", nodes));
329
- } else if (listParent.isSwitchCase()) {
342
+ }
343
+ if (listParent.isSwitchCase()) {
330
344
  return registerPaths(listParent.unshiftContainer("consequent", nodes));
331
345
  }
332
346
  (0, _assert.ok)(false);
@@ -336,6 +350,7 @@ function prependProgram(path) {
336
350
  return p.isProgram();
337
351
  });
338
352
  (0, _assert.ok)(program);
353
+ (0, _assert.ok)(program.isProgram());
339
354
  for (var _len3 = arguments.length, nodes = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
340
355
  nodes[_key3 - 1] = arguments[_key3];
341
356
  }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.chance = chance;
7
7
  exports.choice = choice;
8
8
  exports.getRandom = getRandom;
9
+ exports.getRandomChineseString = getRandomChineseString;
9
10
  exports.getRandomHexString = getRandomHexString;
10
11
  exports.getRandomInteger = getRandomInteger;
11
12
  exports.getRandomString = getRandomString;
@@ -60,6 +61,15 @@ function getRandomHexString(length) {
60
61
  }).join("").toUpperCase();
61
62
  }
62
63
 
64
+ /**
65
+ * @see https://github.com/MichaelXF/js-confuser/issues/150#issuecomment-2466159582
66
+ */
67
+ function getRandomChineseString(length) {
68
+ var characters = [];
69
+ for (var i = 0; i < length; i++) characters.push(String.fromCharCode(Math.floor(Math.random() * (0x9fff - 0x4e00)) + 0x4e00));
70
+ return characters.join("");
71
+ }
72
+
63
73
  /**
64
74
  * Returns a random string.
65
75
  */
@@ -102,7 +102,7 @@ function applyDefaultsToOptions(options) {
102
102
  options.globalVariables = new Set([]);
103
103
  if (options.target == "browser") {
104
104
  // browser
105
- ["window", "document", "postMessage", "alert", "confirm", "location", "btoa", "atob", "unescape", "encodeURIComponent"].forEach(function (x) {
105
+ ["window", "document", "postMessage", "alert", "confirm", "location"].forEach(function (x) {
106
106
  return options.globalVariables.add(x);
107
107
  });
108
108
  } else {
@@ -111,7 +111,7 @@ function applyDefaultsToOptions(options) {
111
111
  return options.globalVariables.add(x);
112
112
  });
113
113
  }
114
- ["globalThis", "console", "parseInt", "parseFloat", "Math", "JSON", "RegExp", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol", "TextDecoder", "TextEncoder", "Uint8Array", "Uint16Array", "Uint32Array", "ArrayBuffer"].forEach(function (x) {
114
+ ["globalThis", "console", "parseInt", "parseFloat", "Math", "JSON", "RegExp", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol", "TextDecoder", "TextEncoder", "Uint8Array", "Uint16Array", "Uint32Array", "Int8Array", "Int16Array", "Int32Array", "ArrayBuffer", "btoa", "atob", "unescape", "encodeURIComponent"].forEach(function (x) {
115
115
  return options.globalVariables.add(x);
116
116
  });
117
117
  }
package/index.d.ts CHANGED
@@ -1,3 +1,17 @@
1
- import JsConfuser from "./src";
1
+ // Export all the types from the index file
2
+ export * from "./src/index";
3
+ export { default } from "./src/index";
2
4
 
3
- export default JsConfuser;
5
+ // Export useful types
6
+ export type {
7
+ ObfuscateOptions,
8
+ ProbabilityMap,
9
+ CustomLock,
10
+ CustomStringEncoding,
11
+ } from "./src/options";
12
+ export type {
13
+ ObfuscationResult,
14
+ ProfileData,
15
+ ProfilerCallback,
16
+ ProfilerLog,
17
+ } from "./src/obfuscationResult";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.4",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "@babel/parser": "^7.25.6",
27
27
  "@babel/traverse": "^7.25.6",
28
28
  "@babel/types": "^7.25.6",
29
- "pako": "^2.1.0"
29
+ "lz-string": "^1.5.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@babel/cli": "^7.24.8",
package/src/constants.ts CHANGED
@@ -1,5 +1,3 @@
1
- import ControlObject from "./utils/ControlObject";
2
-
3
1
  export const predictableFunctionTag = "__JS_PREDICT__";
4
2
 
5
3
  /**
@@ -31,8 +29,6 @@ export const SKIP = Symbol("skip");
31
29
  */
32
30
  export const FN_LENGTH = Symbol("fnLength");
33
31
 
34
- export const CONTROL_OBJECTS = Symbol("controlObjects");
35
-
36
32
  export const NO_RENAME = Symbol("noRename");
37
33
 
38
34
  /**
@@ -58,6 +54,11 @@ export const MULTI_TRANSFORM = Symbol("multiTransform");
58
54
  */
59
55
  export const WITH_STATEMENT = Symbol("withStatement");
60
56
 
57
+ /**
58
+ * Tells minify to not remove the node.
59
+ */
60
+ export const NO_REMOVE = Symbol("noRemove");
61
+
61
62
  /**
62
63
  * Symbols describe precomputed semantics of a node, allowing the obfuscator to make the best choices for the node.
63
64
  */
@@ -66,12 +67,12 @@ export interface NodeSymbol {
66
67
  [PREDICTABLE]?: boolean;
67
68
  [SKIP]?: boolean | number;
68
69
  [FN_LENGTH]?: number;
69
- [CONTROL_OBJECTS]?: ControlObject[];
70
70
  [NO_RENAME]?: string | number;
71
71
 
72
72
  [GEN_NODE]?: boolean;
73
73
  [MULTI_TRANSFORM]?: boolean;
74
74
  [WITH_STATEMENT]?: boolean;
75
+ [NO_REMOVE]?: boolean;
75
76
  }
76
77
 
77
78
  /**
@@ -94,6 +95,15 @@ export const reservedIdentifiers = new Set([
94
95
  "arguments",
95
96
  ]);
96
97
 
98
+ /**
99
+ * Reserved Node.JS module identifiers.
100
+ */
101
+ export const reservedNodeModuleIdentifiers = new Set([
102
+ "module",
103
+ "exports",
104
+ "require",
105
+ ]);
106
+
97
107
  export const reservedObjectPrototype = new Set([
98
108
  "toString",
99
109
  "valueOf",
package/src/index.ts CHANGED
@@ -32,10 +32,16 @@ export async function obfuscateWithProfiler(
32
32
  sourceCode: string,
33
33
  options: ObfuscateOptions,
34
34
  profiler: {
35
- callback: ProfilerCallback;
36
- performance: { now(): number };
37
- }
35
+ callback?: ProfilerCallback;
36
+ performance?: { now(): number };
37
+ } = {}
38
38
  ): Promise<ObfuscationResult & { profileData: ProfileData }> {
39
+ if (!profiler.performance) {
40
+ profiler.performance = {
41
+ now: () => Date.now(),
42
+ };
43
+ }
44
+
39
45
  const startTime = performance.now();
40
46
 
41
47
  const obfuscator = new Obfuscator(options);
@@ -54,12 +60,14 @@ export async function obfuscateWithProfiler(
54
60
  ast = obfuscator.obfuscateAST(ast, {
55
61
  profiler: (log: ProfilerLog) => {
56
62
  var nowTime = performance.now();
57
- transformMap[log.currentTransform] = {
63
+ let entry = {
58
64
  transformTime: nowTime - currentTransformTime,
59
65
  changeData: {},
60
66
  };
67
+
68
+ transformMap[log.currentTransform] = entry;
61
69
  currentTransformTime = nowTime;
62
- profiler.callback(log);
70
+ profiler.callback?.(log, entry, ast);
63
71
  },
64
72
  });
65
73
 
@@ -96,8 +104,10 @@ const JsConfuser = {
96
104
  obfuscate,
97
105
  obfuscateAST,
98
106
  obfuscateWithProfiler,
107
+ Obfuscator,
99
108
  presets,
100
109
  Template,
101
110
  };
102
111
 
103
112
  export default JsConfuser;
113
+ export { Obfuscator, presets, Template };
@@ -1,4 +1,5 @@
1
1
  import { PluginInstance } from "./transforms/plugin";
2
+ import { File } from "@babel/types";
2
3
 
3
4
  /**
4
5
  * Obfuscation result object.
@@ -23,6 +24,7 @@ export interface ProfileData {
23
24
  [transformName: string]: {
24
25
  transformTime: number;
25
26
  changeData: PluginInstance["changeData"];
27
+ fileSize?: string;
26
28
  };
27
29
  };
28
30
  }
@@ -30,7 +32,11 @@ export interface ProfileData {
30
32
  /**
31
33
  * A callback function that is called when a transform is applied.
32
34
  */
33
- export type ProfilerCallback = (log: ProfilerLog) => void;
35
+ export type ProfilerCallback = (
36
+ log: ProfilerLog,
37
+ transformEntry?: object,
38
+ ast?: File
39
+ ) => void;
34
40
 
35
41
  /**
36
42
  * The current progress of the obfuscation process.