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
@@ -0,0 +1,124 @@
1
+ import { ok } from "assert";
2
+ import { reservedIdentifiers } from "../../constants";
3
+ import { walk } from "../../traverse";
4
+ import { isValidIdentifier } from "../../util/compare";
5
+ import { Node } from "../../util/gen";
6
+ import { getIdentifierInfo } from "../../util/identifiers";
7
+ import {
8
+ getDefiningContext,
9
+ getVarContext,
10
+ getLexContext,
11
+ isContext,
12
+ getReferencingContexts,
13
+ } from "../../util/insert";
14
+ import Transform from "../transform";
15
+
16
+ /**
17
+ * Keeps track of what identifiers are defined and referenced in each context.
18
+ */
19
+ export default class VariableAnalysis extends Transform {
20
+ /**
21
+ * Node being the context.
22
+ */
23
+ defined: Map<Node, Set<string>>;
24
+
25
+ /**
26
+ * Context->Nodes referenced (does not include nested)
27
+ */
28
+ references: Map<Node, Set<string>>;
29
+
30
+ /**
31
+ * Set of global identifiers to never be redefined
32
+ */
33
+ globals: Set<string>;
34
+
35
+ /**
36
+ * Set of identifers that are defined within the program
37
+ */
38
+ notGlobals: Set<string>;
39
+
40
+ constructor(o) {
41
+ super(o);
42
+
43
+ this.defined = new Map();
44
+ this.references = new Map();
45
+ this.globals = new Set();
46
+ this.notGlobals = new Set();
47
+ }
48
+
49
+ match(object, parents) {
50
+ return isContext(object);
51
+ }
52
+
53
+ transform(object, parents) {
54
+ walk(object, parents, (o, p) => {
55
+ if (o.type == "Identifier") {
56
+ var name = o.name;
57
+ ok(typeof name === "string");
58
+ if (!isValidIdentifier(name)) {
59
+ return;
60
+ }
61
+
62
+ if (reservedIdentifiers.has(name)) {
63
+ return;
64
+ }
65
+ if (this.options.globalVariables.has(name)) {
66
+ return;
67
+ }
68
+
69
+ var info = getIdentifierInfo(o, p);
70
+ if (!info.spec.isReferenced) {
71
+ return;
72
+ }
73
+
74
+ if (info.spec.isExported) {
75
+ return;
76
+ }
77
+
78
+ var isDefined = info.spec.isDefined;
79
+
80
+ // Keep track of defined names within the program
81
+ if (isDefined) {
82
+ this.notGlobals.add(o.name);
83
+ this.globals.delete(o.name);
84
+ } else if (!this.notGlobals.has(o.name)) {
85
+ this.globals.add(o.name);
86
+ }
87
+
88
+ var definingContexts = info.spec.isDefined
89
+ ? [getDefiningContext(o, p)]
90
+ : getReferencingContexts(o, p, info);
91
+
92
+ ok(definingContexts.length);
93
+
94
+ definingContexts.forEach((definingContext) => {
95
+ ok(
96
+ isContext(definingContext),
97
+ `${definingContext.type} is not a context`
98
+ );
99
+
100
+ if (isDefined) {
101
+ // Add to defined Map
102
+ if (!this.defined.has(definingContext)) {
103
+ this.defined.set(definingContext, new Set());
104
+ }
105
+ this.defined.get(definingContext).add(name);
106
+ this.references.has(definingContext) &&
107
+ this.references.get(definingContext).delete(name);
108
+ } else {
109
+ // Add to references Map
110
+ if (
111
+ !this.defined.has(definingContext) ||
112
+ !this.defined.get(definingContext).has(name)
113
+ ) {
114
+ if (!this.references.has(definingContext)) {
115
+ this.references.set(definingContext, new Set());
116
+ }
117
+ this.references.get(definingContext).add(name);
118
+ }
119
+ }
120
+ });
121
+ }
122
+ });
123
+ }
124
+ }
@@ -16,7 +16,13 @@ export default class Label extends Transform {
16
16
  }
17
17
 
18
18
  match(object, parents) {
19
- return isLoop(object);
19
+ return (
20
+ isLoop(object) ||
21
+ (object.type == "BlockStatement" &&
22
+ parents[0] &&
23
+ parents[0].type == "LabeledStatement" &&
24
+ parents[0].body === object)
25
+ );
20
26
  }
21
27
 
22
28
  transform(object, parents) {
@@ -28,7 +34,19 @@ export default class Label extends Transform {
28
34
 
29
35
  walk(object, parents, (o, p) => {
30
36
  if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
31
- var loop = p.find((x) => isLoop(x));
37
+ function isContinuableStatement(x) {
38
+ return isLoop(x) && x.type !== "SwitchStatement";
39
+ }
40
+ function isBreakableStatement(x) {
41
+ return isLoop(x) || (o.label && x.type == "BlockStatement");
42
+ }
43
+
44
+ var fn =
45
+ o.type == "ContinueStatement"
46
+ ? isContinuableStatement
47
+ : isBreakableStatement;
48
+
49
+ var loop = p.find(fn);
32
50
  if (object == loop) {
33
51
  if (!o.label) {
34
52
  o.label = Identifier(label);
@@ -1,51 +1,86 @@
1
1
  import { ObfuscateOrder } from "../../order";
2
2
  import Template from "../../templates/template";
3
3
  import { isBlock } from "../../traverse";
4
- import { DebuggerStatement } from "../../util/gen";
4
+ import {
5
+ AssignmentExpression,
6
+ DebuggerStatement,
7
+ ExpressionStatement,
8
+ FunctionDeclaration,
9
+ Identifier,
10
+ IfStatement,
11
+ Literal,
12
+ WhileStatement,
13
+ } from "../../util/gen";
5
14
  import { getBlockBody, prepend } from "../../util/insert";
6
15
  import { getRandomInteger } from "../../util/random";
7
16
  import Transform from "../transform";
17
+ import Lock from "./lock";
8
18
 
9
19
  var DevToolsDetection = Template(
10
20
  `
11
- function $jsc_debug(){
12
- var startTime = new Date();
13
- debugger;
14
- var endTime = new Date();
15
- var isDev = endTime-startTime > 600;
16
-
17
- while (isDev) {
18
- debugger;
19
- (function () {}). constructor ("debugger") ()
20
- }
21
-
22
- }
23
21
  try {
24
22
  if ( setInterval ) {
25
23
  setInterval(()=>{
26
- $jsc_debug();
24
+ {functionName}();
27
25
  }, 4000);
28
26
  }
29
27
  } catch ( e ) {
30
28
 
31
29
  }
32
-
33
30
  `
34
31
  );
35
32
 
36
33
  export default class AntiDebug extends Transform {
37
34
  made: number;
35
+ lock: Lock;
38
36
 
39
- constructor(o) {
37
+ constructor(o, lock) {
40
38
  super(o, ObfuscateOrder.Lock);
41
39
 
40
+ this.lock = lock;
42
41
  this.made = 0;
43
42
  }
44
43
 
45
44
  apply(tree) {
46
45
  super.apply(tree);
47
46
 
48
- tree.body.unshift(...DevToolsDetection.compile());
47
+ var fnName = this.getPlaceholder();
48
+ var startTimeName = this.getPlaceholder();
49
+ var endTimeName = this.getPlaceholder();
50
+ var isDevName = this.getPlaceholder();
51
+ var functionDeclaration = FunctionDeclaration(
52
+ fnName,
53
+ [],
54
+ [
55
+ ...Template(`
56
+ var ${startTimeName} = new Date();
57
+ debugger;
58
+ var ${endTimeName} = new Date();
59
+ var ${isDevName} = ${endTimeName}-${startTimeName} > 1000;
60
+ `).compile(),
61
+
62
+ IfStatement(
63
+ Identifier(isDevName),
64
+ this.options.lock.countermeasures
65
+ ? this.lock.getCounterMeasuresCode()
66
+ : [
67
+ WhileStatement(Identifier(isDevName), [
68
+ ExpressionStatement(
69
+ AssignmentExpression(
70
+ "=",
71
+ Identifier(startTimeName),
72
+ Identifier(endTimeName)
73
+ )
74
+ ),
75
+ ]),
76
+ ],
77
+ null
78
+ ),
79
+ ]
80
+ );
81
+
82
+ tree.body.unshift(...DevToolsDetection.compile({ functionName: fnName }));
83
+ tree.body.push(functionDeclaration);
49
84
  }
50
85
 
51
86
  match(object, parents) {
@@ -53,17 +88,25 @@ export default class AntiDebug extends Transform {
53
88
  }
54
89
 
55
90
  transform(object, parents) {
56
- var body = getBlockBody(object.body);
91
+ return () => {
92
+ var body = getBlockBody(object.body);
93
+
94
+ [...body].forEach((stmt, i) => {
95
+ var addDebugger = Math.random() < 0.1 / (this.made || 1);
96
+
97
+ if (object.type == "Program" && i == 0) {
98
+ addDebugger = true;
99
+ }
57
100
 
58
- [...body].forEach((stmt) => {
59
- if (Math.random() < 0.1 / (this.made || 1)) {
60
- var index = getRandomInteger(0, body.length);
61
- if (body[index].type != "DebuggerStatement") {
62
- body.splice(index, 0, DebuggerStatement());
101
+ if (addDebugger) {
102
+ var index = getRandomInteger(0, body.length);
103
+ if (body[index].type != "DebuggerStatement") {
104
+ body.splice(index, 0, DebuggerStatement());
63
105
 
64
- this.made++;
106
+ this.made++;
107
+ }
65
108
  }
66
- }
67
- });
109
+ });
110
+ };
68
111
  }
69
112
  }
@@ -62,7 +62,7 @@ export default class Lock extends Transform {
62
62
  }
63
63
 
64
64
  if (this.options.lock.antiDebug) {
65
- this.before.push(new AntiDebug(o));
65
+ this.before.push(new AntiDebug(o, this));
66
66
  }
67
67
 
68
68
  this.made = 0;
@@ -112,8 +112,7 @@ export default class Lock extends Transform {
112
112
  throw new Error(
113
113
  "Countermeasures function named '" +
114
114
  this.options.lock.countermeasures +
115
- "' was not found. Names found: " +
116
- Array.from(defined).slice(0, 100).join(", ")
115
+ "' was not found."
117
116
  );
118
117
  }
119
118
  }
@@ -215,6 +214,9 @@ export default class Lock extends Transform {
215
214
  if (this.options.lock.osLock && this.options.lock.osLock.length) {
216
215
  choices.push("osLock");
217
216
  }
217
+ if (this.options.lock.selfDefending) {
218
+ choices.push("selfDefending");
219
+ }
218
220
 
219
221
  if (!choices.length) {
220
222
  return;
@@ -261,6 +263,38 @@ export default class Lock extends Transform {
261
263
  var offset = 0;
262
264
 
263
265
  switch (type) {
266
+ case "selfDefending":
267
+ // A very simple mechanism inspired from https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/src/custom-code-helpers/self-defending/templates/SelfDefendingNoEvalTemplate.ts
268
+ // regExp checks for a newline, formatters add these
269
+ var callExpression = Template(
270
+ `
271
+ (
272
+ function(){
273
+ // Breaks JSNice.org, beautifier.io
274
+ var namedFunction = function(){
275
+ const test = function(){
276
+ const regExp=new RegExp('\\n');
277
+ return regExp['test'](namedFunction)
278
+ };
279
+ return test()
280
+ }
281
+
282
+ return namedFunction();
283
+ }
284
+ )()
285
+ `
286
+ ).single().expression;
287
+
288
+ nodes.push(
289
+ IfStatement(
290
+ callExpression,
291
+ this.getCounterMeasuresCode() || [],
292
+ null
293
+ )
294
+ );
295
+
296
+ break;
297
+
264
298
  case "nativeFunction":
265
299
  var set = this.options.lock.nativeFunctions;
266
300
  if (set === true) {