js-confuser 1.5.8 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
package/dist/traverse.js CHANGED
@@ -3,13 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.assertNoCircular = assertNoCircular;
6
7
  exports.default = traverse;
7
8
  exports.getBlock = getBlock;
8
9
  exports.isBlock = isBlock;
9
10
  exports.walk = walk;
10
11
 
11
- var _identifiers = require("./util/identifiers");
12
-
13
12
  /**
14
13
  * A block refers to any object that has a **`.body`** property where code is nested.
15
14
  *
@@ -40,21 +39,11 @@ function isBlock(object) {
40
39
  }
41
40
 
42
41
  function walk(object, parents, onEnter) {
43
- let seen = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : new Set();
44
-
45
42
  if (typeof object === "object" && object) {
46
- if (seen.has(object)) {
47
- console.log(object);
48
- throw new Error("Already seen: " + object.type);
49
- }
50
-
51
- seen.add(object);
52
- var newParents = [object, ...parents];
53
-
54
- if (!Array.isArray(object)) {
55
- (0, _identifiers.validateChain)(object, parents);
56
- } // 1. Call `onEnter` function and remember any onExit callback returned
57
-
43
+ var newParents = [object, ...parents]; // if (!Array.isArray(object)) {
44
+ // validateChain(object, parents);
45
+ // }
46
+ // 1. Call `onEnter` function and remember any onExit callback returned
58
47
 
59
48
  var onExit = onEnter(object, parents); // 2. Traverse children
60
49
 
@@ -66,8 +55,6 @@ function walk(object, parents, onEnter) {
66
55
  return "EXIT";
67
56
  }
68
57
  }
69
-
70
- copy.forEach(x => {});
71
58
  } else {
72
59
  var keys = Object.keys(object);
73
60
 
@@ -108,4 +95,23 @@ function walk(object, parents, onEnter) {
108
95
 
109
96
  function traverse(tree, onEnter) {
110
97
  walk(tree, [], onEnter);
98
+ }
99
+ /**
100
+ * This is debugging function used to test for circular references.
101
+ */
102
+
103
+
104
+ function assertNoCircular(object) {
105
+ var seen = new Set();
106
+ traverse(object, (node, nodeParents) => {
107
+ if (node && typeof node === "object") {
108
+ if (seen.has(node)) {
109
+ console.log(nodeParents);
110
+ console.log(node);
111
+ throw new Error("FOUND CIRCULAR REFERENCE");
112
+ }
113
+
114
+ seen.add(node);
115
+ }
116
+ });
111
117
  }
@@ -59,8 +59,8 @@ function isValidIdentifier(name) {
59
59
  return false;
60
60
  }
61
61
 
62
- var x = name.match(/^[A-z$_][A-z0-9$_]*/);
63
- return x && x[0] == name;
62
+ var x = name.match(/^[A-Za-z$_][A-Za-z0-9$_]*/);
63
+ return !!(x && x[0] == name);
64
64
  }
65
65
 
66
66
  function isInsideType(type, object, parents) {
package/dist/util/gen.js CHANGED
@@ -15,6 +15,7 @@ exports.BreakStatement = BreakStatement;
15
15
  exports.CallExpression = CallExpression;
16
16
  exports.CatchClause = CatchClause;
17
17
  exports.ClassDeclaration = ClassDeclaration;
18
+ exports.ClassExpression = ClassExpression;
18
19
  exports.ConditionalExpression = ConditionalExpression;
19
20
  exports.DebuggerStatement = DebuggerStatement;
20
21
  exports.ExpressionStatement = ExpressionStatement;
@@ -537,6 +538,20 @@ function ClassDeclaration(id) {
537
538
  };
538
539
  }
539
540
 
541
+ function ClassExpression(id) {
542
+ let superClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
543
+ let body = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
544
+ return {
545
+ type: "ClassExpression",
546
+ id: id,
547
+ superClass: superClass,
548
+ body: {
549
+ type: "ClassBody",
550
+ body: body
551
+ }
552
+ };
553
+ }
554
+
540
555
  function ThrowStatement(argument) {
541
556
  return {
542
557
  type: "ThrowStatement",
@@ -139,8 +139,12 @@ function getDefiningContext(o, p) {
139
139
  var variableDeclaration = p.find(x => x.type == "VariableDeclaration");
140
140
  (0, _assert.ok)(variableDeclaration);
141
141
 
142
- if (variableDeclaration.kind === "let") {
143
- return getLexContext(o, p);
142
+ if (variableDeclaration.kind === "let" || variableDeclaration.kind === "const") {
143
+ var context = getVarContext(o, p);
144
+
145
+ if (context && context.type === "Program") {
146
+ return getLexContext(o, p);
147
+ }
144
148
  }
145
149
  }
146
150
 
@@ -287,17 +291,33 @@ function prepend(block) {
287
291
  }
288
292
 
289
293
  if (block.type == "Program") {
290
- var decs = 0;
294
+ var moveBy = 0;
291
295
  block.body.forEach((stmt, i) => {
292
296
  if (stmt.type == "ImportDeclaration") {
293
- if (decs == i) {
294
- decs++;
297
+ if (moveBy == i) {
298
+ moveBy++;
299
+ }
300
+ }
301
+
302
+ if (stmt.type === "ExpressionStatement" && typeof stmt.directive === "string") {
303
+ if (moveBy == i) {
304
+ moveBy++;
295
305
  }
296
306
  }
297
307
  });
298
- block.body.splice(decs, 0, ...nodes);
308
+ block.body.splice(moveBy, 0, ...nodes);
309
+ } else if (block.type === "SwitchCase") {
310
+ block.consequent.unshift(...nodes);
299
311
  } else {
300
- getBlockBody(block).unshift(...nodes);
312
+ var bodyArray = getBlockBody(block); // Check for 'use strict'
313
+
314
+ if (bodyArray[0] && bodyArray[0].directive) {
315
+ // Insert under 'use strict' directive
316
+ bodyArray.splice(1, 0, ...nodes);
317
+ } else {
318
+ // Prepend at the top of the block
319
+ bodyArray.unshift(...nodes);
320
+ }
301
321
  }
302
322
  }
303
323
 
@@ -351,6 +371,10 @@ function isForInitialize(o, p) {
351
371
  (0, _identifiers.validateChain)(o, p);
352
372
  var forIndex = p.findIndex(x => x.type == "ForStatement" || x.type == "ForInStatement" || x.type == "ForOfStatement");
353
373
 
374
+ if (p.slice(0, forIndex).find(x => ["ArrowFunctionExpression", "BlockStatement"].includes(x.type))) {
375
+ return false;
376
+ }
377
+
354
378
  if (forIndex !== -1) {
355
379
  if (p[forIndex].type == "ForStatement") {
356
380
  if (p[forIndex].init == (p[forIndex - 1] || o)) {
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.alphabeticalGenerator = alphabeticalGenerator;
7
+ exports.chance = chance;
7
8
  exports.choice = choice;
8
9
  exports.getRandom = getRandom;
9
10
  exports.getRandomFalseExpression = getRandomFalseExpression;
@@ -17,10 +18,24 @@ var _assert = require("assert");
17
18
 
18
19
  var _gen = require("./gen");
19
20
 
21
+ /**
22
+ * Returns a random element from the given array
23
+ * @param choices Array of items
24
+ * @returns One of the items in the array at random
25
+ */
20
26
  function choice(choices) {
21
27
  var index = Math.floor(Math.random() * choices.length);
22
28
  return choices[index];
23
29
  }
30
+ /**
31
+ * Returns a true/false based on the percent chance (0%-100%)
32
+ * @param percentChance AS A PERCENTAGE 0 - 100%
33
+ */
34
+
35
+
36
+ function chance(percentChance) {
37
+ return Math.random() < percentChance / 100;
38
+ }
24
39
  /**
25
40
  * **Mutates the given array**
26
41
  * @param array
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "1.5.8",
3
+ "version": "1.6.0",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
8
  "dev": "node ./dev.js",
9
9
  "build": "./node_modules/.bin/babel src --out-dir dist --copy-files --extensions \".ts\"",
10
- "test": "jest",
10
+ "test": "jest --forceExit",
11
11
  "test:coverage": "jest --coverage",
12
- "prepublishOnly": "npm run build & npm run test"
12
+ "prepublishOnly": "npm run build & npm run test --forceExit"
13
13
  },
14
14
  "keywords": [
15
15
  "obfuscator",
@@ -36,7 +36,7 @@
36
36
  "@types/jest": "^26.0.24",
37
37
  "@types/node": "^15.14.9",
38
38
  "babel-jest": "^26.6.3",
39
- "jest": "^26.6.3"
39
+ "jest": "^29.5.0"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",
@@ -45,7 +45,7 @@
45
45
  "bugs": {
46
46
  "url": "https://github.com/MichaelXF/js-confuser/issues"
47
47
  },
48
- "homepage": "https://master--hungry-shannon-c1ce6b.netlify.app/",
48
+ "homepage": "https://js-confuser.com",
49
49
  "jest": {
50
50
  "coverageReporters": [
51
51
  "html"
package/src/index.ts CHANGED
@@ -85,8 +85,8 @@ var JsConfuser: IJsConfuser = async function (
85
85
  return result;
86
86
  } as any;
87
87
 
88
- export var debugTransformations: IJsConfuserDebugTransformations =
89
- async function debugTransformations(
88
+ export const debugTransformations: IJsConfuserDebugTransformations =
89
+ async function (
90
90
  code: string,
91
91
  options: ObfuscateOptions
92
92
  ): Promise<{ name: string; code: string; ms: number }[]> {
@@ -115,28 +115,66 @@ export var debugTransformations: IJsConfuserDebugTransformations =
115
115
  return frames;
116
116
  };
117
117
 
118
- export var debugObfuscation: IJsConfuserDebugObfuscation =
119
- async function debugTransformations(
120
- code: string,
121
- options: ObfuscateOptions,
122
- callback: (name: string, complete: number, totalTransforms: number) => void
123
- ): Promise<string> {
124
- validateOptions(options);
125
- options = await correctOptions(options);
118
+ /**
119
+ * This method is used by the obfuscator website to display a progress bar and additional information
120
+ * about the obfuscation.
121
+ *
122
+ * @param code - Source code to obfuscate
123
+ * @param options - Options
124
+ * @param callback - Progress callback, called after each transformation
125
+ * @returns
126
+ */
127
+ export const debugObfuscation: IJsConfuserDebugObfuscation = async function (
128
+ code: string,
129
+ options: ObfuscateOptions,
130
+ callback: (name: string, complete: number, totalTransforms: number) => void,
131
+ performance: Performance
132
+ ) {
133
+ const startTime = performance.now();
126
134
 
127
- var tree = parseSync(code);
128
- var obfuscator = new Obfuscator(options);
129
- var totalTransforms = obfuscator.array.length;
135
+ validateOptions(options);
136
+ options = await correctOptions(options);
130
137
 
131
- obfuscator.on("debug", (name: string, tree: Node, i: number) => {
132
- callback(name, i, totalTransforms);
133
- });
138
+ const beforeParseTime = performance.now();
134
139
 
135
- await obfuscator.apply(tree, true);
140
+ var tree = parseSync(code);
141
+
142
+ const parseTime = performance.now() - beforeParseTime;
143
+
144
+ var obfuscator = new Obfuscator(options);
145
+ var totalTransforms = obfuscator.array.length;
146
+
147
+ var transformationTimes = Object.create(null);
148
+ var currentTransformTime = performance.now();
149
+
150
+ obfuscator.on("debug", (name: string, tree: Node, i: number) => {
151
+ var nowTime = performance.now();
152
+ transformationTimes[name] = nowTime - currentTransformTime;
153
+ currentTransformTime = nowTime;
154
+
155
+ callback(name, i, totalTransforms);
156
+ });
157
+
158
+ await obfuscator.apply(tree, true);
159
+
160
+ const beforeCompileTime = performance.now();
161
+
162
+ var output = await compileJs(tree, options);
163
+
164
+ const compileTime = performance.now() - beforeCompileTime;
165
+
166
+ const endTime = performance.now();
136
167
 
137
- var output = compileJs(tree, options);
138
- return output;
168
+ return {
169
+ obfuscated: output,
170
+ transformationTimes: transformationTimes,
171
+ obfuscationTime: endTime - startTime,
172
+ parseTime: parseTime,
173
+ compileTime: compileTime,
174
+ totalTransforms: totalTransforms,
175
+ totalPossibleTransforms: obfuscator.totalPossibleTransforms,
139
176
  };
177
+ };
140
178
 
141
179
  JsConfuser.obfuscate = obfuscate;
142
180
  JsConfuser.obfuscateAST = obfuscateAST;
package/src/obfuscator.ts CHANGED
@@ -7,7 +7,7 @@ import { ProbabilityMap, isProbabilityMapProbable } from "./probability";
7
7
 
8
8
  import Transform from "./transforms/transform";
9
9
 
10
- import Preparation from "./transforms/preparation/preparation";
10
+ import Preparation from "./transforms/preparation";
11
11
  import ObjectExtraction from "./transforms/extraction/objectExtraction";
12
12
  import Lock from "./transforms/lock/lock";
13
13
  import Dispatcher from "./transforms/dispatcher";
@@ -17,8 +17,9 @@ import Calculator from "./transforms/calculator";
17
17
  import ControlFlowFlattening from "./transforms/controlFlowFlattening/controlFlowFlattening";
18
18
  import Eval from "./transforms/eval";
19
19
  import GlobalConcealing from "./transforms/identifier/globalConcealing";
20
- import StringConcealing from "./transforms/string/stringConcealing";
21
20
  import StringSplitting from "./transforms/string/stringSplitting";
21
+ import StringConcealing from "./transforms/string/stringConcealing";
22
+ import StringCompression from "./transforms/string/stringCompression";
22
23
  import DuplicateLiteralsRemoval from "./transforms/extraction/duplicateLiteralsRemoval";
23
24
  import Shuffle from "./transforms/shuffle";
24
25
  import MovedDeclarations from "./transforms/identifier/movedDeclarations";
@@ -26,15 +27,12 @@ import RenameVariables from "./transforms/identifier/renameVariables";
26
27
  import RenameLabels from "./transforms/renameLabels";
27
28
  import Minify from "./transforms/minify";
28
29
  import ES5 from "./transforms/es5/es5";
29
- import StringEncoding from "./transforms/string/stringEncoding";
30
30
  import RGF from "./transforms/rgf";
31
31
  import Flatten from "./transforms/flatten";
32
32
  import Stack from "./transforms/stack";
33
- import StringCompression from "./transforms/string/stringCompression";
34
33
  import NameRecycling from "./transforms/identifier/nameRecycling";
35
34
  import AntiTooling from "./transforms/antiTooling";
36
- import HideInitializingCode from "./transforms/hideInitializingCode";
37
- import HexadecimalNumbers from "./transforms/hexadecimalNumbers";
35
+ import Finalizer from "./transforms/finalizer";
38
36
 
39
37
  /**
40
38
  * The parent transformation holding the `state`.
@@ -47,17 +45,19 @@ export default class Obfuscator extends EventEmitter {
47
45
  state: "transform" | "eval" = "transform";
48
46
  generated: Set<string>;
49
47
 
48
+ totalPossibleTransforms: number;
49
+
50
50
  constructor(public options: ObfuscateOptions) {
51
51
  super();
52
52
 
53
53
  this.varCount = 0;
54
54
  this.transforms = Object.create(null);
55
55
  this.generated = new Set();
56
-
57
- this.push(new Preparation(this));
58
- this.push(new RenameLabels(this));
56
+ this.totalPossibleTransforms = 0;
59
57
 
60
58
  const test = <T>(map: ProbabilityMap<T>, ...transformers: any[]) => {
59
+ this.totalPossibleTransforms += transformers.length;
60
+
61
61
  if (isProbabilityMapProbable(map)) {
62
62
  // options.verbose && console.log("+ Added " + transformer.name);
63
63
 
@@ -68,36 +68,33 @@ export default class Obfuscator extends EventEmitter {
68
68
  };
69
69
 
70
70
  // Optimization: Only add needed transformers. If a probability always return false, no need in running that extra code.
71
- test(options.objectExtraction, ObjectExtraction);
72
- test(options.deadCode, DeadCode);
71
+ test(true, Preparation);
72
+ test(true, RenameLabels);
73
73
 
74
+ test(options.objectExtraction, ObjectExtraction);
75
+ test(options.flatten, Flatten);
76
+ test(options.rgf, RGF);
74
77
  test(options.dispatcher, Dispatcher);
78
+ test(options.deadCode, DeadCode);
79
+ test(options.calculator, Calculator);
75
80
  test(options.controlFlowFlattening, ControlFlowFlattening);
76
- test(options.globalConcealing, GlobalConcealing);
77
- test(options.stringCompression, StringCompression);
78
- test(options.stringConcealing, StringConcealing);
79
- test(options.stringEncoding, StringEncoding);
80
- test(options.stringSplitting, StringSplitting);
81
- test(options.renameVariables, RenameVariables);
82
- test(options.nameRecycling, NameRecycling);
83
-
84
81
  test(options.eval, Eval);
82
+ test(options.globalConcealing, GlobalConcealing);
85
83
  test(options.opaquePredicates, OpaquePredicates);
84
+ test(options.stringSplitting, StringSplitting);
85
+ test(options.stringConcealing, StringConcealing);
86
+ test(options.stringCompression, StringCompression);
87
+ test(options.stack, Stack);
86
88
  test(options.duplicateLiteralsRemoval, DuplicateLiteralsRemoval);
87
- test(options.minify, Minify);
88
-
89
- test(options.calculator, Calculator);
89
+ test(options.shuffle, Shuffle);
90
+ test(options.nameRecycling, NameRecycling);
90
91
  test(options.movedDeclarations, MovedDeclarations);
91
-
92
+ test(options.minify, Minify);
93
+ test(options.renameVariables, RenameVariables);
92
94
  test(options.es5, ES5);
93
- test(options.shuffle, Shuffle);
94
95
 
95
- test(options.flatten, Flatten);
96
- test(options.rgf, RGF);
97
- test(options.stack, Stack);
98
96
  test(true, AntiTooling);
99
- test(options.hideInitializingCode, HideInitializingCode);
100
- test(options.hexadecimalNumbers, HexadecimalNumbers);
97
+ test(true, Finalizer); // String Encoding, Hexadecimal Numbers, BigInt support is included
101
98
 
102
99
  if (
103
100
  options.lock &&
package/src/options.ts CHANGED
@@ -10,9 +10,9 @@ export interface ObfuscateOptions {
10
10
  *
11
11
  * | Preset | Transforms | Performance Reduction | Sample |
12
12
  * | --- | --- | --- | --- |
13
- * | High | 21/22 | 98% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/high.js) |
14
- * | Medium | 15/22 | 52% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/medium.js) |
15
- * | Low | 10/22 | 30% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/low.js) |
13
+ * | High | 22/25 | 98% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/high.js) |
14
+ * | Medium | 19/25 | 52% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/medium.js) |
15
+ * | Low | 15/25 | 30% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/low.js) |
16
16
  *
17
17
  * You can extend each preset or all go without them entirely. (`"high"/"medium"/"low"`)
18
18
  *
@@ -53,7 +53,7 @@ export interface ObfuscateOptions {
53
53
  /**
54
54
  * ### `hexadecimalNumbers`
55
55
  *
56
- * Uses the hexadecimal representation (`50` -> `0x32`) for numbers. (`true/false`)
56
+ * Uses the hexadecimal representation for numbers. (`true/false`)
57
57
  */
58
58
  hexadecimalNumbers?: boolean;
59
59
 
@@ -144,6 +144,8 @@ export interface ObfuscateOptions {
144
144
  /**
145
145
  * ### `nameRecycling`
146
146
  *
147
+ * (Experimental feature)
148
+ *
147
149
  * Attempts to reuse released names.
148
150
  *
149
151
  * - Potency Medium
@@ -189,19 +191,6 @@ export interface ObfuscateOptions {
189
191
  */
190
192
  controlFlowFlattening?: ProbabilityMap<boolean>;
191
193
 
192
- /**
193
- * ### `hideInitializingCode`
194
- *
195
- * Hides initializing code with complex ternary expressions. (`true/false`)
196
- *
197
- * - Potency High
198
- * - Resilience High
199
- * - Cost High
200
- *
201
- * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options)
202
- */
203
- hideInitializingCode?: ProbabilityMap<boolean>;
204
-
205
194
  /**
206
195
  * ### `globalConcealing`
207
196
  *
@@ -691,7 +680,6 @@ const validProperties = new Set([
691
680
  "identifierGenerator",
692
681
  "nameRecycling",
693
682
  "controlFlowFlattening",
694
- "hideInitializingCode",
695
683
  "globalConcealing",
696
684
  "stringCompression",
697
685
  "stringConcealing",
@@ -726,7 +714,7 @@ const validBrowsers = new Set([
726
714
  ]);
727
715
 
728
716
  export function validateOptions(options: ObfuscateOptions) {
729
- if (Object.keys(options).length <= 1) {
717
+ if (!options || Object.keys(options).length <= 1) {
730
718
  /**
731
719
  * Give a welcoming introduction to those who skipped the documentation.
732
720
  */
@@ -867,8 +855,7 @@ export async function correctOptions(
867
855
  options.compact = true; // self defending forcibly enables this
868
856
  }
869
857
 
870
- // options.globalVariables was never used.
871
- // GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified.
858
+ // options.globalVariables outlines generic globals that should be present in the execution context
872
859
  if (!options.hasOwnProperty("globalVariables")) {
873
860
  options.globalVariables = new Set([]);
874
861
 
@@ -908,6 +895,10 @@ export async function correctOptions(
908
895
  "Array",
909
896
  "Proxy",
910
897
  "Error",
898
+ "TypeError",
899
+ "ReferenceError",
900
+ "RangeError",
901
+ "EvalError",
911
902
  "setTimeout",
912
903
  "clearTimeout",
913
904
  "setInterval",
@@ -919,6 +910,11 @@ export async function correctOptions(
919
910
  "module",
920
911
  "isNaN",
921
912
  "isFinite",
913
+ "Set",
914
+ "Map",
915
+ "WeakSet",
916
+ "WeakMap",
917
+ "Symbol",
922
918
  ].forEach((x) => options.globalVariables.add(x));
923
919
  }
924
920
 
package/src/order.ts CHANGED
@@ -32,8 +32,6 @@ export enum ObfuscateOrder {
32
32
 
33
33
  StringCompression = 18,
34
34
 
35
- HideInitializingCode = 19,
36
-
37
35
  Stack = 20,
38
36
 
39
37
  DuplicateLiteralsRemoval = 22,
@@ -44,17 +42,15 @@ export enum ObfuscateOrder {
44
42
 
45
43
  MovedDeclarations = 26,
46
44
 
47
- RenameVariables = 27,
45
+ RenameLabels = 27,
48
46
 
49
- RenameLabels = 28,
47
+ Minify = 28,
50
48
 
51
- Minify = 30,
49
+ RenameVariables = 30,
52
50
 
53
51
  ES5 = 31,
54
52
 
55
- StringEncoding = 32,
56
-
57
53
  AntiTooling = 34,
58
54
 
59
- HexadecimalNumbers = 35,
55
+ Finalizer = 35,
60
56
  }
@@ -87,6 +87,8 @@ export function ComputeProbabilityMap<T>(
87
87
  * @param map
88
88
  */
89
89
  export function isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
90
+ ok(!Number.isNaN(map), "Numbers cannot be NaN");
91
+
90
92
  if (!map || typeof map === "undefined") {
91
93
  return false;
92
94
  }
@@ -97,9 +99,6 @@ export function isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
97
99
  if (map > 1 || map < 0) {
98
100
  throw new Error(`Numbers must be between 0 and 1 for 0% - 100%`);
99
101
  }
100
- if (isNaN(map)) {
101
- throw new Error("Numbers cannot be NaN");
102
- }
103
102
  }
104
103
  if (Array.isArray(map)) {
105
104
  ok(
@@ -0,0 +1,68 @@
1
+ import Template from "./template";
2
+
3
+ export const BufferToStringTemplate = Template(`
4
+ function __getGlobal(){
5
+ try {
6
+ return global||window|| ( new Function("return this") )();
7
+ } catch ( e ) {
8
+ try {
9
+ return this;
10
+ } catch ( e ) {
11
+ return {};
12
+ }
13
+ }
14
+ }
15
+
16
+ var __globalObject = __getGlobal() || {};
17
+ var __TextDecoder = __globalObject["TextDecoder"];
18
+ var __Uint8Array = __globalObject["Uint8Array"];
19
+ var __Buffer = __globalObject["Buffer"];
20
+ var __String = __globalObject["String"] || String;
21
+ var __Array = __globalObject["Array"] || Array;
22
+
23
+ var utf8ArrayToStr = (function () {
24
+ var charCache = new __Array(128); // Preallocate the cache for the common single byte chars
25
+ var charFromCodePt = __String["fromCodePoint"] || __String["fromCharCode"];
26
+ var result = [];
27
+
28
+ return function (array) {
29
+ var codePt, byte1;
30
+ var buffLen = array["length"];
31
+
32
+ result["length"] = 0;
33
+
34
+ for (var i = 0; i < buffLen;) {
35
+ byte1 = array[i++];
36
+
37
+ if (byte1 <= 0x7F) {
38
+ codePt = byte1;
39
+ } else if (byte1 <= 0xDF) {
40
+ codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);
41
+ } else if (byte1 <= 0xEF) {
42
+ codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
43
+ } else if (__String["fromCodePoint"]) {
44
+ codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
45
+ } else {
46
+ codePt = 63; // Cannot convert four byte code points, so use "?" instead
47
+ i += 3;
48
+ }
49
+
50
+ result["push"](charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt)));
51
+ }
52
+
53
+ return result["join"]('');
54
+ };
55
+ })();
56
+
57
+ function {name}(buffer){
58
+ if(typeof __TextDecoder !== "undefined" && __TextDecoder) {
59
+ return new __TextDecoder()["decode"](new __Uint8Array(buffer));
60
+ } else if(typeof __Buffer !== "undefined" && __Buffer) {
61
+ return __Buffer["from"](buffer)["toString"]("utf-8");
62
+ } else {
63
+ return utf8ArrayToStr(buffer);
64
+ }
65
+ }
66
+
67
+
68
+ `);