js-confuser 1.2.1 → 1.4.1

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 (94) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +7 -6
  3. package/dist/options.js +5 -1
  4. package/dist/parser.js +1 -2
  5. package/dist/presets.js +2 -2
  6. package/dist/transforms/calculator.js +48 -60
  7. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
  8. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
  9. package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
  10. package/dist/transforms/deadCode.js +1 -1
  11. package/dist/transforms/dispatcher.js +14 -13
  12. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
  13. package/dist/transforms/flatten.js +5 -1
  14. package/dist/transforms/hideInitializingCode.js +17 -2
  15. package/dist/transforms/identifier/globalConcealing.js +46 -25
  16. package/dist/transforms/identifier/movedDeclarations.js +69 -68
  17. package/dist/transforms/identifier/renameVariables.js +22 -98
  18. package/dist/transforms/identifier/variableAnalysis.js +133 -0
  19. package/dist/transforms/label.js +11 -2
  20. package/dist/transforms/lock/antiDebug.js +32 -13
  21. package/dist/transforms/lock/lock.js +13 -2
  22. package/dist/transforms/minify.js +117 -120
  23. package/dist/transforms/opaquePredicates.js +4 -2
  24. package/dist/transforms/preparation/preparation.js +8 -0
  25. package/dist/transforms/renameLabels.js +17 -3
  26. package/dist/transforms/rgf.js +8 -3
  27. package/dist/transforms/shuffle.js +25 -9
  28. package/dist/transforms/stack.js +5 -9
  29. package/dist/transforms/string/encoding.js +209 -0
  30. package/dist/transforms/string/stringCompression.js +10 -10
  31. package/dist/transforms/string/stringConcealing.js +94 -65
  32. package/dist/transforms/string/stringSplitting.js +7 -7
  33. package/dist/transforms/transform.js +10 -0
  34. package/dist/traverse.js +1 -35
  35. package/dist/util/gen.js +3 -1
  36. package/dist/util/identifiers.js +9 -19
  37. package/dist/util/insert.js +6 -40
  38. package/dist/util/scope.js +17 -0
  39. package/package.json +2 -2
  40. package/src/options.ts +19 -3
  41. package/src/parser.ts +1 -2
  42. package/src/presets.ts +2 -2
  43. package/src/transforms/calculator.ts +87 -91
  44. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
  45. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
  46. package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
  47. package/src/transforms/deadCode.ts +8 -0
  48. package/src/transforms/dispatcher.ts +29 -14
  49. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
  50. package/src/transforms/flatten.ts +15 -2
  51. package/src/transforms/hideInitializingCode.ts +432 -406
  52. package/src/transforms/identifier/globalConcealing.ts +148 -46
  53. package/src/transforms/identifier/movedDeclarations.ts +78 -101
  54. package/src/transforms/identifier/renameVariables.ts +21 -96
  55. package/src/transforms/identifier/variableAnalysis.ts +124 -0
  56. package/src/transforms/label.ts +20 -2
  57. package/src/transforms/lock/antiDebug.ts +69 -26
  58. package/src/transforms/lock/lock.ts +37 -3
  59. package/src/transforms/minify.ts +154 -130
  60. package/src/transforms/opaquePredicates.ts +25 -3
  61. package/src/transforms/preparation/preparation.ts +8 -1
  62. package/src/transforms/renameLabels.ts +26 -3
  63. package/src/transforms/rgf.ts +6 -1
  64. package/src/transforms/shuffle.ts +87 -29
  65. package/src/transforms/stack.ts +6 -8
  66. package/src/transforms/string/encoding.ts +310 -0
  67. package/src/transforms/string/stringCompression.ts +37 -24
  68. package/src/transforms/string/stringConcealing.ts +157 -160
  69. package/src/transforms/string/stringSplitting.ts +12 -8
  70. package/src/transforms/transform.ts +15 -2
  71. package/src/traverse.ts +1 -31
  72. package/src/util/gen.ts +5 -3
  73. package/src/util/identifiers.ts +20 -20
  74. package/src/util/insert.ts +12 -78
  75. package/src/util/scope.ts +9 -0
  76. package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
  77. package/test/index.test.ts +109 -1
  78. package/test/templates/template.test.ts +14 -0
  79. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
  80. package/test/transforms/dispatcher.test.ts +30 -0
  81. package/test/transforms/flatten.test.ts +28 -0
  82. package/test/transforms/hideInitializingCode.test.ts +336 -336
  83. package/test/transforms/identifier/globalConcealing.test.ts +1 -2
  84. package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
  85. package/test/transforms/identifier/renameVariables.test.ts +124 -13
  86. package/test/transforms/lock/antiDebug.test.ts +43 -0
  87. package/test/transforms/lock/selfDefending.test.ts +68 -0
  88. package/test/transforms/minify.test.ts +137 -0
  89. package/test/transforms/renameLabels.test.ts +33 -0
  90. package/test/transforms/rgf.test.ts +29 -0
  91. package/test/transforms/string/stringSplitting.test.ts +33 -0
  92. package/test/util/identifiers.test.ts +105 -17
  93. package/dist/util/expr.js +0 -60
  94. package/src/util/expr.ts +0 -56
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.VariableAnalysis = void 0;
6
+ exports.default = void 0;
7
7
 
8
8
  var _assert = require("assert");
9
9
 
@@ -15,107 +15,23 @@ var _identifiers = require("../../util/identifiers");
15
15
 
16
16
  var _insert = require("../../util/insert");
17
17
 
18
- var _compare = require("../../util/compare");
19
-
20
18
  var _transform = _interopRequireDefault(require("../transform"));
21
19
 
22
20
  var _constants = require("../../constants");
23
21
 
24
22
  var _probability = require("../../probability");
25
23
 
24
+ var _variableAnalysis = _interopRequireDefault(require("./variableAnalysis"));
25
+
26
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
27
 
28
28
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
29
29
 
30
- /**
31
- * Keeps track of what identifiers are defined and referenced in each context.
32
- */
33
- class VariableAnalysis extends _transform.default {
34
- /**
35
- * Node being the context.
36
- */
37
- constructor(o) {
38
- super(o);
39
-
40
- _defineProperty(this, "defined", void 0);
41
-
42
- _defineProperty(this, "references", void 0);
43
-
44
- this.defined = new Map();
45
- this.references = new Map();
46
- }
47
-
48
- match(object, parents) {
49
- return (0, _insert.isContext)(object);
50
- }
51
-
52
- transform(object, parents) {
53
- (0, _traverse.walk)(object, parents, (o, p) => {
54
- if (o.type == "Identifier") {
55
- var name = o.name;
56
- (0, _assert.ok)(typeof name === "string");
57
-
58
- if (!(0, _compare.isValidIdentifier)(name)) {
59
- return;
60
- }
61
-
62
- if (_constants.reservedIdentifiers.has(name)) {
63
- return;
64
- }
65
-
66
- if (this.options.globalVariables.has(name)) {
67
- return;
68
- }
69
-
70
- var info = (0, _identifiers.getIdentifierInfo)(o, p);
71
-
72
- if (!info.spec.isReferenced) {
73
- return;
74
- }
75
-
76
- if (info.spec.isExported) {
77
- return;
78
- }
79
-
80
- var definingContexts = info.spec.isDefined ? [(0, _insert.getDefiningContext)(o, p)] : [(0, _insert.getVarContext)(o, p), (0, _insert.getLexContext)(o, p)];
81
- (0, _assert.ok)(definingContexts.length);
82
- var isDefined = info.spec.isDefined;
83
- definingContexts.forEach(definingContext => {
84
- (0, _assert.ok)((0, _insert.isContext)(definingContext), "".concat(definingContext.type, " is not a context"));
85
-
86
- if (isDefined) {
87
- // Add to defined Map
88
- if (!this.defined.has(definingContext)) {
89
- this.defined.set(definingContext, new Set());
90
- }
91
-
92
- this.defined.get(definingContext).add(name);
93
- this.references.has(definingContext) && this.references.get(definingContext).delete(name);
94
- } else {
95
- // Add to references Map
96
- if (!this.defined.has(definingContext) || !this.defined.get(definingContext).has(name)) {
97
- if (!this.references.has(definingContext)) {
98
- this.references.set(definingContext, new Set());
99
- }
100
-
101
- this.references.get(definingContext).add(name);
102
- }
103
- }
104
- });
105
- }
106
- });
107
- }
108
-
109
- }
110
30
  /**
111
31
  * Rename variables to randomly generated names.
112
32
  *
113
33
  * - Attempts to re-use already generated names in nested scopes.
114
34
  */
115
-
116
-
117
- exports.VariableAnalysis = VariableAnalysis;
118
-
119
35
  class RenameVariables extends _transform.default {
120
36
  // Generator object
121
37
  // Names already used
@@ -133,7 +49,8 @@ class RenameVariables extends _transform.default {
133
49
  _defineProperty(this, "variableAnalysis", void 0);
134
50
 
135
51
  this.changed = new Map();
136
- this.before.push(this.variableAnalysis = new VariableAnalysis(o));
52
+ this.variableAnalysis = new _variableAnalysis.default(o);
53
+ this.before.push(this.variableAnalysis);
137
54
  this.gen = this.getGenerator();
138
55
  this.generated = [];
139
56
  }
@@ -195,16 +112,23 @@ class RenameVariables extends _transform.default {
195
112
 
196
113
  defined.forEach(name => {
197
114
  if ((isGlobal && !name.startsWith("__p_") ? (0, _probability.ComputeProbabilityMap)(this.options.renameGlobals, x => x, name) : true) && (0, _probability.ComputeProbabilityMap)(this.options.renameVariables, x => x, name, isGlobal)) {
198
- if (possible.size) {
199
- var first = possible.values().next().value;
200
- possible.delete(first);
201
- newNames[name] = first;
202
- } else {
203
- // Fix 1. Use `generateIdentifier` over `gen.generate()` so Integrity can get unique variable names
204
- var g = this.generateIdentifier();
205
- newNames[name] = g;
206
- this.generated.push(g);
207
- }
115
+ // Fix 2. Ensure global names aren't overridden
116
+ var newName;
117
+
118
+ do {
119
+ if (possible.size) {
120
+ var first = possible.values().next().value;
121
+ possible.delete(first);
122
+ newName = first;
123
+ } else {
124
+ // Fix 1. Use `generateIdentifier` over `gen.generate()` so Integrity can get unique variable names
125
+ var g = this.generateIdentifier();
126
+ newName = g;
127
+ this.generated.push(g);
128
+ }
129
+ } while (this.variableAnalysis.globals.has(newName));
130
+
131
+ newNames[name] = newName;
208
132
  } else {
209
133
  newNames[name] = name;
210
134
  }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _assert = require("assert");
9
+
10
+ var _constants = require("../../constants");
11
+
12
+ var _traverse = require("../../traverse");
13
+
14
+ var _compare = require("../../util/compare");
15
+
16
+ var _identifiers = require("../../util/identifiers");
17
+
18
+ var _insert = require("../../util/insert");
19
+
20
+ var _transform = _interopRequireDefault(require("../transform"));
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
25
+
26
+ /**
27
+ * Keeps track of what identifiers are defined and referenced in each context.
28
+ */
29
+ class VariableAnalysis extends _transform.default {
30
+ /**
31
+ * Node being the context.
32
+ */
33
+
34
+ /**
35
+ * Context->Nodes referenced (does not include nested)
36
+ */
37
+
38
+ /**
39
+ * Set of global identifiers to never be redefined
40
+ */
41
+
42
+ /**
43
+ * Set of identifers that are defined within the program
44
+ */
45
+ constructor(o) {
46
+ super(o);
47
+
48
+ _defineProperty(this, "defined", void 0);
49
+
50
+ _defineProperty(this, "references", void 0);
51
+
52
+ _defineProperty(this, "globals", void 0);
53
+
54
+ _defineProperty(this, "notGlobals", void 0);
55
+
56
+ this.defined = new Map();
57
+ this.references = new Map();
58
+ this.globals = new Set();
59
+ this.notGlobals = new Set();
60
+ }
61
+
62
+ match(object, parents) {
63
+ return (0, _insert.isContext)(object);
64
+ }
65
+
66
+ transform(object, parents) {
67
+ (0, _traverse.walk)(object, parents, (o, p) => {
68
+ if (o.type == "Identifier") {
69
+ var name = o.name;
70
+ (0, _assert.ok)(typeof name === "string");
71
+
72
+ if (!(0, _compare.isValidIdentifier)(name)) {
73
+ return;
74
+ }
75
+
76
+ if (_constants.reservedIdentifiers.has(name)) {
77
+ return;
78
+ }
79
+
80
+ if (this.options.globalVariables.has(name)) {
81
+ return;
82
+ }
83
+
84
+ var info = (0, _identifiers.getIdentifierInfo)(o, p);
85
+
86
+ if (!info.spec.isReferenced) {
87
+ return;
88
+ }
89
+
90
+ if (info.spec.isExported) {
91
+ return;
92
+ }
93
+
94
+ var isDefined = info.spec.isDefined; // Keep track of defined names within the program
95
+
96
+ if (isDefined) {
97
+ this.notGlobals.add(o.name);
98
+ this.globals.delete(o.name);
99
+ } else if (!this.notGlobals.has(o.name)) {
100
+ this.globals.add(o.name);
101
+ }
102
+
103
+ var definingContexts = info.spec.isDefined ? [(0, _insert.getDefiningContext)(o, p)] : (0, _insert.getReferencingContexts)(o, p, info);
104
+ (0, _assert.ok)(definingContexts.length);
105
+ definingContexts.forEach(definingContext => {
106
+ (0, _assert.ok)((0, _insert.isContext)(definingContext), "".concat(definingContext.type, " is not a context"));
107
+
108
+ if (isDefined) {
109
+ // Add to defined Map
110
+ if (!this.defined.has(definingContext)) {
111
+ this.defined.set(definingContext, new Set());
112
+ }
113
+
114
+ this.defined.get(definingContext).add(name);
115
+ this.references.has(definingContext) && this.references.get(definingContext).delete(name);
116
+ } else {
117
+ // Add to references Map
118
+ if (!this.defined.has(definingContext) || !this.defined.get(definingContext).has(name)) {
119
+ if (!this.references.has(definingContext)) {
120
+ this.references.set(definingContext, new Set());
121
+ }
122
+
123
+ this.references.get(definingContext).add(name);
124
+ }
125
+ }
126
+ });
127
+ }
128
+ });
129
+ }
130
+
131
+ }
132
+
133
+ exports.default = VariableAnalysis;
@@ -27,7 +27,7 @@ class Label extends _transform.default {
27
27
  }
28
28
 
29
29
  match(object, parents) {
30
- return (0, _compare.isLoop)(object);
30
+ return (0, _compare.isLoop)(object) || object.type == "BlockStatement" && parents[0] && parents[0].type == "LabeledStatement" && parents[0].body === object;
31
31
  }
32
32
 
33
33
  transform(object, parents) {
@@ -36,7 +36,16 @@ class Label extends _transform.default {
36
36
  var label = currentLabel || this.getPlaceholder();
37
37
  (0, _traverse.walk)(object, parents, (o, p) => {
38
38
  if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
39
- var loop = p.find(x => (0, _compare.isLoop)(x));
39
+ function isContinuableStatement(x) {
40
+ return (0, _compare.isLoop)(x) && x.type !== "SwitchStatement";
41
+ }
42
+
43
+ function isBreakableStatement(x) {
44
+ return (0, _compare.isLoop)(x) || o.label && x.type == "BlockStatement";
45
+ }
46
+
47
+ var fn = o.type == "ContinueStatement" ? isContinuableStatement : isBreakableStatement;
48
+ var loop = p.find(fn);
40
49
 
41
50
  if (object == loop) {
42
51
  if (!o.label) {
@@ -23,20 +23,31 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
23
23
 
24
24
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
25
25
 
26
- var DevToolsDetection = (0, _template.default)("\n function $jsc_debug(){\n var startTime = new Date();\n debugger;\n var endTime = new Date();\n var isDev = endTime-startTime > 600;\n \n while (isDev) {\n debugger;\n (function () {}). constructor (\"debugger\") ()\n }\n \n }\n try {\n if ( setInterval ) {\n setInterval(()=>{\n $jsc_debug();\n }, 4000);\n }\n } catch ( e ) {\n\n }\n \n");
26
+ var DevToolsDetection = (0, _template.default)("\n try {\n if ( setInterval ) {\n setInterval(()=>{\n {functionName}();\n }, 4000);\n }\n } catch ( e ) {\n\n }\n");
27
27
 
28
28
  class AntiDebug extends _transform.default {
29
- constructor(o) {
29
+ constructor(o, lock) {
30
30
  super(o, _order.ObfuscateOrder.Lock);
31
31
 
32
32
  _defineProperty(this, "made", void 0);
33
33
 
34
+ _defineProperty(this, "lock", void 0);
35
+
36
+ this.lock = lock;
34
37
  this.made = 0;
35
38
  }
36
39
 
37
40
  apply(tree) {
38
41
  super.apply(tree);
39
- tree.body.unshift(...DevToolsDetection.compile());
42
+ var fnName = this.getPlaceholder();
43
+ var startTimeName = this.getPlaceholder();
44
+ var endTimeName = this.getPlaceholder();
45
+ var isDevName = this.getPlaceholder();
46
+ var functionDeclaration = (0, _gen.FunctionDeclaration)(fnName, [], [...(0, _template.default)("\n var ".concat(startTimeName, " = new Date();\n debugger;\n var ").concat(endTimeName, " = new Date();\n var ").concat(isDevName, " = ").concat(endTimeName, "-").concat(startTimeName, " > 1000;\n ")).compile(), (0, _gen.IfStatement)((0, _gen.Identifier)(isDevName), this.options.lock.countermeasures ? this.lock.getCounterMeasuresCode() : [(0, _gen.WhileStatement)((0, _gen.Identifier)(isDevName), [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(startTimeName), (0, _gen.Identifier)(endTimeName)))])], null)]);
47
+ tree.body.unshift(...DevToolsDetection.compile({
48
+ functionName: fnName
49
+ }));
50
+ tree.body.push(functionDeclaration);
40
51
  }
41
52
 
42
53
  match(object, parents) {
@@ -44,17 +55,25 @@ class AntiDebug extends _transform.default {
44
55
  }
45
56
 
46
57
  transform(object, parents) {
47
- var body = (0, _insert.getBlockBody)(object.body);
48
- [...body].forEach(stmt => {
49
- if (Math.random() < 0.1 / (this.made || 1)) {
50
- var index = (0, _random.getRandomInteger)(0, body.length);
51
-
52
- if (body[index].type != "DebuggerStatement") {
53
- body.splice(index, 0, (0, _gen.DebuggerStatement)());
54
- this.made++;
58
+ return () => {
59
+ var body = (0, _insert.getBlockBody)(object.body);
60
+ [...body].forEach((stmt, i) => {
61
+ var addDebugger = Math.random() < 0.1 / (this.made || 1);
62
+
63
+ if (object.type == "Program" && i == 0) {
64
+ addDebugger = true;
65
+ }
66
+
67
+ if (addDebugger) {
68
+ var index = (0, _random.getRandomInteger)(0, body.length);
69
+
70
+ if (body[index].type != "DebuggerStatement") {
71
+ body.splice(index, 0, (0, _gen.DebuggerStatement)());
72
+ this.made++;
73
+ }
55
74
  }
56
- }
57
- });
75
+ });
76
+ };
58
77
  }
59
78
 
60
79
  }
@@ -62,7 +62,7 @@ class Lock extends _transform.default {
62
62
  }
63
63
 
64
64
  if (this.options.lock.antiDebug) {
65
- this.before.push(new _antiDebug.default(o));
65
+ this.before.push(new _antiDebug.default(o, this));
66
66
  }
67
67
 
68
68
  this.made = 0;
@@ -104,7 +104,7 @@ class Lock extends _transform.default {
104
104
  });
105
105
 
106
106
  if (!this.counterMeasuresNode) {
107
- throw new Error("Countermeasures function named '" + this.options.lock.countermeasures + "' was not found. Names found: " + Array.from(defined).slice(0, 100).join(", "));
107
+ throw new Error("Countermeasures function named '" + this.options.lock.countermeasures + "' was not found.");
108
108
  }
109
109
  }
110
110
 
@@ -204,6 +204,10 @@ class Lock extends _transform.default {
204
204
  choices.push("osLock");
205
205
  }
206
206
 
207
+ if (this.options.lock.selfDefending) {
208
+ choices.push("selfDefending");
209
+ }
210
+
207
211
  if (!choices.length) {
208
212
  return;
209
213
  }
@@ -231,6 +235,13 @@ class Lock extends _transform.default {
231
235
  var offset = 0;
232
236
 
233
237
  switch (type) {
238
+ case "selfDefending":
239
+ // A very simple mechanism inspired from https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/src/custom-code-helpers/self-defending/templates/SelfDefendingNoEvalTemplate.ts
240
+ // regExp checks for a newline, formatters add these
241
+ var callExpression = (0, _template.default)("\n (\n function(){\n // Breaks JSNice.org, beautifier.io\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n return test()\n }\n\n return namedFunction();\n }\n )()\n ").single().expression;
242
+ nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode() || [], null));
243
+ break;
244
+
234
245
  case "nativeFunction":
235
246
  var set = this.options.lock.nativeFunctions;
236
247